阻止recv()返回小于请求字节的情况

编程入门 行业动态 更新时间:2024-10-25 06:33:59
本文介绍了阻止recv()返回小于请求字节的情况的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

recv() 库函数手册页提到: :

它返回接收到的字节数.通常,它会返回任何可用数据,直到请求的金额,而不是等待收到请求的全部金额.

如果我们正在使用阻塞recv()调用并请求100个字节:

recv(sockDesc, buffer, size, 0); /* Where size is 100. */

,服务器仅发送50个字节,然后阻止此recv()直到100个字节可用,否则它将返回接收50个字节.

情况可能是:

  • 仅50个字节的sendign后服务器崩溃

  • 不良的协议设计,其中服务器仅发送50个字节,而客户端期望100个字节,并且服务器还等待客户端的答复(即,套接字关闭连接尚未由recv将返回的服务器启动)

我对Linux/Solaris平台感兴趣.我没有开发环境可以自己检查.

解决方案

recv将在内部缓冲区中有要返回的数据时返回.如果您请求100个字节,它不会等到100个字节为止.

如果要发送100字节的消息",请记住TCP不提供消息,它只是一个流.如果要处理应用程序消息,则需要在应用程序层进行处理,因为TCP不会这样做.

在很多情况下,调用recv(...,100)时,只有一个recv调用可能无法完全读取另一端的100字节send()调用;这只是一些 例子:

  • 发送方TCP堆栈决定将15个写调用捆绑在一起,而MTU恰好是1460,这取决于到达数据的时间,可能导致客户端的前14个调用获取100个字节,而15个调用.调用以获取60个字节-最后40个字节将在您下次调用recv()时出现. (但是,如果使用缓冲区100调用recv,则可能会获得前一个应用程序的消息"的后40个字节和下一条消息的前60个字节)

  • 发送器缓冲区已满,可能读取器速度很慢,或者网络拥塞.在某些时候,数据可能会通过,在清空缓冲区时,最后一块数据不是100的倍数.

  • 接收方缓冲区已满,而您的应用程序recv()接收到该数据时,它提取的最后一个块只是部分的,因为该消息的整个100字节都不适合缓冲区.

许多情况下很难测试,特别是在局域网上,那里可能没有很多拥塞或数据包丢失-当您提高和降低发送/产生消息的速度时,情况可能会有所不同. /p>

无论如何.如果要从套接字读取100个字节,请使用类似的

int readn(int f, void *av, int n) { char *a; int m, t; a = av; t = 0; while(t < n){ m = read(f, a+t, n-t); if(m <= 0){ if(t == 0) return m; break; } t += m; } return t; }

...

if(readn(mysocket,buffer,BUFFER_SZ) != BUFFER_SZ) { //something really bad is going on. }

The recv() library function man page mention that:

It returns the number of bytes received. It normally returns any data available, up to the requested amount, rather than waiting for receipt of the full amount requested.

If we are using blocking recv() call and requested for 100 bytes:

recv(sockDesc, buffer, size, 0); /* Where size is 100. */

and only 50 bytes are send by the server then this recv() is blocked until 100 bytes are available or it will return receiving 50 bytes.

The scenario could be that:

  • server crashes after sendign only 50 bytes

  • bad protocol design where server is only sending 50 bytes while client is expecting 100 and server is also waiting for client's reply (i.e. socket close connection has not been initiated by server in which recv will return)

I am interested on Linux / Solaris platform. I don't have the development environment to check it out myself.

解决方案

recv will return when there is data in the internal buffers to return. It will not wait until there is 100 bytes if you request 100 bytes.

If you're sending 100 byte "messages", remember that TCP does not provide messages, it is just a stream. If you're dealing with application messages, you need to handle that at the application layer as TCP will not do it.

There are many, many conditions where a send() call of 100 bytes might not be read fully on the other end with only one recv call when calling recv(..., 100); here's just a few examples:

  • The sending TCP stack decided to bundle together 15 write calls, and the MTU happened to be 1460, which - depending on timing of the arrived data might cause the clients first 14 calls to fetch 100 bytes and the 15. call to fetch 60 bytes - the last 40 bytes will come the next time you call recv() . (But if you call recv with a buffer of 100 , you might get the last 40 bytes of the prior application "message" and the first 60 bytes of the next message)

  • The sender buffers are full, maybe the reader is slow, or the network is congested. At some point, data might get through and while emptying the buffers the last chunk of data wasn't a multiple of 100.

  • The receiver buffers are full, while your app recv() that data, the last chunk it pulls up is just partial since the whole 100 bytes of that message didn't fit the buffers.

Many of these scenarios are rather hard to test, especially on a lan where you might not have a lot of congestion or packet loss - things might differ as you ramp up and down the speed at which messages are sent/produced.

Anyway. If you want to read 100 bytes from a socket, use something like

int readn(int f, void *av, int n) { char *a; int m, t; a = av; t = 0; while(t < n){ m = read(f, a+t, n-t); if(m <= 0){ if(t == 0) return m; break; } t += m; } return t; }

...

if(readn(mysocket,buffer,BUFFER_SZ) != BUFFER_SZ) { //something really bad is going on. }

更多推荐

阻止recv()返回小于请求字节的情况

本文发布于:2023-11-29 23:04:53,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1647899.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:字节   情况   recv

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!