2015-09-23 2 views
2

У меня есть TCP-сервер, который прослушивает два разных порта. Я создал два разных сокета один на порт 8888 и один на порт 6634. Я слушаю эти порты, а затем добавляю два сокета в FD_SET и передаю их функции select() ... Когда сокет готов к чтению, я проверяю с FD_ISSET, чтобы увидеть, на каком порту у меня есть сообщение для чтения.TCP-сервер, который прослушивает два разных порта

в любом случае, когда я подключаюсь к порту 8888, концепция выполнена успешно, и я могу отправить ее на сервер и получить ... когда i ctrl + c клиент функция выбора возвращается снова 1, и теперь мой accept() терпит неудачу. .. , когда я делаю то же самое на порту 6634, все в порядке ... код останавливается на select() и ждет, когда сокет будет готов к чтению!

может кто-нибудь сказать мне, ПОЧЕМУ это происходит?

взглянуть на мой код в приложении

int main() 
    { 
     SOCKET   conn_request_skt; /* socket where connections are accepted */ 
     char   buf[RBUFLEN], buf1[RBUFLEN];  /* reception buffer */ 
     uint16_t  lport_n, lport_h, lport_n1, lport_h1; /* port where the server listens (net/host byte ord resp.) */ 
     int   bklog = 2;  /* listen backlog */ 
     SOCKET   s,s1;   
     int   result, n; 
     socklen_t addrlen; 
     struct sockaddr_in saddr, caddr;  /* server and client address structures */ 
     int optval,childpid,i; /* flag value for setsockopt */ 
     int connectcnt; /* number of connection requests */ 
     fd_set readfds; 

     /* Initialize socket API if needed */ 
     SockStartup(); 

     /* input server port number */ 
     lport_h=6634; 
     lport_n = htons(lport_h); 
     lport_h1=8888; 
     lport_n1 = htons(lport_h1); 

     /* create the socket */ 
     printf("Creating first socket\n"); 
     s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
     if (s == INVALID_SOCKET) 
      err_fatal("socket() failed"); 
     printf("done, socket number %u\n",s); 

     /* bind the socket to any local IP address */ 
     saddr.sin_family  = AF_INET; 
     saddr.sin_port  = lport_n; 
     saddr.sin_addr.s_addr = INADDR_ANY; 
     showAddr("Binding to address first socket", &saddr); 
     result = bind(s, (struct sockaddr *) &saddr, sizeof(saddr)); 
     if (result == -1) 
      err_fatal("bind() failed"); 
     printf("done.\n"); 

     printf("Creating second socket\n"); 
     s1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
     if (s1 == INVALID_SOCKET) 
      err_fatal("socket() failed"); 
     printf("done, socket number %u\n",s1); 

     /* bind the socket to any local IP address */ 

     saddr.sin_port=lport_n1; 

     showAddr("Binding to address second socket", &saddr); 
     result = bind(s1, (struct sockaddr *) &saddr, sizeof(saddr)); 
     if (result == -1) 
      err_fatal("bind() failed"); 
     printf("done.\n"); 


     /* listen */ 
     printf ("Listening at socket %d with backlog = %d \n",s,bklog); 
     result = listen(s, bklog); 
     if (result == -1) 
      err_fatal("listen() failed"); 
     printf("done.\n"); 

     printf ("Listening at socket %d with backlog = %d \n",s1,bklog); 
     result = listen(s1, bklog); 
     if (result == -1) 
      err_fatal("listen() failed"); 
     printf("done.\n"); 
for (;;) 
    { 


     FD_ZERO(&readfds);   /* initialize the fd set */ 
     FD_SET(s, &readfds); 
     FD_SET(s1, &readfds); /* add socket fd */ 
     printf("here \n"); 

     printf("result bifore select is %d \n", result); 
     result=select(s1+1, &readfds, 0, 0, 0); 

     printf("result after select is %d \n", result); 

     if(result<0) 
      { 
       err_fatal("select() failed"); 

      } 
     if(result>0) 
     { 

      if(FD_ISSET(s,&readfds)) 
      { 

       conn_request_skt=s; 
       /* accept next connection */ 
       addrlen = sizeof(struct sockaddr_in); 
       s = accept(conn_request_skt, (struct sockaddr *) &caddr, &addrlen); 
       if (s == INVALID_SOCKET) 
       err_fatal("accept() failed"); 
       showAddr("Accepted connection from", &caddr); 
       printf("new socket: %u\n",s); 
       /* serve the client on socket s */ 
       for (;;) 
       { 
        n=recv(s, buf, RBUFLEN-1, 0); 
        if (n < 0) 
        { 
         printf("Read error\n"); 
         closesocket(s); 
         printf("Socket %d closed\n", s); 
         break; 
        } 
        else if (n==0) 
        { 
         printf("Connection closed by party on socket %d\n",s); 
         //closesocket(s); 
         break; 
        } 
        else 
        { 
         printf("Received line from socket %03d :\n", s); 
         buf[n]=0; 
         printf("[%s]\n",buf); 
         if(writen(s, buf, n) != n) 
         printf("Write error while replying\n"); 
         else 
         printf("Reply sent\n"); 
        } 
       } 
      } 


      if(FD_ISSET(s1,&readfds)) 
      { 
       conn_request_skt=s1; 
       /* accept next connection */ 
       addrlen = sizeof(struct sockaddr_in); 
       printf("bifore accept! \n"); 
       s1 = accept(conn_request_skt, (struct sockaddr *) &caddr, &addrlen); 
       if (s1 == INVALID_SOCKET) 
       err_fatal("accept() failed"); 
       showAddr("Accepted connection from", &caddr); 
       printf("new socket: %u\n",s1); 
       /* serve the client on socket s */ 
       for (;;) 
       { 
        n=recv(s1, buf, RBUFLEN-1, 0); 
        if (n < 0) 
        { 
         printf("Read error\n"); 
         closesocket(s1); 
         printf("Socket %d closed\n", s1); 
         break; 
        } 
        else if (n==0) 
        { 
         printf("Connection closed by party on socket %d\n",s1); 
         //closesocket(s); 
         break; 
        } 
        else 
        { 
         printf("Received line from socket %03d :\n", s1); 
         buf[n]=0; 
         printf("[%s]\n",buf); 
         if(writen(s1, buf, n) != n) 
         printf("Write error while replying\n"); 
         else 
         printf("Reply sent\n"); 
        } 
       } 
      } 
     } 
    } 
} 

ответ

2

Первый сокет слушатель создается с:

s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 

А затем сокет данные принимаются с:

conn_request_skt=s; 
s = accept(conn_request_skt, (struct sockaddr *) &caddr, &addrlen); 

Видеть? Следующий цикл, когда вы собираетесь выбирать над сокетом прослушивателя, s больше не поддерживает этот сокет, а (закрытый) разъем данных.

Решение заключается в использовании разных переменных для сокета-получателя и сокета данных (conn_request_skt просто затуманивает проблему).

1

Вы переписываете переменную сокета s1 с результатом вызова accept(). Таким образом, s1 содержит теперь дескриптор сокета, который вы действительно читаете. Затем вы закрываете этот сокет. Но в следующем проходе основного цикла вы проверяете возможность чтения на этом (теперь закрытом) дескрипторе, который не работает.

Я считаю, что было бы лучше не использовать переменные в этом случае. Используйте новую переменную для фактического гнезда подключения, чтобы сохранить исходный гнездо для прослушивания в s1.

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