一直以为在阻塞的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都会实现的。
分享到:
相关推荐
在这些应用中,TCP(传输控制协议)客户端数据收发是一项关键功能,允许设备与服务器进行可靠的数据通信。以下是对STM32F407实现TCP客户端数据收发的详细解释: 首先,要建立TCP连接,我们需要理解TCP/IP协议栈的...
本主题将深入探讨如何在Visual C++(简称VC++)环境中使用Winsock库实现TCP多连接。 首先,让我们理解什么是Winsock。Winsock是Windows操作系统提供的一个API(应用程序编程接口),用于实现TCP/IP协议栈。它使得...
在Structured Text中,你可以使用系统提供的库函数来建立TCP连接、发送数据和接收数据。 1. 建立TCP连接:使用`TCP_CONNECT`函数打开到指定IP和端口的连接。你需要提供连接请求的目标IP地址、端口号和连接超时时间...
在VC++环境中,实现向指定IP和端口发送数据或文件以及获取本机IP的功能,主要涉及网络编程、多线程技术以及对话框界面设计。下面将详细解释这些知识点。 1. **网络编程基础**: 网络编程是通过网络在不同设备间...
在压缩包中的"TCP+client+server"和"TCP client+server"文件可能包含了示例代码,这些代码通常会演示如何在VC++环境中设置和管理TCP连接,包括如何创建套接字、绑定、监听、接受连接、发送和接收数据等步骤。...
在本主题中,我们将深入探讨TCP(传输控制协议)连接的Socket编程,包括服务器端和客户端的实现代码。 TCP是一种面向连接的、可靠的传输层协议,它确保了数据在发送到目的地之前是完整且有序的。TCP连接的建立过程...
- **发送与接收数据**:连接成功后,客户端同样使用`send()`发送数据,`recv()`接收数据。在完成通信后,客户端关闭socket连接。 在实际开发中,需要注意以下几点: - 错误处理:对于可能出现的网络异常,如连接...
在IT行业中,网络通信是至关重要的一个领域,而TCP(传输控制协议)作为网络通信的基础协议之一,扮演着数据可靠传输的重要角色。本篇将详细探讨C++编程中如何实现TCP的发送与接收,主要针对VC++6.0环境下进行讨论。...
在Linux环境下进行网络编程,TCP协议是最常用的传输层协议之一,因为它提供了面向连接、可靠的数据传输服务。本篇文章将深入探讨如何使用C语言在Linux下编写TCP客户端和服务器端的数据传输代码。 首先,TCP服务器端...
- 接收数据:客户端通过`recv()`或`recvfrom()`方法接收服务器返回的数据,这些函数通常是阻塞式的,直到有数据到达才会返回。 - 断开连接:完成通信后,客户端需要调用`close()`函数关闭连接。 2. **TCP服务器类...
在Windows网络编程中,"变长数据接收"是一个关键的概念,尤其在使用Socket套接字进行通信时。这个过程涉及到如何有效地处理不确定长度的数据包,这些数据包可以在网络上发送和接收。以下是对这一主题的详细说明。 1...
6. **数据传输**:在线程中,使用`recv()`和`send()`函数进行数据的读取和发送。`recv()`用于接收客户端发送的数据,`send()`用于将数据发送回客户端。 7. **关闭资源**:处理完一个连接后,记得关闭相关套接字和...
在TCP客户端设计中,我们需要创建一个套接字并连接到服务器,然后通过recv函数读取指定长度的数据。recv函数会阻塞直到指定数量的字节被接收,或者遇到错误或连接关闭。 接着,我们要实现变长数据的接收功能。与定...
在IT行业中,网络通信是至关重要的一个领域,特别是在开发服务器应用程序时。TCP(Transmission Control Protocol)是一种面向连接的、可靠的传输协议,广泛用于确保数据的完整性和顺序。本篇文章将详细探讨如何在...
在C语言中,我们可以使用`socket`库来实现TCP通信,这个库提供了创建套接字、绑定地址、监听连接请求、接受连接以及收发数据等功能。 1. **创建套接字**:使用`socket()`函数创建一个套接字,它需要指定协议族(如...
在IT领域,网络通信是不可或缺的一部分,而TCP(Transmission Control Protocol)协议作为传输层的核心协议,为应用程序提供了可靠的、基于连接的数据传输服务。本话题主要关注如何使用C++语言实现TCP协议进行文件...
4. **数据收发**:服务器使用recv和send函数接收和发送数据,这两个函数会阻塞直到有数据可读或可写。 5. **多线程/异步处理**:为了同时处理多个客户端连接,服务器通常使用多线程、多进程或者异步I/O模型,如...
2. **设置非阻塞模式**: 使用`fcntl()`函数,将套接字设置为非阻塞模式,这样在调用`accept()`或`recv()`等函数时,如果数据未准备好,不会导致进程阻塞。 3. **绑定与监听**: 使用`bind()`函数将套接字绑定到特定的...
TCP(Transmission Control Protocol)是一种面向连接、可靠的传输协议,它确保了数据的正确顺序传输和错误检查,而Socket则是TCP/IP协议族中的应用编程接口(API),它为应用程序提供了创建和使用TCP连接的手段。...
在TCP连接建立后,数据的传输是通过`read()`和`write()`(或其变体如`recv()`和`send()`)函数进行的。服务器通常会在接收完客户端的数据后进行处理,然后再发送响应数据。这个过程可以是简单的数据交换,也可以是...