-2

为了开发一个可以同时处理最大“x”个客户端的 udp 服务器,我有两个选择:

  1. 当服务器启动时,立即创建“x”线程,而不检查所有“x”客户端是否处于活动状态。

  2. 第二种选择是,当服务器启动时,它会等待客户端的请求,当来自特定客户端的请求到达时,才会生成一个线程来为该客户端提供服务。如果特定客户端出现故障,则专用于该特定客户端的线程也将被删除。

在选项#1 中,即使只有 1 个客户端连接,也会在开始时创建“x”个线程,只有在使用线程并且所有剩余的“x-1”个线程将被挂起时。

在选项#2 中,我似乎将面临连续创建和删除线程的开销。

我决定使用选项#2 来实现我的应用程序,但我仍然对我的选择是否正确感到困惑。

如果我错了,请帮助我。

4

4 回答 4

2

Use a combination of the two by implementing thread pooling. Create a thread pool that is initially empty, or contains a number of initial suspended threads, your choice. When a new client "connects" and does not exceed the max number of allowed clients, check if the pool has an available thread. If so, re-use it. If not, create a new thread. When the client "disconnects", put the thread back into the pool and suspend it. If a given thread stays in the pool for awhile, remove and destroy it.

于 2013-04-27T05:14:20.287 回答
1

考虑线程运行上下文切换的开销。在四核 CPU 上使用三千个线程将比在同一个四核 CPU 上使用四到八个线程引入更多的开销。考虑一下 3000 个线程将使用的资源,就堆栈分配而言,与 4 到 8 个线程相比。

在静态、预定或用户可配置数量的线程上处理尽可能多的非阻塞套接字更有意义。

于 2013-04-27T05:54:44.983 回答
1

选项 3 - 可以根据需要增加和减少的线程池,或者理想情况下,根本不增加和减少。

于 2013-04-27T06:00:02.847 回答
1

您在说什么有点困惑,或者可能需要更多信息。请记住,UDP 客户端不连接它们只是发送数据包,并且不能保证这些数据包按发送顺序到达。

我要做的只是让一个监听 UDP 套接字等待数据包。您应该通过其 IP 地址或任何其他方法维护有效客户端的列表,例如数据包数据中的 ID。收到数据包后,您可以使用处理客户端请求的函数/线程对其进行处理。正如我所看到的,您甚至不需要启动新线程,但这取决于服务器在收到数据包时要做什么以及处理它需要多长时间。另外,请记住处理请求的函数/线程不能从客户端(通过同一端口)接收更多数据包;所有传入的数据包都由服务器线程处理。处理客户端的函数或线程' s request 它所能做的只是向客户端发送一个或多个 UDP 数据包以确认请求,但它无法与客户端保持对话,也无法确定客户端是否已关闭,因为没有永久打开的连接。如果您需要服务器和客户端之间的对话,那么您需要更改为 TCP 套接字。

这是代码草稿:

ClientRequestThread(DatagramPacket packet)
{
    String FromIP = packet.getAddress().getHostAddress();
    byte[] data = packet.getData();
    // Here you must identify the client, either by its IP address 
    // or maybe an ID inside the data.

    if (TheDataHaveBeenProccessOK)
    {
        Send a positive acknowledge
    }
    else
    {
        Send a negative acknowledge
    }
}

ServerThread()
{
    DatagramSocket datagramSocket;
    try
    {
        datagramSocket = new DatagramSocket(MyPortNumber);
    }
    catch (Exception e)
    {
        // Unable to open the datagram socket.
        // Handle it accordingly
        return;
    }

    byte[] buffer = new byte[256]; // change it to your needs
    DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

    while (YouDontStopMe)
    {
        try
        {
            datagramSocket.receive(packet);
// Here you must either call a function or start a thread 
// to handle the client request
// depends on what you are going to do with the client's request.
            ClientRequestThread(packet);
        }
        catch (Exception e)
        {
            // Error reading the socket, handle it accordingly
            e.printStackTrace();
        }
    }
    datagramSocket.close();
}
于 2013-04-27T11:35:15.357 回答