Пишу на С ,http+сокеты.Нужно использовать в работе программы прокси.Исходя из того что все паблик прокси УГ.Столкнулся с одной очень болезненной проблемой.После иногда после send recv может ооочень долго ждать входящих данных.Так вот как можно этому делу задать таймаут?Я нагуглил что нужно использовать select,но вот только решений касающихся именно моей проблемы в гугле я не нашол А как работает этот мезанизм до конца немогу понять Вот и мучаюсь вопросами когда вызывать select после send,или вообще перед connect?Надо ли перводить сокет через ioctlsocket в "non-blocking" режим? К сожалению найти специально прокси который бы так фризил неочень просто и поэтому поэкспереминтировать неочень получается Подскажите пожалуйста как это все правильно организовать.
просто send() это blocking mode. Переведи сокет в non blocking mode, потом send() и потом select(). Последний вернётся когда данные отправлены+приняты или по timeout. Whichever is first.
Код (Text): struct timeval timeout; bzero(&timeout, sizeof(timeval)); timeout.tv_sec= 1; setsockopt(sclient, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeval)); [добавлено] power1# man setsockopt ........... Most socket-level options utilize an int argument for optval. For setsockopt(), the argument should be non-zero to enable a boolean option, or zero if the option is to be disabled. SO_LINGER uses a struct linger argument, defined in <sys/socket.h>, which specifies the desired state of the option and the linger interval (see below). SO_SNDTIMEO and SO_RCVTIMEO use a struct timeval argument, defined in <sys/time.h>. ........... SO_OOBINLINE enables reception of out-of-band data in band SO_SNDBUF set buffer size for output SO_RCVBUF set buffer size for input SO_SNDLOWAT set minimum count for output SO_RCVLOWAT set minimum count for input SO_SNDTIMEO set timeout value for output SO_RCVTIMEO set timeout value for input SO_ACCEPTFILTER set accept filter on listening socket SO_NOSIGPIPE controls generation of SIGPIPE for the socket SO_TIMESTAMP enables reception of a timestamp with datagrams SO_BINTIME enables reception of a timestamp with datagrams SO_ACCEPTCONN get listening status of the socket (get only) SO_TYPE get the type of the socket (get only) SO_ERROR get and clear error on the socket (get only)
Всеравно ничего непонятно Что то должно происходить при таймауте? Попытался сделать вот такой эксперимент Клиент: Код (Text): void main() { char buf[1024]; ULONG ulB=TRUE;fd_set FdSet; SOCKET s;SOCKADDR_IN adr;WSADATA wsd; struct timeval Time;int sr=0; WSAStartup(MAKEWORD(2,0),&wsd); adr.sin_family=AF_INET; adr.sin_port=htons(157); adr.sin_addr.s_addr=inet_addr("127.0.0.1"); s=socket(AF_INET,SOCK_STREAM,0); getch(); connect(s,(sockaddr*)&adr,sizeof(adr)); ioctlsocket(s,FIONBIO,&ulB); Time.tv_sec=10; Time.tv_usec=10*1000000; FD_ZERO(&FdSet); FD_SET(s,&FdSet); for(;;) { cin>>buf; send(s,buf,1024,0); sr=select(0,NULL,&FdSet,NULL,&Time); memset(buf,NULL,strlen(buf)); recv(s,buf,1024,0); if(sr>0){cout<<"timeout"<<endl;} cout<<buf<<endl; memset(buf,NULL,strlen(buf)); } } Сервер: Код (Text): void main() { char buff[1024]; SOCKET s1,s2;SOCKADDR_IN ladr,cadr; WSADATA wsd;WSAStartup(MAKEWORD(2,0),&wsd); ladr.sin_family=AF_INET; ladr.sin_port=htons(157); ladr.sin_addr.s_addr=0; s1=socket(AF_INET,SOCK_STREAM,0); bind(s1,(sockaddr*)&ladr,sizeof(ladr)); listen(s1,1); int sz=sizeof(cadr); s2=accept(s1,(sockaddr*)&cadr,&sz); for(;;) { recv(s2,buff,1024,0); cout<<buff<<endl; if(strcmp(buff,"exit")==0){getch();} send(s2,buff,1024,0); memset(buff,NULL,strlen(buff)); } } ВОПРОС:как ловить таймаут????
У тебя много мелких глюков в коде: 1) что ты посылаешь в ioctlsocket()? Где присвоение? 2) проверяй что возвращают системные вызовы, пиши в cout 3) Time = 20с, думаю ты хотел 10 4) timeout ты пустил в операцию select(), а не в сокет (разные вещи) 5) после возврата из select() проверь каждый descriptor через FD_ISSET 6) выведи на экран
Извени я непонимаю ( Что значит: "а не в сокет" ?? Дескриптор сокета?Для чего? Так что же должно произойти с recv по истечению таймаута? Оно должно завершится с кодом ошибки?
s0larian, не, в данном случае если select() в клиенте, то в него пихается один сокет. FD_ISSET не нужен. _nic, по истечению таймаута в хорошем раскладе select вернёт 1, если ничего не будет принято вернёт 0.
Я имел ввиду sendsockopt(SO_SNDTIMEO), но сейчас проверил доку - эта опция только для blocking sockets. Следовательно делать надо так как ты пробовал - стачала send(), потом select(). Если select() вернёт ноль - значит это timeout. Если 1 - то прверяешь socket-ы с FD_ISSET(). Ессно в случае с одним сокетом это должен быть именно он С отправкой - та же схема. Если сокетов нескольно - то надо внимательно смотреть что было послано/принято, что осталось, на что уже timeout.
Изменил вот так Код (Text): void main() { char buf[1024]; ULONG ulB=TRUE;fd_set FdSet; SOCKET s;SOCKADDR_IN adr;WSADATA wsd; struct timeval Time;int sr=1; WSAStartup(MAKEWORD(2,0),&wsd); adr.sin_family=AF_INET; adr.sin_port=htons(157); adr.sin_addr.s_addr=inet_addr("127.0.0.1"); s=socket(AF_INET,SOCK_STREAM,0); getch(); connect(s,(sockaddr*)&adr,sizeof(adr)); ioctlsocket(s,FIONBIO,&ulB); Time.tv_sec=5; Time.tv_usec=10*1000000; FD_ZERO(&FdSet); FD_SET(s,&FdSet); for(;;) { cin>>buf; send(s,buf,1024,0); sr=select(0,NULL,&FdSet,NULL,&Time); memset(buf,NULL,strlen(buf)); if(sr==0){cout<<"timeout"<<endl;} if(sr!=0) { recv(s,buf,1024,0); cout<<buf<<endl; memset(buf,NULL,strlen(buf)); }// } } select 0 невозвращяет сколько не жди Что я не так понял? _____________________________________________________ А все ...Понял...Я не в то место передал параметры select .Вот так select(0,&FdSet,NULL,NULL,&Time) все работает