WinSocks многопоточный сканер

Тема в разделе "WASM.NETWORKS", создана пользователем Aids, 4 май 2011.

  1. Aids

    Aids New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2007
    Сообщения:
    275
    Пишу что то на подобии многопоточного IP сканера. И у меня возникла проблема. После следующего события. Я подключаюсь к хосту connect.
    send отправляю HTTP запрос на скачивание файла. читаю файл select 10 ожидание recv. Так вот если файл на хосте есть то всё в порядке. А вот если его нет, то я больше не могу выполнить connect. Я так понял что предидущее соединение осталось активным на созданном сокете, и поэтому не происходит коннест. пробовал вызвать shutdown перед коннектом, но тоже не работает. Подскажите как быть?
     
  2. Aids

    Aids New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2007
    Сообщения:
    275
    Как вариант нашёл решение: закрытие и создание нового сокета. Но мне кажется это как то не правильно. Хотя работает вроде бы
     
  3. Aids

    Aids New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2007
    Сообщения:
    275
    Код (Text):
    1. DWORD WINAPI ThreadProc(
    2.     __in  LPVOID lpParameter){
    3.         TThreadInfo *p=(TThreadInfo*)lpParameter;
    4.         CHTTP *HTTP=new CHTTP();
    5.         char genhost[0x50];
    6.         long TempKey=p->ScanHost->Key;
    7.         bool Status=true;
    8.         while(Status){
    9.             while (HTTP->CheckInet()&&Status){//есть интернет
    10.                 EnterCriticalSection(&p->ScanHost->cs);
    11.                 long TempInd=p->index;
    12.                 printf("ind %d\n",TempInd);
    13.                 p->index++;
    14.                 LeaveCriticalSection(&p->ScanHost->cs);
    15.                 p->ScanHost->Rnd->gen_host(TempKey+TempInd,genhost);
    16.                
    17.                 if (HTTP->Connect(genhost)){
    18.                     HTTP->RequestGET((char*)PageSign);
    19.                     HTTP->Recv();
    20.                     //HTTP->Disconnect();
    21.                     if (HTTP->GetLen()>=(sizeof(PageID)-1)){
    22.                         if (memcmp(HTTP->GetData(),(char*)PageID,sizeof(PageID)-1)==0){
    23.                             p->Status=false;
    24.                             p->ScanHost->Key=TempKey+TempInd;
    25.                             strcpy(p->ScanHost->Host,genhost);
    26.                         }
    27.                     }
    28.                 }
    29.                 Status=p->Status;
    30.                
    31.             }
    32.             if (Status) Sleep(30000);  
    33.         }
    34.         delete HTTP;
    35.     return TRUE;
    36. }
    37.  
    38. bool CClientTCP::Connect(char *Host,int Port){
    39.     if (bConnect) Disconnect();
    40.     strcpy(this->Host,Host);
    41.     this->Port=Port;
    42.     sockaddr_in sa;
    43.     sa.sin_family = AF_INET;
    44.     hostent *ip=gethostbyname(Host);
    45.     if (ip==0) return bConnect;
    46.     sa.sin_addr.s_addr = *(DWORD*)(ip->h_addr_list[0]);
    47.         sa.sin_port = htons(Port);
    48.     if (connect(hSocket,(sockaddr*)&sa,sizeof(sa))==0) bConnect=true;  
    49.     return bConnect;
    50. };
    51. bool CClientTCP::Send(char *buf,int len){
    52.     bool Status=false;
    53.     if (!bSocket || !bConnect) return false;
    54.     if (send(hSocket,buf,len,0)!=SOCKET_ERROR) Status=true;
    55.     return Status;
    56. }
    57.  
    58. int CClientTCP::Recv(char *buf,int len){
    59.     int Status=0;
    60.     int iResult=0;
    61.     if (!bSocket || !bConnect) return false;
    62.     unsigned long am_bytes;
    63.     fd_set fd_read;
    64.     FD_ZERO(&fd_read);
    65.     FD_SET(hSocket,&fd_read);
    66.     timeval tv;
    67.     tv.tv_sec=3;
    68.     tv.tv_usec=0;
    69.     int res=select(0,&fd_read,0,0,&tv);
    70.     if (SOCKET_ERROR==res) return Status;
    71.     if ((res!=0) && (FD_ISSET (hSocket, &fd_read)))
    72.         iResult=recv(hSocket,buf,len,0);
    73.     else iResult=0;
    74.     if (iResult>0) Status=iResult;
    75.     if (iResult==0) Status=-1;
    76.     if (iResult<0) Status=0;
    77.     return Status;
    78. }
    основные части выложил.
    Код (Text):
    1.     fd_set fd_read;
    2.     FD_ZERO(&fd_read);
    3.     FD_SET(hSocket,&fd_read);
    4.     timeval tv;
    5.     tv.tv_sec=3;
    6.     tv.tv_usec=0;
    7.     int res=select(0,&fd_read,0,0,&tv);    думаю тут что то нахимичил
    8.     if (SOCKET_ERROR==res) return Status;
    9.     if ((res!=0) && (FD_ISSET (hSocket, &fd_read)))
    так как были проблемы при отсутствии файла на сервере(ждал бесконечно) и при лишнем чтении recv
     
  4. Aids

    Aids New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2007
    Сообщения:
    275
    Код (Text):
    1.   int Status=0;
    2.     int iResult=0;
    3.     if (!bSocket || !bConnect) return false;
    4.     unsigned long am_bytes;
    5.     fd_set fd_read;
    6.     FD_ZERO(&fd_read);
    7.     FD_SET(hSocket,&fd_read);
    8.     timeval tv;
    9.     tv.tv_sec=3;
    10.     tv.tv_usec=0;
    11.     int res=select(0,&fd_read,0,0,&tv);
    12.     if (SOCKET_ERROR==res) return Status;
    13.     if ((res!=0) && (FD_ISSET (hSocket, &fd_read)))
    14.         iResult=recv(hSocket,buf,len,0);
    15.     else iResult=0;
    16.     if (iResult>0) Status=iResult;
    17.     if (iResult==0) Status=-1;
    18.     if (iResult<0) Status=0;
    Код работает. Но есть проблемка. При приёме любых данных в конце происходит таймаут 3 сек. Таймаут происходит так как код не может определить когда закончились пакеты, recv должен вернуть 0. Но получается так первый буфер 630 байт, он и последний должен быть. И потом ещё раз считывает. Но в сокете нет уже данных и выход происходит по таймауту. Как определить размер принимаемых данных?
     
  5. Aids

    Aids New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2007
    Сообщения:
    275
    И тишина. Что никто не может сказать как правильо определить последний пакет загрузки файла?
     
  6. fsd

    fsd New Member

    Публикаций:
    0
    Регистрация:
    4 июл 2010
    Сообщения:
    353
    необходимо рассчитать размер HTTP сообщения, как это сделать читайте в RFC
     
  7. Aids

    Aids New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2007
    Сообщения:
    275
    fsd
    это мне надо смотреть поле Content-Length: ? Но ведь оно не всегда есть в заголовке. А если это не HTTP протокол, а просто посылается команда серверу, а он в ответ шлёт какие то данные. То тогда как быть?
     
  8. T800

    T800 Member

    Публикаций:
    0
    Регистрация:
    7 дек 2006
    Сообщения:
    293
    Адрес:
    Moscow
    Aids
    Вы почитайте что нибудь о протоколах, которые поверх TCP работают. И не будет таких вопросов.
     
  9. Aids

    Aids New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2007
    Сообщения:
    275
    ещё одно решение
    HTTP 1.0
    Connection: Close
    и после последнего пакета соединение закрывается. и recv 0 возвращает. Но вот если что нибудь на другой стороне произойдёт и не произойдёт закрытия. повиснет же. Тоже не очень решение.
    T800
    Так у меня же нет доступа к IP/TCP уровню. При использовании сокетов.
    хотя возможно я не знаю каких то основных принципов TCP/IP
    fsd
    не слышал раньше почитаю RFC