我一定在使用recv()从TCP套接字接收数据的地方遇到了缓冲区限制
我正在从通过 TCP 套接字连接的测试仪器下载 6kB 的数据。我正在使用 SOCK_STREAM:
if((MySocket=socket(PF_INET,SOCK_STREAM,0))==-1) exit(1);
我没有设置任何缓冲区大小,所以我假设我正在使用默认值。我在接收数据时遇到问题。声明如下:
if((recv(MySocket, &YRaw[indx], sizeChunk*2, 0))==-1)
{perror("recv()"); exit(9); } // where sizeChunk=3000; sizeof(YRaw[0])=2
其中YRaw是一个3000个对象的数组,每个对象为2个字节。
运行代码后我观察到的问题是,YRaw 数组的大约 3/4 处有一串零,这是我将数组初始化为的值。看起来接收函数在达到数组的 3/4 时工作正常,然后跳过 YRaw 数组的一块(保留初始化值),然后再次拾取,然后 YRaw 数组填满。缓冲区中剩余要读取的数据,等于 YRaw 数组中跳过的值的数量。
我怀疑这与系统中的某些缓冲区有关。任何人都可以阐明如何解决这个问题吗?
我不知道是否相关,但我还设置了 TCP_NODELAY,如下所示:
// TCP_NODELAY option minimizes latency by instructing system to send small msgs immediately
// Insert setsockopt() before connect() occurs
int StateNODELAY = 1; // turn NODELAY on
if(setsockopt(MySocket, IPPROTO_TCP,TCP_NODELAY,
(void *) &StateNODELAY, sizeof StateNODELAY)==-1) {perror("setsockopt()"); exit(2); };
最好的问候,gkk
I'm downloading 6kB of data from a test instrument connected via TCP socket. I'm using SOCK_STREAM:
if((MySocket=socket(PF_INET,SOCK_STREAM,0))==-1) exit(1);
I haven't set the any buffer sizes, so I assume I'm using whatever the default is. I'm having a problem with receiving data. Here's the statement:
if((recv(MySocket, &YRaw[indx], sizeChunk*2, 0))==-1)
{perror("recv()"); exit(9); } // where sizeChunk=3000; sizeof(YRaw[0])=2
where YRaw is a 3000 object array, each object is 2 bytes.
The problem I observe after running the code, is that about 3/4 of the way through YRaw array, there's a string of zeros, which are what I initialized the array to. It appears the receive function works fine up to 3/4 of the array, then skips a chunk of YRaw array (leaving the initialized values), then picks up again, and the YRaw array fills up. There's data remaining in the buffer to read, equal to the number of values skipped in the YRaw array.
I suspect this is related to some buffer in the system. Can anyone shed some light on how to fix this?
I don't know if it's related, but I also set TCP_NODELAY, shown here:
// TCP_NODELAY option minimizes latency by instructing system to send small msgs immediately
// Insert setsockopt() before connect() occurs
int StateNODELAY = 1; // turn NODELAY on
if(setsockopt(MySocket, IPPROTO_TCP,TCP_NODELAY,
(void *) &StateNODELAY, sizeof StateNODELAY)==-1) {perror("setsockopt()"); exit(2); };
Best regards, gkk
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
recv()
不一定填满整个缓冲区。它只读取可用的内容并返回已读取的字节数。因此,请检查返回值以查看有多少数据可用,处理该数据,然后再次调用
recv()
直到收到所需的所有数据。recv()
doesn't necessarily fill the whole buffer. It just reads whatever is available and returns how many bytes have been read.So inspect the return value to see how much data was available, process that data, and call
recv()
again until you received all the data you expect.您应该明确存储
recv
的结果(即不仅检查它是否为-1)。这是实际读取的字节大小,您需要它来知道缓冲区中有多少字节是有效的。除此之外,您应该检查是否可以在不阻塞的情况下读取更多字节,并读取更多字节直到发生阻塞。
缓冲区大小限制可以存在于系统中的任何位置,例如以太网 MTU,甚至可以存在于发送设备上。
You should definitively store the result of
recv
(i.e. not only check whether it's -1 or not). That's the size of bytes actually read and you need this to know how many bytes are valid in your buffer.Apart from that, you should check if you can read more bytes without blocking and read more until it would block.
Buffer size limitations can be anywhere in the system, e.g. the Ethernet MTU or even on your sending device.