0

我正在尝试用 Java 创建一个多客户端/服务器应用程序。我遇到了很多问题,因为我的线程似乎被纠缠在一起......这就是我想要做的。

  1. 我有一个使用这段代码接受客户端的服务器类:

    while(true){ 套接字套接字 = serverSocket.accept(); }

  2. 我的服务器应该记住已连接的客户端,因此我使用该套接字创建一个名为 ClientThread 的新线程,并将该线程放在服务器上的列表中

  3. 该线程侦听从客户端发送的命令对象。如果它接收到一个命令,它需要将它发送到服务器实例以进行进一步处理(无需在该 ClientThread 上创建一个新的服务器实例)。我试图通过在创建该线程时将服务器实例添加到该线程来做到这一点。(这是正确的方法吗?)

  4. 我的服务器还应该能够随时将对象发送回客户端(1 个或多个)。我试图通过使用socket.getOutputStream()保存在 ClientThread 中的方法来做到这一点

我应该如何组织我的线程,以便每个客户端都在不断地收听来自服务器的对象,并且他们可以随时将对象发送到服务器。

我知道这并不是一个真正的具体问题,但如果您知道一些可能对这个用例有帮助的信息或教程,我将非常感激。

顺便说一句:我知道如何创建套接字和发送(可序列化)对象等等。我只是坚持如何组织一切

4

2 回答 2

1

由于您已经了解套接字和线程,因此我将想法伪代码发送给您(如果需要代码的特定部分,请告诉我)

您没有提到的一件事是如何通过其 IP o 通过任何其他方法(如 ID)来跟踪客户?任何给定的设备可以打开多个具有不同客户端 ID 的连接吗?或者您只接受每台设备的一个连接?无论如何,如果客户已经在列表中,您打算怎么做?您会将创建的线程与新套接字进行通信吗?您会销毁该线程并创建一个新线程吗?或者您可能会忽略这个新请求?

这是我的想法(取自一个工作应用程序):

服务器准备服务器套接字并在接受状态下等待。

一旦客户端连接,服务器就会启动一个线程来处理客户端,传递它刚刚使用 accept 命令创建的套接字。当参与客户端的线程启动时,它从客户端接收到的第一条消息应该是一个密码或特殊签名,以便让客户端进入(这是可选的)。

服务器代码:

Prepares the server socket which listen in a well known port
Clear client list;

While (!Terminated)
{
      // if you want to impose a limit for connections, check it here:
      if (Is the list of connected client full?)
      {
           Sleep(reasonable time in seconds or miliseconds);
           continue;
       }
       ClientSocket = ServerSocket.Accept();
       if the client's IP is already in the list
       {
           depends on what you want to do.
       }
       else
       {
            Add client's IP to the list
            Start (create) new client Tread(ClientSocket);
       }
}
// when server finish
If (client list is not empty?)
{
   Kill all threads
   or
   Wait until all threads are done
   or
   Wait an amount of time and then kill those remaining.
}

线程客户端代码:

// This is optional, just to make sure a valid client is connected
Read packet from ClientSocket
if (!Is_the_passport_packet)
{
   close socket;
   return;
}

// if passport is not required, start here
Try
{
   While (!Terminated)
   {
      if (read packet from client);
      {
         switch (packet.Command)
         {
 // In your question you said you want the Server thread to process the request
 // I guess you have your requirements to do so,
 // anyway, you must use a mutex o some other synchronization method.
             case TASK_1:
                [sync] process TASK_1(packet, ClientSocket);
                break;
             case TASK_2:
                [sync] process TASK_2(packet, ClientSocket);
                break;
             etc ….

             case WORK_DONE:
                Close Socket;
                return;

             default:
                Log(received an unknown command: packet.command);
                break;

         }
      }
      else if (Client has quit (closed/broken socket))
      {
         // as you may know, a socket is consider shutdown when you received a 0 length data
         // and a broken connection when received -1 in either case all you have to do is
         Close Socket;
         return;
      }
  }
}
catch (Exception e)
{
    Log(received an exception: e.message);
}
finally
{
   Remove this client from the client's list
}
于 2013-05-13T21:52:50.147 回答
1

你似乎有纠结的线程和对象。我会

a) 确保您没有在任何地方扩展 Thread 或调用您的对象 XxxxThread。使用 ExecutorService 来管理你的线程是个好主意。

b) 有一个响应客户端命令的简单模型,例如每个客户端线程读取一个任务,然后执行一个任务。

c) 每个连接都有一个包装器,例如使用 sendMessage 方法。

于 2013-05-13T16:23:26.783 回答