setsockopt непонятная проблема

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by _nic, 18 Nov 2009.

  1. _nic

    _nic Elder - Старейшина

    Joined:
    5 May 2006
    Messages:
    651
    Likes Received:
    54
    Reputations:
    3
    Использую setsockopt для таймаута в случае с recv(чекаю прокси).Проблема в том что в большинстве случаев recv висит до конца таймаута, но если приконектится к тому же проксику без setsockopt то recv получает данные в пределах таймаута :confused:
    ВОт код:
    Code:
    DWORD WINAPI check(LPVOID lParam)
    {
    	/*WSADATA wsd;
    	WSAStartup(MAKEWORD(2,2),&wsd);*/
    	char Ip[30],msg[100]="                         ";
    	char *port=new char[30];
    	char *indata=new char[1024*256];
    	memset(indata,NULL,1024*256);
    	char *result=new char[1024*256];
    	memset(result,NULL,1024*256);
    	SOCKADDR_IN adr;
    	struct timeval timeout;
    	ZeroMemory(&timeout,sizeof(timeval));
    	timeout.tv_sec= 9;
    	SOCKET s;
    	ZeroMemory(&adr,sizeof(adr));
    	for(int i=0;i!=Form1->ListBox1->Count;i++)
    	{
    		strcpy(Ip,Form1->ListBox1->Items->operator [](i).c_str());
    		strcpy(port,Form1->ListBox1->Items->operator [](i).c_str());
    		strtok(Ip,":");
    		port+=strlen(Ip)+1;
    		adr.sin_family=AF_INET;
    		adr.sin_addr.s_addr=inet_addr(Ip);
    		adr.sin_port=htons(atoi(port));
    		WSASetLastError(0);
    		s=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    		setsockopt(s,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeval));
    		connect(s,(sockaddr*)&adr,sizeof(adr));
    		send(s,msg,100,0);
    		Form1->Memo1->Lines->Add("1\r");
    		recv(s,indata,1024*256,0);
    		Form1->Memo1->Lines->Add("2\r");
    		Form1->Memo1->Lines->Add("Count:"+AnsiString(i)+"\r");
    		//wsprintf(result,"Proxy: %s:%s\rAnswer:\r%s\rSocketError: %d",Ip,port,indata,WSAGetLastError());
    		//Form1->Memo1->Lines->Add(result);
    		strtok(indata,"\r\n\r\n");
    		Form1->Memo1->Lines->Add(AnsiString(indata)+"\r");
    		if(strstr(indata,"200")!=NULL)
    		{
                Form1->ListBox2->Items->Add(AnsiString(Ip)+":"+AnsiString(port));
            }
    		port-=strlen(Ip)+1;
    		closesocket(s);
    		memset(result,NULL,1024*256);
    		memset(indata,NULL,1024*256);
    	}
    	//WSACleanup();
    	return(0);
    }
    
    Если коротко то проблема в том что recv нереагирует на появивщиеся данные в сокете и таймаут тикает до конца :(
     
    #1 _nic, 18 Nov 2009
    Last edited: 18 Nov 2009
  2. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    какое-то у тебя неадекватное время таймаута стоит. Оно задается на в секундах а в миллисекундах.
    Code:
     struct timeval timeout = {0}
    ...........
     timeout.tv_sec = 10000;  // 10 секунд
    ...........
     setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(struct timeval));
    
    А вообще в коде чтото не вижу проверок на валидность сокета. Т.е. ты не проверяещ - создался он или нет.
    также нет проверки того что возвращает recv.
    Но главное - ты неудасужился даже проверить что вернул connect
    Потому как может ты даже не подключился, а пытаешься считать уже данные.
    Также тебе нужны таймауты на connect

    В моей статейке по винсоку (/showpost.php?p=1331069&postcount=1) может почитать про таймаут на коннект.