2012-10-24 74 views
0

我有客戶端可以連接到的此服務器應用程序。現在我希望當客戶端連接時,我可以發送數據給他們。當我連接我的兩個客戶端時,我設法做到這一點..我發送的是我的兩個客戶端收到的。但我的問題是當我連接客戶端1然後發送數據到服務器,客戶端1可以接收數據,然後我連接客戶端2,我發送數據到服務器。現在當我從服務器發送數據到我的客戶端時,只有客戶端1可以接收數據,但是當我斷開客戶端1時,客戶端2可以從服務器接收數據。將數據發送到我的服務器上連接的多個客戶端

我怎樣才能讓他們在同一時間工作?..而且我怎樣才能讓我的服務器從我的客戶接受的同時消息?..

這裏是有碼IM麻煩的一部分。

for(j=0;j<MAX_CLIENTS; j++) 
Clients[j].connected_sock = -1; 


do 
    { 

     fduse = fdin; 

     printf("Waiting for Connection\n"); 
     err = select(sMax + 1, &fduse, NULL, NULL, NULL); 

     if (err < 0) 
     { 
    perror(" select() failed"); 
    break; 
     } 

     DescRead = err; 
     for (SockStorage=0; SockStorage <= sMax && DescRead > 0; ++SockStorage) 
     { 

     if (FD_ISSET(SockStorage, &fduse)) 
     { 

     DescRead -= 1; 


     if (SockStorage == socketFd) 
     { 
      printf(" Listening socket is readable\n"); 

      do 
      { 

       NewSFD = accept(socketFd,(struct sockaddr *) &cli_addr, &clilen); 
       if (NewSFD < 0) 
       { 
       if (errno != EWOULDBLOCK) 
       { 
        perror(" accept() failed"); 
        DCSERVER = TRUE; 
       } 
       break; 
       } 

       if(ClientCount < MAX_CLIENTS){ 

       for(loop = 0; loop <MAX_CLIENTS; loop++){ 

       if(Clients[loop].connected_sock<0){ 

       Clients[loop].connected_sock = NewSFD; 

       break; 

       } 

       } 

       ClientCount++; 
       } 
       else 
       { 

       printf("Maximum Client Reached.\n"); 
       char *sendtoclient = "Server full. "; 
       send(NewSFD, sendtoclient, strlen(sendtoclient),0); 
       close(NewSFD); 
       break; 

       } 

       ip = ntohl(cli_addr.sin_addr.s_addr); 
       printf(" Connection from %d.%d.%d.%d\n", 
        (int)(ip>>24)&0xff, 
        (int)(ip>>16)&0xff, 
        (int)(ip>>8)&0xff, 
        (int)(ip>>0)&0xff); 
        dlogs(ip); 


       FD_SET(NewSFD, &fdin); 
       if (NewSFD > sMax) 
       sMax = NewSFD; 

      } while (NewSFD != -1); 


     } 

     else 
     { 

     int d; 
     for(d=0; d<MAX_CLIENTS; d++){ 

     printf("Descriptor ID: %d\n", Clients[d].connected_sock); 

     } 


      pfds[0].fd = fd; 
      pfds[0].events = POLLIN; 
      pfds[1].fd = SockStorage; 
      pfds[1].events = POLLIN; 
      state = FALSE; 

      do 
      { 
      rc = poll(pfds, 2, -1); 

      if (pfds[0].revents & POLLIN) 
      { 

       while ((nbytes = read(fd, buf, sizeof(buf)-1)) > 0) 
       { 

         buf[nbytes] = '\0'; 
        printf("%s\n", buf); 

        } 

       pfds[0].events = 0; 
       pfds[1].events = POLLIN | POLLOUT; 

       } 

      if (pfds[1].revents & POLLIN) 
      { 
       err = recv(SockStorage, strbuf, sizeof(strbuf), 0); 
       if (err < 0) 
       { 
       if (errno != EWOULDBLOCK) 
       { 
        perror(" recv() failed"); 
        state = TRUE; 

       } 
       break; 
       } 

       if (err == 0) 
       { 
       printf(" Connection closed\n"); 
       state = TRUE; 

       break; 
       } 

       dSize = err; 
       printf(" %d bytes received\n", dSize); 
      } 


      if (pfds[1].revents & POLLOUT) 
      { 

      int s; 
      for(s=0; s<MAX_CLIENTS; s++){ 

       if(Clients[s].connected_sock>0){ 

       err = send(Clients[s].connected_sock, buf, strlen(buf), 0); 

       if (err < 0) 
       { 
       perror(" send() failed"); 


       state = TRUE; 

       break; 
       } 

       } 

      } 
      pfds[0].events = POLLIN; 
      pfds[1].events = POLLIN; 
      } 


      } while (TRUE); 

下面是如何發送數據給我的客戶。

int s; 
      for(s=0; s<MAX_CLIENTS; s++){ 

       if(Clients[s].connected_sock>0){ 

       err = send(Clients[s].connected_sock, buf, strlen(buf), 0); 

       if (err < 0) 
       { 
       perror(" send() failed"); 


       state = TRUE; 

       break; 
       } 

       } 

      } 

感謝,

+1

爲每個socket連接 – mathematician1975

+0

你的意思是,每接受一個單獨的線程? – demic0de

+0

是的,你應該有一個單獨的線程,每個接受。你可以閱讀'pthread'庫。 – Raj

回答

0

通常有幾個可能的解決方案:

  1. 您可以使用單獨的線程爲每個客戶端連接;
  2. 您可以使用select;
  3. 您可以使用民意調查;
  4. 你可以使用epoll;

在Windows環境下,也有一些其他的可能性,例如IOCP例如。

上述每種解決方案都有一些優缺點(您通常需要區分簡單性和性能)。

你可以閱讀一些網絡編程教程的詳細信息,例如this

+0

我已閱讀關於libev。我可以使用它嗎? – demic0de

+0

經過一些簡單的檢查後,您似乎可以將其用於您的目的。不過,如果你打算只與幾個客戶端連接,你可以檢查一些「簡單選擇」的例子。 – codewarrior

+0

是的,謝謝你,我設法使它與選擇循環一起工作。非常感謝 – demic0de

相關問題