【发布时间】:2016-10-18 12:22:35
【问题描述】:
我正在编写客户端/服务器应用程序,其中多个客户端连接到服务器并通过 TCP 连接以高速率连续向服务器发送序列化对象。
我在客户端使用 ObjectOutputStream.writeObject,在服务器使用 ObjectInputStream.readObject。
服务器应用程序使用 serverSocket.accept() 在单个端口上接受客户端连接,并将 Socket 传递给新线程以读取对象。
当单个客户端连接并发送大约 25K 个对象/秒时 - 一切正常。一旦我启动第二个客户端,在很短的时间之后,一个或两个客户端都挂在其中一台服务器的 ObjectOutputStream.writeObject 上,而相应的服务器挂起在 ObjectInputStream.readObject 上。 双方都没有抛出异常。
如果速率非常低,假设总共 10-20/s - 它不会挂起,但在 100-1000/s 时会挂起。
在客户端机器上使用netstat -an可以看到对应链接的send-Q大概有30K左右。在服务器端,receive-Q 也是 ~30K。
在本地 Windows 上运行客户端/服务器时,我观察到类似的情况 - 客户端挂起,但服务器继续处理传入的对象,一旦赶上,客户端解锁并继续发送对象。
在本地,在 windows 上,服务器比客户端慢,但在 linux 上,运行在不同机器上的服务器实例数量足以满足客户端产生的速度。
有什么线索吗?
客户端代码片段:
Socket socket = new Socket(address, port);
ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
while(true)
{
IMessage msg = createMsg();
outputStream.writeObject(msg);
outputStream.flush();
outputStream.reset();
}
接受连接的服务器代码:
while(active)
{
Socket socket = serverSocket.accept();
SocketThread socketThread = new SocketThread(socket);
socketThread.setDaemon(true);
socketThread.start();
}
服务器代码读取对象:
public class SocketThread extends Thread
{
Socket socket;
public SocketThread(Socket socket)
{
this.socket = socket;
}
@Override
public void run() {
try {
ObjectInputStream inStream = new ObjectInputStream(socket.getInputStream());
while(true)
{
IMessage msg = (IMessage)inStream.readObject();
if(msg == null){
continue;
}
List<IMessageHandler> handlers = handlersMap.get(msg.getClass());
for(IMessageHandler handler : handlers){
handler.onMessage(msg);
}
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
【问题讨论】:
-
NB
readObject()不会返回 null,除非您发送 null。如果您不打算这样做,那么空测试毫无意义。
标签: java sockets tcp objectinputstream objectoutputstream