2013-10-06 2 views
0

Я новичок в использовании winsock2 и собрал следующий код для сервера, который я пытаюсь использовать для отправки строки клиенту, который я запускаю на том же компьютере (подключение к 127.0.0.1 с тем же портом, что и сервер для прослушивания).Winsock2: «listen» возвращается раньше

Я использую MinGW, если это имеет значение.

Проблема, с которой я сталкиваюсь, заключается в том, что listen(), кажется, заканчивается раньше, но возвращает код успеха. Это проблема, потому что тогда, когда accept() вызывается, кажется, что он блокируется навсегда. Это событие происходит независимо от того, выполняю ли я клиентскую программу, и я пытался запустить клиентскую программу до и после, но это, похоже, не влияет на нее.

// -1: "Could not initialize WSA." 
// -2: "Could not create listener socket." 
#define WIN32_LEAN_AND_MEAN 
#define _WIN32_WINNT 0x0501 
#include <windows.h> 
#include <winsock2.h> 
#include <ws2tcpip.h> 
#include <iphlpapi.h> 
#include <cstdio> 
#define port 0x0ABC 
UINT64 trStrLen (char* str) 
{ 
    if (str == NULL) return 0; 
    UINT64 pos = 0; 
    while (*(str + pos) != '\0') pos++; 
    return pos; 
}; 
#include <cstdio> 
int main() 
{ 
    WSADATA wsadata; 
    if (WSAStartup(MAKEWORD(2,0),&wsadata)) return -1; 
    SOCKET server = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
    SOCKADDR_IN sin; 
    memset(&sin,0,sizeof(SOCKADDR_IN)); 
    sin.sin_family = AF_INET; 
    sin.sin_port = htons(port); 
    sin.sin_addr.s_addr = INADDR_ANY; 
    int socksize = sizeof(SOCKADDR); 
    while (bind(server,(SOCKADDR*)(&sin),socksize) == SOCKET_ERROR) return -2; 
    char* TEMP_TO_SEND = "Billy Mays does not approve."; 
    UINT64 TEMP_SEND_LEN = trStrLen(TEMP_TO_SEND); 
    printf("Server online.\n"); 
    while (true) 
    { 
     printf("Waiting for connections.\n"); 
     while (listen(server,SOMAXCONN) == SOCKET_ERROR); 
     printf("Client requesting connection.\n"); 
     SOCKET client = accept(server,NULL,NULL); 
     printf("Accept is no longer blocking.\n"); 
     if (client != INVALID_SOCKET) 
     { 
      printf("Attempting to send information to the client...\n"); 
      if (send(client,TEMP_TO_SEND,TEMP_SEND_LEN,0) == SOCKET_ERROR) printf("The information wasn't sent properly.\n"); 
      else printf("The client received the information.\n"); 
     } 
     else printf("Couldn't establish a connection to the client.\n"); 
    }; 
}; 

Это, вероятно, что-то очевидное, но я не вижу его, поэтому любые советы будут полезны.

ответ

5

listen() не является блокирующим вызовом. Он ничего не делает с сетью. Он просто помещает сокет в режим пассивного прослушивания, устанавливает очередь на отставание и возвращается. Это accept(), который является блокирующим вызовом: он блокируется до тех пор, пока входящее соединение не будет завершено, а затем вернет для него сокет.

Таким образом, вы не должны звонить listen() в петлю while вообще.

То же самое относится к bind(). Позвоните один раз.

+0

Спасибо! Я думал, что слушать ждет, что там будет связь, это очень помогает. – rsethc

+0

На самом деле я не знаю, почему в этом я поставил цикл while в 'bind()'. В моем фактическом коде это выражение 'if'. Выполнение 'while' здесь не имеет смысла. – rsethc

+0

@rsethc: если вы хотите дождаться получения соединения до вызова 'accept()', для этого вы можете использовать 'select()'. Он расскажет вам, когда доступно новое соединение, и у него есть необязательный параметр тайм-аута, который полезен в циклах, если вам нужно делать другие вещи во время ожидания. –

Смежные вопросы