【问题标题】:C++ - Accepting Multiple ClientsC++ - 接受多个客户端
【发布时间】:2013-01-24 23:49:22
【问题描述】:

我真的很难接受多个客户端进入 Socket 服务器。 目前,允许一个客户端。当下一个客户端尝试加入时,应用程序冻结并且什么都不做。

过去一周我对此进行了大量研究,但似乎没有什么能让我满意。 我已经看过关于多线程的教程,但是我没有得到足够的关于函数的信息来实际使用它(是的,我是一个非常直观的学习者,这不是编程的最佳选择)。

所以我只是想知道我是否可以得到一个关于如何做到这一点的体面到很好的解释。 如果可能的话,甚至可以在那里举一个例子。

我也看到了这个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;
}

如您所见,这对我的客户非常有用。但只接受一个。 我该如何解决这个问题?

【问题讨论】:

  • 基于select 的单线程服务器应该是您的第一步。它在概念上很简单,并且对于训练目的相当强大。
  • @KerrekSB 对于生产目的来说它相当强大...... Nginx......
  • 您编写了哪些有效的网络代码?
  • @KerrekSB 我不确定 select 是如何工作的?我查了一下,但我无法理解它。
  • @brianbeuning 只是一个使用 WinSock2 的基本服务器-客户端套接字。它工作正常,所以这不是问题。

标签: c++ multithreading sockets winsock


【解决方案1】:
// 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
    }
}

【讨论】:

  • 好的,在我将它添加到我的代码之前,它是如何工作的?例如,这个“循环”(或任何你想称之为的)套接字是如何实现的?
  • "cannot convert 'readfds' from type 'fd_set' to type 'fd_set*'" 当我将它更改为 "fd_set* readfds" 时,我在 'fd_set' 的 'select' 中得到相同的错误**' 到 'fd_set'
猜你喜欢
  • 2013-02-17
  • 2016-10-05
  • 2015-10-01
  • 1970-01-01
  • 2013-01-24
  • 2014-07-04
  • 1970-01-01
  • 1970-01-01
  • 2014-09-25
相关资源
最近更新 更多