一直以为在阻塞的tcp socket上使用read/recv读取的数据长度一定和指定的读取长度一致,但是实际测试时发现往往返回的长度都比指定长度短,查找资料发现其实是一直误解了这个函数。
引用《UNIX网络编程 卷一 套接字联网API》3.9中的说法:
字节流套接口(如tcp套接口)上的read和write函数所表现的行为不同于通常的文件IO。字节流套接口上的读或写输入或输出的字节数可能比要求的数量少,但这不是错误状况,原因是内核中套接口的缓冲区可能已达到了极限。此时所需的是调用者再次调用read或write函数,以输入或输出剩余的字节。
书中给出了readn和writen函数解决这个问题。
ssize_t /* Read "n" bytes from a descriptor. */
readn(int fd, void *vptr, size_t n)
{
size_t nleft;
ssize_t nread;
char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nread = read(fd, ptr, nleft)) < 0) {
if (errno == EINTR)
nread = 0; /* and call read() again */
else
return(-1);
} else if (nread == 0)
break; /* EOF */
nleft -= nread;
ptr += nread;
}
return(n - nleft); /* return >= 0 */
}
ssize_t /* Write "n" bytes to a descriptor. */
writen(int fd, const void *vptr, size_t n)
{
size_t nleft;
ssize_t nwritten;
const char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
if (nwritten < 0 && errno == EINTR)
nwritten = 0; /* and call write() again */
else
return(-1); /* error */
}
nleft -= nwritten;
ptr += nwritten;
}
return(n);
}
在13.3中提供了另外一个选择:
在recv中,可以使用MSG_WAITALL标志保证要求读取的字节数。即使使用了MSG_WAITALL标志,如果发生了下列情况:(a)捕获一个信号(b)连接被终止,或(c)在套接口上发生错误,这个函数返回的字节数仍会比请求的少。
而且要注意的是这个标志并不是每个版本的recv都会实现的。
分享到:
相关推荐
关于recv函数在不知道接收数据大小时如何申请buffer
本文主要介绍了python网络编程调用recv函数完整接收数据的三种方法。具有很好的参考价值,下面跟着小编一起来看下吧
一个很详细的文档,基于c++ winsocket的非阻塞服务器开发
采用C++开发的服务端和客户端均可运用TCP通信收发结构体信息
hook recv函数.将接收的数据在debugview窗口格式输出
tcp协议的一些常见的函数使用,tcp的创建,tcp客户端,tcp服务器,connect, recv函数
这是套接字接收程序,还有一个发送程序tcp-send.c,学习linux可以下载看一下,对理解套接字很有用
很经典很详细的pdf资料整理,让你快速明白tcp内核缓冲机制,不用再为send、recv而担忧
功能与样例:通过TCP协议(利用FC5 “AG_SEND”和FC6“AG_RECV”) 传送具有可变消息长度的数据.doc
其中,TCP是一种基于连接的、可靠的、面向字节流的传输层协议,它负责在网络中传输数据,并提供错误检测和数据重传机制。 在编写应用程序时,通常会使用Socket来实现网络通信。在TCP协议下,应用程序使用Socket API...
和客户端进行数据传输,使用send()和recv()函数进行数据发送和接收。 关闭连接,使用close()函数关闭套接字。 客户端: 创建一个套接字(socket),使用socket()函数。 连接到服务器的IP地址和端口号,使用connect...
很多人写tcp程序的时候,都不考虑tcp stream的流特性,认为对方发送两个包,我们就是收到两个包,不考虑tcp的粘滞的可能。也就是说对方发送了两个数据包,我们可能会收到一个大包,这个大包就是对方发送的两个包在...
4) accept(), 阻塞函数,阻塞等待客户端的连接请求,如果有客户端连接,则accept()函数返回,返回一个用于通信的套接字文件; 5) recv(), 接收客户端发来的数据; 6) send(), 发送数据; 7) close(), 关闭文件描述...
(在线程中进行) 6、返回,等待另一客户请求。 7、关闭套接字。 客户端流程: 1、创建套接字(socket)。 2、向服务器发出连接请求(connect)。 3、和服务器端进行通信(send/recv)。 4、关闭套接字。
不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。
支持客户端和服务器的常用TCP接口:绑定Bind、监听Listen、接收Recv、连接Conn、发送Send、关闭Close。所有接口均使用异步回调的方式处理,内部实现使用Windows下性能最高的IOCP完成端口网络模型,并很好地处理了多...
使用python开发的tcp服务器程序,非阻塞,比较简单,使用为每一个client用一个线程的方式处理客户端的相关请求,一定时间后未收到client的请求,则关闭为该client处理的线程。
关于recv函数buffer大小的设置,当不知道数据长度时如何设置buffer长度,以及buffer长度对实际接收长度的影响。
这是一份关于 socket_recv的文档,相信对想学习 socket_recv的同学一定有很大的帮助!