繁体   English   中英

客户端冻结从套接字读取对象

[英]Client freeze on reading object from socket

我正在通过套接字开发一个简单的Client-Server应用程序,但是我不明白为什么客户端在读取对象时会冻结。 服务器必须能够处理多个客户端。

保持简单,我的服务器看起来像:

    ...
    server_thread = new Thread(new Runnable() {
        @Override
        public void run() {
            int p = 0;
            ObjectInputStream in;
            ObjectOutputStream out;
            NetworkOffer message;    

            try (ServerSocket serverSocket = new ServerSocket(port)) {
                // get connections
                LinkedList<Socket> client_sockets = new LinkedList<>();
                while (p++ < partecipants) client_sockets.add(serverSocket.accept());

                // sending welcome object
                for (Socket socket : client_sockets) {
                    out = new ObjectOutputStream(socket.getOutputStream());
                    message = new NetworkOffer();
                    out.writeObject(buyer_offer);
                }
            ...

我的客户:

    ...
    client_thread = new Thread(new Runnable() {

        @Override
        public void run() {
            ObjectInputStream in;
            NetworkOffer smessage;
            try {
                Socket ssocket = new Socket("localhost", port);
                in = new ObjectInputStream(ssocket.getInputStream());

                // waiting server message
  ------------->Object o = in.readObject();
                smessage = (NetworkOffer)o;


                System.out.println(smessage.toString());
                ...

编辑 :为了使事情更清楚,这是我要实现的协议:

  1. N个客户端连接到服务器
  2. 服务器向客户发送welcome

  3. 每个客户报价

  4. 服务器选择最佳报价,并通过Accept/Reject向每个客户端发送消息
  5. 如果没有可接受的报价,请转到3。

客户端坚持Object o = in.readObject(); 即使服务器已经发送了他的消息。 没错,没事。 线程只是冻结在那里等待某事。

这是怎么回事?

问题是ServerSocket.accept()是一个阻塞调用,这意味着服务器将挂起,直到有人连接到它为止。 当有人连接时,服务器会将新套接字添加到client_sockets 如果添加的套接字数少于participants ,那么它将再次调用accept()并等待另一个连接。 仅当套接字的总数等于participants时,才进入for循环。 您需要产生一个新线程来处理每个传入的客户端套接字,并允许服务器立即返回ServerSocket.accept() 看一下Reactor模式,以了解如何实现此示例。

您的代码应如下所示:

  1. 服务器等待连接。
  2. 当客户端连接时,产生一个新线程来处理连接。
  3. 服务器返回到等待连接。
  4. 新线程在套接字上发送欢迎消息,将套接字添加到client_sockets列表中,并等待客户端提供。
  5. 存储客户报价。
  6. 收到所有报价后,进行比较以找到最佳报价。
  7. 发送Accept/Reject消息。

就像我之前说过的:您确定服务器已将数据发送到客户端-没有缓冲区刷新,因此仍可以对其进行缓存。
out.flush()将确保缓冲区被刷新。 分别处理客户端并向其发送定期消息以更新有关状态的信息将是有意义的。
对于您的服务器代码来说,处理客户端断开/连接断开也很有用。

在侧面说明:

message = new NetworkOffer();
out.writeObject(buyer_offer);

您的代码似乎正在发送示例中未包含的其他内容。 那是对的吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM