当前位置: 首页 > 知识库问答 >
问题:

在Java建立多客户机/服务器TCP连接

周辰沛
2023-03-14

我正在尝试在Java创建一个多客户机/服务器应用程序。我有些问题因为我的线好像纠缠在一起了...这就是我要做的。

>

  • 我有一个服务器类,它通过使用以下代码来接受客户端:

    while(true){Socket Socket=ServerSocket.Accept();}

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

    该线程侦听从客户端发送的命令对象。如果它接收到一个命令,它需要将其发送到服务器实例以进行进一步的处理(而不需要在那个ClientThread上创建一个新的服务器实例)。我尝试在创建线程时将服务器实例添加到线程中。(这条路对吗?)

    我的服务器还应该能够在任何时候将对象发送回客户端(1个或多个)。我尝试使用保存在ClientThread中的socket.getOutputStream()来实现这一点

    我应该如何组织我的线程,这样每个客户端都在不断地监听从服务器接受对象,并且他们可以随时向服务器发送对象。

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

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

  • 共有2个答案

    牧信厚
    2023-03-14

    由于您已经了解了套接字和线程,所以我给您发送了idea pseudo代码(如果需要特定部分的代码就让我知道)

    您没有提到的一件事是如何跟踪客户机,通过它的IP或任何其他方法,如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
    }
    
    戈华茂
    2023-03-14

    你似乎有纠缠的线和物体。我会的

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

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

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

     类似资料:
    • 我在Java开发了一个客户端-服务器游戏(称为“Set”)。 在调试过程中遇到了一个非常尴尬的问题: 如果在同一台机器上同时运行客户端和服务器(客户端连接到localhost),这个游戏工作得很棒(如果我运行服务器和大量客户端的话也是如此)。 但是,如果我在两台不同的机器上运行客户端和服务器,那么客户端和服务器都挂起了Inputstream readLine方法。 我会提到我正在使用writeBy

    • 在Mac OS X 10.8机器上,我有一台Tomcat 7.0.40服务器和一台客户端,都在本地运行。通过三方握手建立TCP连接,然后立即从服务器发送FIN、ACK和RST。客户端收到“来自服务器的文件结束”或“连接重置”。 TCP序列: 客户端SYN 服务器SYN,确认 客户端确认 服务器[TCP窗口更新]确认字符 服务器FIN,确认字符 客户端确认字符 服务器[TCP Dup确认字符]确认字

    • 有没有一种简单的方法可以使用java程序重现tcp CLOSE_WAIT状态? 我有一个遗留的java应用程序存在这个问题,我希望能够重现它,以便测试我的修复。 谢谢

    • 编辑2:我切换到,并用包装客户端工厂,这样设备就可以很好地到达后端。但是当后端发回一些东西时,我会得到错误的出站套接字,客户机套接字死亡。我认为这是因为后端没有正确路由消息所必需的头。如何捕获此信息?我的配置类如下:

    • 真的需要你帮忙。 我的项目是通过电缆连接两台PC机,并使用tcp套接字将客户端文本框形式的字符串发送到服务器。问题是ATI只能发送一个字符串,然后连接就会关闭。 注意:某个端口上的连接将在表单加载中建立并成功。