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

时间:2014-03-14 10:29:07

标签: java sockets

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

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

    ...
    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. 向每个客户发送消息
  6. 如果没有可接受的报价转到3。
  7. 即使服务器已经发送了他的消息,客户端仍然会Object o = in.readObject();。 没有错误,没有。线程只是在那里等待一些东西冻结。

    发生了什么事?

2 个答案:

答案 0 :(得分:1)

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

您的代码应该是这样的:

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

答案 1 :(得分:1)

正如我之前所说:你确定服务器已经将数据发送到客户端 - 没有缓冲区刷新,所以它仍然可以被缓存。
out.flush()将确保刷新缓冲区。 分别处理客户端并定期发送消息以更新状态是有意义的 您的服务器代码也可以处理客户端断开/连接丢弃。

旁注:

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

您的代码似乎正在发送您的示例中不存在的其他内容。这是对的吗?