我正在通过套接字开发一个简单的客户端 - 服务器应用程序,但我无法理解为什么客户端在读取对象时会冻结。 服务器必须能够处理多个客户端。
保持简单,我的服务器看起来像:
...
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());
...
修改: 为了使事情更清楚,这是我想要实现的协议:
服务器向客户端发送welcome
每位客户提出要约
Accept/Reject
即使服务器已经发送了他的消息,客户端仍然会Object o = in.readObject();
。
没有错误,没有。线程只是在那里等待一些东西冻结。
发生了什么事?
答案 0 :(得分:1)
问题是ServerSocket.accept()
是一个阻塞调用,这意味着服务器将挂起,直到某人连接到它。当有人连接时,服务器会将新套接字添加到client_sockets
。如果添加的套接字数小于participants
,则会再次调用accept()
并等待另一个连接。只有当套接字总数等于for
时,它才会进入participants
循环。您需要生成一个新线程来处理每个传入的客户端套接字,并允许服务器立即返回ServerSocket.accept()
。查看Reactor模式,了解如何实现此功能。
您的代码应该是这样的:
client_sockets
列表并等待客户端报价。Accept/Reject
条消息。答案 1 :(得分:1)
正如我之前所说:你确定服务器已经将数据发送到客户端 - 没有缓冲区刷新,所以它仍然可以被缓存。
out.flush()
将确保刷新缓冲区。
分别处理客户端并定期发送消息以更新状态是有意义的
您的服务器代码也可以处理客户端断开/连接丢弃。
旁注:
message = new NetworkOffer();
out.writeObject(buyer_offer);
您的代码似乎正在发送您的示例中不存在的其他内容。这是对的吗?