2013-01-24 150 views
0

我真的有麻煩,接受多個客戶端到Socket服務器。 目前,允許一個客戶端。當下一個客戶端嘗試加入時,該應用會凍結並且什麼也不做。C++ - 接受多個客戶端

上週我已經做了大量的研究,但沒有任何東西能滿足我。 我看過關於多線程的教程,但是我沒有給出足夠的關於函數的信息來實際使用它(是的,我是一個非常直觀的學習者,這不是編程的最佳選擇)。

所以我只是想知道如果我能得到一個體面的如何做到這一點很好的解釋。 如果可能的話,甚至可能會拋出一個例子。

我也看到這個select()函數,其中我也沒有提供足夠的信息。

雖然我確實有一個運行和工作的服務器,但多線程真的開始攪亂我的頭腦,我對這種情況以及它的工作方式感到非常困惑。

所以如果我能給出一個解釋和例子,那會很棒!

這是我目前的服務器代碼,我將如何啓用多個客戶端?

#include <iostream> 
#include <winsock2.h> 
#include <vector> 

bool gamerunning = true; 
bool srvr_connect = false; 
int srvr_rec = 0; 

int main() { 
    WSAData wsa; 
    WORD Version = MAKEWORD(2, 1); 

    WSAStartup(Version, &wsa); 

    SOCKET Listen; 
    SOCKET Connect; 

    Listen = socket(AF_INET, SOCK_STREAM, 0); 
    Connect = socket(AF_INET, SOCK_STREAM, 0); 

    SOCKADDR_IN Server; 

    Server.sin_addr.s_addr = inet_addr("192.168.2.4"); 
    Server.sin_family = AF_INET; 
    Server.sin_port = htons(100); 

    bind(Listen, (SOCKADDR*)&Server, sizeof(Server)); 

    listen(Listen, 4); 

    int size = sizeof(Server); 

    std::cout << "Your server has been started!\nConnecting...\n"; 

    Connect = accept(Listen, (SOCKADDR*)&Server, &size); 

    while (gamerunning) { 
     if (Connect != NULL) { 
      srvr_connect = true; 
      std::cout << "Welcome to player: " << srvr_rec << "\n"; 
      srvr_rec +=1; 
     } 
     if (srvr_connect == true) { 
      if (test_frame == 0) { 
       std::cout << "Connection Sent!\nConnection Has Been Breached!\nPlayers Are Now Able to Join Your Server!\n"; 
       test_frame +=1; 
      } 
     } 
    } 
    std::cin.get(); 
    return 0; 
} 

正如您所看到的,這對我的客戶非常有用。但只接受一個。 我該如何解決這個問題?

+3

單線程'基於select'服務器應該是你的第一步。它在概念上很簡單,對於培訓目的來說也是合理的。 –

+0

@KerrekSB這對於生產目的來說是相當強大的... Nginx ... –

+1

你寫的那種網絡代碼有效嗎? –

回答

0
// define a list of sockets 
// create the socket you are going to accept on and add the socket to the list 
while(true) { 
    // use the list to build the read set 
    select(.. read-set ..) 
    for(all sockets in the read-set) { 
     if(socket == accept-socket) { 
       // do accept 
       // add the new socket to the list 
     } else { 
       // read data from the socket 
     } 
    } 
} 

你可以使用select()這樣的

fd_set readfds; 
fd_set writefds; 
fd_set exceptfds; 
FD_ZERO(readfds); 
FD_ZERO(writefds); 
FD_ZERO(exceptfds); 
int nfds = 0; 
for(all socket x in socket list) { 
    FD_SET(x, readfds) 
    nfds++; 
} 
int rc = select(nfds, & readfds, & writefds, & exceptfds, 0); 
for(all socket x in socket list) { 
    if(FD_ISSET(x, readfds)) { 
     // socket x has something to read or accept 
    } 
} 
+0

好吧,在我將它添加到我的代碼之前,這是如何工作的?例如,這個「循環」(或者任何你想要調用它的)套接字是如何的? 「 – user2009320

+0

」當我將其改爲「fd_set * readfds」時,無法將'readfds'從'fd_set'類型轉換爲鍵入'fd_set *'「,然後在'select'中將'fd_set **'更改爲'fd_set' – user2009320

+0

我上面發佈了我的代碼。你能幫忙嗎? – user2009320