Java-奇怪的悬挂式插座?
我有一个带有java服务器的客户机-服务器应用程序。它的工作原理非常完美,只是经过一段时间的延长,突然之间,一个插座一直挂着。这个套接字只是许多套接字中的一个,其余的看起来仍然很好,但是一旦它到达套接字,服务器就不会通过发送线路。以下是代码的相关部分:Java-奇怪的悬挂式插座?,java,sockets,Java,Sockets,我有一个带有java服务器的客户机-服务器应用程序。它的工作原理非常完美,只是经过一段时间的延长,突然之间,一个插座一直挂着。这个套接字只是许多套接字中的一个,其余的看起来仍然很好,但是一旦它到达套接字,服务器就不会通过发送线路。以下是代码的相关部分: Socket socket; // A normal socket out = new PrintWriter(socket.getOutputStream(), true); // The outstream out.println(msg
Socket socket; // A normal socket
out = new PrintWriter(socket.getOutputStream(), true); // The outstream
out.println(msg + "\0"); // This command is used to send stuff, msg is a String
没有抛出异常,行应用程序似乎根本没有通过该行:
out.println(msg + "\0");
我确实知道这个字符串是一个好的字符串,因为在这个字符串发送它之前,还有4或5个其他套接字。还要注意的是,据我所知,这个套接字可以在突然挂起之前发送数百条消息。有人知道我应该寻找什么样的错误吗?有很多因素可能会导致这种情况,但听起来你可能在TCP级别受到了反压力 通常,当您在套接字上发送数据时,它只是被缓冲,发送调用(在您的情况下,
println()
和flush()
)可以在数据实际发送到网络之前返回。这可能是因为您以前在此套接字上的所有写入操作都只是缓冲到本地,而您只是将其填满
(1) 您能否使用tcpdump或Wireshark跟踪此情况,并找到挂起的确切连接(我知道很多连接都很难做到这一点)?在程序挂起时检查TCP窗口大小将告诉您更多关于是在Java本身还是在网络级别阻塞的信息
(2) 转储堆栈并将其张贴在此处。Java套接字有一个内部锁,以防止两个线程同时向它们写入数据。您确定在您尝试写入时只有一个线程正在访问该套接字吗
你肯定想试着做一个
$ jstack <PID>
$jstack
当它被冻结以查看其挂起的确切位置,以及写入线程是否试图获取任何锁。当本地套接字缓冲区已满时,
Socket
对象的OutputStream
将在写入时阻塞,与底层send()
调用阻塞的条件相同。它保持阻塞状态表示无法清空输出缓冲区,这反过来表示连接另一端的读取缓冲区已满,并且处理连接另一端的应用程序没有读取已经到达的数据。您在哪个操作系统上运行?您正在与附近或远处的某物通话?检查发送/接收队列大小?听起来像是我最近遇到的一个问题,缓冲区填满了,导致连接的其余部分挂起。你确定套接字有一个活动的读卡器,而不仅仅是缓冲区满了吗?