Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.144.233.150] |
|
Сообщ.
#1
,
|
|
|
Пытаюсь запустить UDP клиент и сервер под нагрузкой. Для этого я гоняю туда сюда пакетик размером 516 байт.
Приблизительно на 10-ой итерации клиентского цикла, в сервере, в функции recvfrom возникает ошибка 10054: Цитата An existing connection was forcibly closed by the remote host. Подскажите как ее избежать? // КЛИЕНТ #include <winsock2.h> #include <windows.h> #include <stdio.h> #include <ctime> #include "../test_packet.h" #pragma comment(lib, "ws2_32.lib") const int iPackets = 400; int main(int argc, char *argv[]) { WSADATA wsa; if(WSAStartup(0x202, &wsa)!=0) { printf("ERROR: WSAStartup failed\n"); return 0; } int Sock = socket(AF_INET, SOCK_DGRAM, 0); if (Sock < 0) { printf("ERROR: Create socket failed\n"); return 0; } struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); char time[10]; _strtime_s(time); printf("Start client: %s\n", time); printf("%d packets\n", iPackets); for(int i = 0; i < iPackets; i++) { sendto(Sock, TEST_PACKET, TEST_PACKET_SIZE, 0, (sockaddr *)&addr, sizeof(addr)); } closesocket(Sock); } // СЕРВЕР #include <winsock2.h> #include <windows.h> #include <stdio.h> #include <ctime> #include "../test_packet.h" #pragma comment(lib, "ws2_32.lib") int main(int argc, char *argv[]) { WSADATA wsa; if(WSAStartup(0x202, &wsa)!=0) { printf("ERROR: WSAStartup failed\n"); return 0; } int Sock = socket(AF_INET, SOCK_DGRAM, 0); if (Sock < 0) { printf("ERROR: Create socket failed\n"); return 0; } struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(Sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { printf("ERROR: Bind failed\n"); closesocket(Sock); return 0; } char time[10]; _strtime_s(time); printf("Start server: %s\n", time); while (true) { sockaddr_in client_addr; int client_addr_size = sizeof(client_addr); char buff[1024]; int bytes_read = recvfrom(Sock, buff, sizeof(buff) - 1, 0, (sockaddr*)&client_addr, &client_addr_size); if (bytes_read < 0) { printf("ERROR: Receive data error %d\n", WSAGetLastError()); closesocket(Sock); return 0; } printf("recv %d bytes, ", bytes_read); sendto(Sock, TEST_PACKET, TEST_PACKET_SIZE, 0, (sockaddr*)&client_addr, sizeof(client_addr)); } closesocket(Sock); } |
Сообщ.
#2
,
|
|
|
А что будет, если попробовать так:
for(int i = 0; i < iPackets; i++) { ::Sleep(200); sendto(Sock, TEST_PACKET, TEST_PACKET_SIZE, 0, (sockaddr *)&addr, sizeof(addr)); } -Added И вот так: printf("recv %d bytes, ", bytes_read); /* sendto(Sock, TEST_PACKET, TEST_PACKET_SIZE, 0, (sockaddr*)&client_addr, sizeof(client_addr)); */ |
Сообщ.
#3
,
|
|
|
Та же самая ошибка. Но если разместить исходные клиент и сервер на разных машинах, то ошибок нет.
|
Сообщ.
#4
,
|
|
|
Цитата =MOHAX= @ An existing connection was forcibly closed by the remote host. В протоколе udp нет понятия CONNECTION - в принципе Потому все описание ситуации не соответствует идеям взаимодействия. Что-то не так |
Сообщ.
#5
,
|
|
|
Я приложил полный код исходников, может это какой-то глюк на моей машине?
У меня стоит WinXP SP3. Сейчас попробую запустить этот код под red hat... |
Сообщ.
#6
,
|
|
|
В общем это снова бредовые изыски Мелкософта:
WinSock Recvfrom() now returns WSAECONNRESET instead of blocking or timing out http://support.microsoft.com/default.aspx?scid=kb;en-us;263823 правда они пишут что эту муть они сделали только под 2000-ный, значит врут Принципиально это все-таки возможно – только в одном случае: This error is also possible on a datagram socket; for instance, this error could result if your application sends a UDP datagram to a host, which rejects it by responding with an ICMP Port Unreachable.[B] |
Сообщ.
#7
,
|
|
|
Мде...
|
Сообщ.
#8
,
|
|
|
Цитата =MOHAX= @ Я приложил полный код исходников, может это какой-то глюк на моей машине? У меня стоит WinXP SP3. Сейчас попробую запустить этот код под red hat... Нет, у меня то же самое. Но суть предложения ты похоже не уловил. я предположил, что работа твоей проги слишком "напрягает" компьютер и он попросту не в состоянии обработать такое количество информации. Стоило ослабить нагрузку (уменьшить темп передачи) у меня ошибки прекратились. Не удивительно, что на разных компьютерах эффект пропал. |
Сообщ.
#9
,
|
|
|
Цитата ЫукпШ @ я предположил, что работа твоей проги слишком "напрягает" компьютер и он попросту не в состоянии обработать такое количество информации. Это безусловно так Стек одного и того же компа вынужден очень быстро реагировать на то, что он сам себе и шлет Потому slep(200)проблемы не решил. Для интереса можно было бы поставить секунду. и более Ну и конечно же сама ошибка в микрософтовской интерпретации напрягает |
Сообщ.
#10
,
|
|
|
Цитата Oleg2004 @ Стек одного и того же компа вынужден очень быстро реагировать на то, что он сам себе и шлет Потому slep(200)проблемы не решил. А если так ?: for(int i = 0; i < iPackets; i++) { WaitTrReady (Sock); sendto(Sock, TEST_PACKET, TEST_PACKET_SIZE, 0, (sockaddr *)&addr, sizeof(addr)); } // где: bool WaitTrReady (SOCKET Socket) { bool ReadRDY, bool WriteRDY, bool ErrRDY; bool RetC = false; for(int i=0; i<T_OUT;++i) { if(!SelectOP (Socket, ReadRDY, WriteRDY, ErrRDY)) return false; if(WriteRDY) {RetC = true;break;} ::Sleep(200+i*50); } return RetC; } //.................... bool SelectOP (SOCKET Socket, bool& ReadRDY, bool& WriteRDY, bool& ErrRDY) { bool RetC=false; fd_set ReadS,WriteS,ErrS; ReadRDY = false; WriteRDY = false; ErrRDY = false; FD_ZERO(&ReadS); FD_ZERO(&WriteS); FD_ZERO(&ErrS); FD_SET(Socket, &ReadS); FD_SET(Socket, &WriteS); FD_SET(Socket, &ErrS); SetTimeval ();// установка t-out if(::select(0,&ReadS,&WriteS,&ErrS,&tv)!=SOCKET_ERROR) { if(FD_ISSET(Socket, &ReadS)) {ReadRDY = true;} if(FD_ISSET(Socket, &WriteS)) {WriteRDY = true;} if(FD_ISSET(Socket, &ErrS)) {ErrRDY = true;} RetC=true; } return RetC; } |
Сообщ.
#11
,
|
|
|
Извините, но без комментов к идее разобраться в чужих соображениях очень нелегко, если вообще возможно.
Однако позволю себе еще раз напомнить, что в UDP быстрый передатчик подавляет приемник "Уведомление ICMP типа source quench иногда называют также "подавление источника". Его можно рассматривать как примитивный инструмент сдерживания потоков, генерируемых отправителем, но нельзя причислить к эффективным методам контроля за перегрузками. В ранних UNIX-реализациях протоколов TCP/IP ICMP-пакеты этого типа игнорировались. В TCP-реализациях, поддерживающих алгоритм медленного старта, в ответ на это сообщение уменьшается размер "окна перегруженности". UDP-модули игнорируют это сообщение, информируя при этом обслуживаемую прикладную программу о требовании приемника уменьшить интенсивность и/или размер пакетов.Согласно RFC-1812 эта ошибка признана устаревшей" Повидимому та ошибка, о которой шла речь вначале, и призвана для оповещения....... |
Сообщ.
#12
,
|
|
|
Цитата Oleg2004 @ Извините, но без комментов к идее разобраться в чужих соображениях очень нелегко, если вообще возможно. Однако позволю себе еще раз напомнить, что в UDP быстрый передатчик подавляет приемник Извините, что так произошло. В данном случае я пытался предложить перед отправкой сообщения проверить готовность передатчика. |
Сообщ.
#13
,
|
|
|
Цитата ЫукпШ @ В данном случае я пытался предложить перед отправкой сообщения проверить готовность передатчика. А смысл? Если это UDP-сервер, то он всегда готов - так как висит на recvfrom() и ждет вечно...... Так что он то готов всегда - если включен |
Сообщ.
#14
,
|
|
|
Вернемся к исходному коду. Во-первых, поставьте и в цикл сервера и в цикл клиента задержку, хоть какую-то. Смотрите на это хотя бы с той стороны, что это является плохим тоном, т.е. у Вас должно быть представление в какой момент времени от начала секунды что происходит, а в Вашем варианте получается мешанина. А ошибка возникает скорее всего из-за того, что на клиент Вы отправляете данные, но клиентом их не считатываете. По умалчиванию буффер приема, если не ошибаюсь, равен 4096 байт. На 10-й операции у Вас туда пытается записаться 5160 байт, поэтому клиент и отрубается. Правда не могу понять почему на двух разных компьютерах этого не происходит Юзайте setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (char *)&size, sizeof(size)) и setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char *)&size, sizeof(size))
PS И еще WSACleanup() забыли |