什么是字节的最低数量,会导致Socket.Receive回来? [英] What is the minimum number of bytes that will cause Socket.Receive to return?

查看:178
本文介绍了什么是字节的最低数量,会导致Socket.Receive回来?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们使用的应用协议,它指定在第一个4字节的消息的长度指示符。 Socket.Receive将返回尽可能多的数据在此时的协议栈或阻塞,直到数据可用。这就是为什么我们有,直到我们收到了长度指示器的字节数不间断的从套接字读取。如果对方关闭了连接的Socket.Receive将返回0。我明白了这一切。



是否有已被读取的字节数量最少?我想问的原因是从文档似乎完全有可能整个长度指标(4字节)可能不可用时socket.Receive可以返回。然后,我们就必须有不断尝试。这将是更有效的,以尽量减少我们称之为socket.receive,因为它具有在与出缓冲器的复制物的次数。因此,它是更安全的同时获得长度指标得到一个单字节,它是安全的假设,4个字节将始终可用,或者我们应该不断尝试使用偏移变量拿到4个字节?



这是我认为有可能是某种默认的最低水平的原因是,我遇到了一个名为ReceiveLowWater变量,我可以在套接字选项设置varaible来了。但是,这似乎只适用于BSD。 MSDN 见SO_RCVLOWAT



这是不是真的那么重要,但我想要编写单元测试。我已经包裹标准的.NET的Socket接口后面。


解决方案

是安全的假设这4个字节将始终可用。




没有。决不。如果有人用,比方说,telnet和键盘测试协议?或通过真正的缓慢或繁忙的连接?您的可以的接收一次一个字节或分裂长度指示在多个接收()来电。这不是单元测试的问题,它是基本的socket此事引起生产中的问题,尤其是在紧张的情况下。




还是应该继续努力使用偏移变量拿到4个字节?




是的,你应该。为了您的方便,你可以使用 Socket.Receive() 读取重载允许您指定的字节数,所以你不会看太多。但请注意它的可以的回报低于需要,这就是偏移参数是什么,所以它可以继续在同一个缓冲区写:

 字节[] = lenBuf新的字节[4]; 
INT偏移= 0;

而(偏移下; lenBuf.Length)
{
INT接收= socket.Receive(lenBuf,胶印,lenBuf.Length - 偏移,0);

偏差+ =接受;如果

(收到== 0)
{
//连接正常关闭,做你的事来处理
}
}

//在这里你就可以解析lenBuf




我认为有可能是某种默认的最低水平的原因是,我遇到了一个名为ReceiveLowWater变量,我可以在套接字选项设置varaible来了。但是,这似乎只适用于BSD。




这是正确的,接受低水标志只是为了向后兼容,所以没有任何除了引发错误,按 MSDN ,搜索为 SO_RCVLOWAT




这个选项不被Windows TCP / IP供应商支持。如果该选项用于在Windows Vista和更高版本,以及的getsockopt功能的setsockopt失败,WSAEINVAL。在早期版本的Windows中,这些函数失败,WSAENOPROTOOPT。所以,我想你将不得不使用的偏移量。




这是一个耻辱,因为它的可以的增强性能,但由于@cdleonard在评论中指出,从饲养的偏移变量将是最小的,因为you'l的的性能损失通常是的一下子收到四个字节。


We are using a application protocol which specifies the length indicator of the message in the first 4 bytes. Socket.Receive will return as much data as in the protocol stack at the time or block until data is available. This is why we have to continously read from the socket until we receive the number of bytes in the length indicator. The Socket.Receive will return 0 if the other side closed the connection. I understand all that.

Is there a minimum number of bytes that has to be read? The reason I ask is from the documentation it seems entirely possible that the entire length indicator (4 bytes) might not be available when socket.Receive can return. We would then have to have to keep trying. It would be more efficient to minimize the number of times we call socket.receive because it has to copy things in and out of buffers. So is it safer to get a single byte at a time to get the length indicator, is it safe to assume that 4 bytes will always be available or should we keep trying to get 4 bytes using an offset variable?

The reason that I think that there may be some sort of default minimum level is that I came across a varaible called ReceiveLowWater variable that I can set in the socket options. But this appears to only apply to BSD. MSDN See SO_RCVLOWAT.

It isn't really that important but I am trying to write unit tests. I have already wrapped a standard .Net Socket behind an interface.

解决方案

is it safe to assume that 4 bytes will always be available

NO. Never. What if someone is testing your protocol with, say, telnet and a keyboard? Or over a real slow or busy connection? You can receive one byte at a time or a split "length indicator" over multiple Receive() calls. This isn't unit testing matter, it's basic socket matter that causes problems in production, especially under stressful situations.

or should we keep trying to get 4 bytes using an offset variable?

Yes, you should. For your convenience, you can use the Socket.Receive() overload that allows you to specify a number of bytes to be read so you won't read too much. But please note it can return less than required, that's what the offset parameter is for, so it can continue to write in the same buffer:

byte[] lenBuf = new byte[4];
int offset = 0;

while (offset < lenBuf.Length)
{       
    int received = socket.Receive(lenBuf, offset, lenBuf.Length - offset, 0);

    offset += received;     

    if (received == 0)
    {
        // connection gracefully closed, do your thing to handle that
    }
}

// Here you're ready to parse lenBuf

The reason that I think that there may be some sort of default minimum level is that I came across a varaible called ReceiveLowWater variable that I can set in the socket options. But this appears to only apply to BSD.

That is correct, the "receive low water" flag is only included for backwards compatibility and does nothing apart from throwing errors, as per MSDN, search for SO_RCVLOWAT:

This option is not supported by the Windows TCP/IP provider. If this option is used on Windows Vista and later, the getsockopt and setsockopt functions fail with WSAEINVAL. On earlier versions of Windows, these functions fail with WSAENOPROTOOPT". So I guess you'll have to use the offset.

It's a shame, because it can enhance performance. However, as @cdleonard pointed out in a comment, the performance penalty from keeping an offset variable will be minimal, as you'l usually receive the four bytes at once.

这篇关于什么是字节的最低数量,会导致Socket.Receive回来?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆