如何获取Socket的SendBuffer中的字节数?

问题描述 投票:0回答:3

我有一个网络应用程序,可能无法访问服务器。客户端在空闲时间每 30 秒通过 TCP 连接向服务器发送字符串

ping\n
,以便服务器可以查看客户端是否在线。我的服务器根本没有响应。如果连接中断并且客户端继续发送“ping”消息,则包可能会被操作系统存储在缓冲区中,直到服务器收到包为止。如果服务器重新上线,服务器可能会同时收到数十个 ping 包。是否可以获得该缓冲区的字节数?

编辑: 如何获取客户端必须发送的字节数?

java sockets tcp protocol-buffers
3个回答
0
投票

如果您询问是否可以在调用网络套接字上的 read 之前检测到有多少字节可供读取,简短的回答是否定的。您只能检测是否有any字节可供读取,而不能检测字节数。客户端也可能有字节写入其内核,但被服务器的完整缓冲区阻止,因此服务器本身可能不知道有多少字节可供读取。另外,从客户端来看,没有办法知道有多少数据已被客户端写入但尚未被服务器消费。

数据在客户端和服务器端都进行缓冲,但在 Java 中无法查看这些缓冲区中有多少字节。您也许可以通过 C 中的一些非常具体的内核调用来获取它,但它非常不可移植。

  • 需要考虑的一件事是使用
    Socket.setKeepAlive(true)
    ,它将使用 TCP 机制来保持套接字处于活动状态。我不确定服务器端的可靠性如何,但当客户端消失后套接字超时时,它应该从读取中获得 -1。
  • 另一种方法是为每个 ping 建立单独的 TCP 连接。如果这太昂贵,那么您可以在一定次数的 ping 尝试后重新连接。
  • 要考虑的第三件事是从客户端发送 UDP 数据包,该数据包不会被缓冲并且成本要低得多。您应该更频繁地发送,因为也没有重试。
  • 服务器还可以发回某种响应,以便客户端知道客户端知道套接字仍然良好。如果没有得到响应,它可以重新连接。

0
投票

参加聚会已经很晚了,但是当您搜索“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
可能会更好。


-1
投票

是否可以获取该缓冲区的字节数?

如果应用程序缓冲区足够大,下一个成功的 read() 会将其作为返回值。但这对你有什么好处呢?您仍然必须读取所有这些数据并对其进行处理。问题似乎毫无意义。

© www.soinside.com 2019 - 2024. All rights reserved.