简体   繁体   English

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

[英]Client freeze on reading object from socket

I'm developing a simple Client-Server application over socket, but I can't get why client freezes when he is reading an object. 我正在通过套接字开发一个简单的Client-Server应用程序,但是我不明白为什么客户端在读取对象时会冻结。 Server must be capable of dealing with multiple client. 服务器必须能够处理多个客户端。

Keeping it simple, my Server looks like: 保持简单,我的服务器看起来像:

    ...
    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);
                }
            ...

My Client: 我的客户:

    ...
    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());
                ...

EDIT : To make things clearer, this is the protocol I want to implement: 编辑 :为了使事情更清楚,这是我要实现的协议:

  1. N clients connect to Server N个客户端连接到服务器
  2. Server send welcome to Clients 服务器向客户发送welcome

  3. Every client makes an offer 每个客户报价

  4. Server chooses best offer, and sends a message to each Client with Accept/Reject 服务器选择最佳报价,并通过Accept/Reject向每个客户端发送消息
  5. If there isn't an acceptable offer goto 3. 如果没有可接受的报价,请转到3。

Client sticks on Object o = in.readObject(); 客户端坚持Object o = in.readObject(); even if server has already sent his message. 即使服务器已经发送了他的消息。 No error, nothing. 没错,没事。 Thread is simply freezed there waiting for something. 线程只是冻结在那里等待某事。

What's going on? 这是怎么回事?

The problem is ServerSocket.accept() is a blocking call meaning the server will hang until somebody connects to it. 问题是ServerSocket.accept()是一个阻塞调用,这意味着服务器将挂起,直到有人连接到它为止。 When somebody connects, the server will add that new socket to the client_sockets . 当有人连接时,服务器会将新套接字添加到client_sockets If the number of sockets added is less than participants , it will then call accept() again and wait for another connection. 如果添加的套接字数少于participants ,那么它将再次调用accept()并等待另一个连接。 It will only enter your for loop when the total number of sockets is equal to participants . 仅当套接字的总数等于participants时,才进入for循环。 You need to spawn a new thread to handle each incoming client socket and allow the server to return immediately to ServerSocket.accept() . 您需要产生一个新线程来处理每个传入的客户端套接字,并允许服务器立即返回ServerSocket.accept() Have a look at the Reactor pattern for a good example of how to implement this. 看一下Reactor模式,以了解如何实现此示例。

What your code should look like is this: 您的代码应如下所示:

  1. Server waits for connections. 服务器等待连接。
  2. When client connects, spawn a new thread to handle the connection. 当客户端连接时,产生一个新线程来处理连接。
  3. Server returns to waiting for connections. 服务器返回到等待连接。
  4. New thread sends welcome message on socket, adds the socket to the list of client_sockets and waits for the clients offer. 新线程在套接字上发送欢迎消息,将套接字添加到client_sockets列表中,并等待客户端提供。
  5. Store the clients offer. 存储客户报价。
  6. When all offers have been received, compare to find the best. 收到所有报价后,进行比较以找到最佳报价。
  7. Send Accept/Reject messages. 发送Accept/Reject消息。

As I said before: are you sure that the server have sent the data to the client - there is no buffer flush so it can still be cached. 就像我之前说过的:您确定服务器已将数据发送到客户端-没有缓冲区刷新,因此仍可以对其进行缓存。
out.flush() will make sure that buffer is flushed. out.flush()将确保缓冲区被刷新。 It will make sense to handle clients separately and send them periodic messages to update them about the status. 分别处理客户端并向其发送定期消息以更新有关状态的信息将是有意义的。
It is useful for your server code to handle the client disconnect/connection drop too. 对于您的服务器代码来说,处理客户端断开/连接断开也很有用。

On the side note: 在侧面说明:

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

Your code seems to be sending something else that is not present in your example. 您的代码似乎正在发送示例中未包含的其他内容。 Is that correct? 那是对的吗?

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

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