缓冲插座读数

时间:2010-07-15 17:09:06

标签: ruby sockets networking

我遇到了问题 - 我不知道发送到UDP服务器的数据量。

目前的代码就是这样 - 用irb进行测试:

require 'sockets'
sock = UDPSocket.new
sock.bind('0.0.0.0',41588)

sock.read # Returns nothing
sock.recvfrom(1024) # Requires length of data to be read - I don't know this

我可以将recvfrom设置为65535或其他一些大数字,但这似乎是一个不必要的黑客。

recvfrom和recvfrom_nonblock都会在指定的长度之后扔掉任何东西。

我是否错误地设置了套接字?

2 个答案:

答案 0 :(得分:4)

请注意,UDP是数据报协议,而不是像TCP一样的。 UDP套接字的每次读取都会使一个完整的数据报出列。您可以将这些标记传递给recvfrom(2)

MSG_PEEK

    This  flag  causes  the  receive operation to return
    data from the beginning of the receive queue without
    removing that data from the queue. Thus, a subsequent
    receive call will return the same data.

MSG_WAITALL

    This flag requests that the operation block until the
    full request is satisfied. However, the call may still
    return less data than requested if a signal is caught,
    an error or disconnect occurs, or the next data to be
    received is of a different type than that returned.

MSG_TRUNC

    Return the real length of the packet, even when it was
    longer than the passed buffer. Only valid for packet sockets.

如果你真的不知道你可能得到多大的数据包(协议限制为65507字节,请参阅here)并且不关心系统调用次数加倍,首先是MSG_PEEK,然后从套接字中读取确切的字节数。

或者您可以设置近似的最大缓冲区大小,例如4096,然后使用MSG_TRUNC检查是否丢失了任何数据。

另请注意,UDP数据报很少大于1472 - 以太网数据大小1500减去20字节的IPv4标头减去8字节的UDP标头 - 没人喜欢碎片。

编辑:

Socket::MSG_PEEK在那里,对于其他人,您可以使用整数值:

MSG_TRUNC   0x20
MSG_WAITALL 0x100

查看系统标题(Linux上的/usr/include/bits/socket.h)以确定。

答案 1 :(得分:2)

查看Ruby的recvfrom()的文档,该参数是最大长度。只需提供65535(UDP数据报的最大长度);返回的数据应该是它发生的任何大小的发送数据报,你应该能够像Ruby中任何类似字符串的东西那样确定它的大小。