我有一个网络应用程序,可能无法访问服务器。客户端在空闲时间每 30 秒通过 TCP 连接向服务器发送字符串
ping\n
,以便服务器可以查看客户端是否在线。我的服务器根本没有响应。如果连接中断并且客户端继续发送“ping”消息,则包可能会被操作系统存储在缓冲区中,直到服务器收到包为止。如果服务器重新上线,服务器可能会同时收到数十个 ping 包。是否可以获得该缓冲区的字节数?
编辑: 如何获取客户端必须发送的字节数?
如果您询问是否可以在调用网络套接字上的 read 之前检测到有多少字节可供读取,简短的回答是否定的。您只能检测是否有any字节可供读取,而不能检测字节数。客户端也可能有字节写入其内核,但被服务器的完整缓冲区阻止,因此服务器本身可能不知道有多少字节可供读取。另外,从客户端来看,没有办法知道有多少数据已被客户端写入但尚未被服务器消费。
数据在客户端和服务器端都进行缓冲,但在 Java 中无法查看这些缓冲区中有多少字节。您也许可以通过 C 中的一些非常具体的内核调用来获取它,但它非常不可移植。
Socket.setKeepAlive(true)
,它将使用 TCP 机制来保持套接字处于活动状态。我不确定服务器端的可靠性如何,但当客户端消失后套接字超时时,它应该从读取中获得 -1。参加聚会已经很晚了,但是当您搜索“linux socket系统调用获取发送队列中的字节计数”时,这个问题首先出现。
实际上有一种方法可以做到这一点,尽管它似乎是特定于 Linux 的。 Linux 有一个名为
ioctl
的 SIOCOUTQ
(与 TIOCOUTQ
相同)和一个 SIOCOUTQNSD
,它们可以起到作用。包含文件中的相关行:
/usr/include/linux/sockios.h
27:#define SIOCOUTQ TIOCOUTQ /* output queue size (not sent + not acked) */
110:#define SIOCOUTQNSD 0x894B /* output queue size (not sent only) */
你可以使用类似的东西
int unsent;
if (ioctl(fd, SIOCOUTQ, &unsent) == -1) {
unsent = -1;
}
查询未发送的字节数,错误则返回-1。
如果你只想检查对方是否还活着,那么最好使用
SIOCOUTQ
,因为你的一方会快速清空其缓冲区,并等待ACK,所以SIOCOUTQNSD
将返回0,而SIOCOUTQ
将返回接收方尚未确认的字节数。如果您认为网络连接可能会过载并且不想在缓冲区中包含超过 n
字节,那么 SIOCOUTQNSD
可能会更好。
是否可以获取该缓冲区的字节数?
如果应用程序缓冲区足够大,下一个成功的 read() 会将其作为返回值。但这对你有什么好处呢?您仍然必须读取所有这些数据并对其进行处理。问题似乎毫无意义。