`
老竹枝
  • 浏览: 80934 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

在阻塞式的tcp连接中使用recv接收数据未达到指定长度返回问题

阅读更多
  一直以为在阻塞的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都会实现的。
分享到:
评论

相关推荐

    stm32f407-TCP客户端数据收发实验_stm32f407_stm32f407TCP客户端_

    在这些应用中,TCP(传输控制协议)客户端数据收发是一项关键功能,允许设备与服务器进行可靠的数据通信。以下是对STM32F407实现TCP客户端数据收发的详细解释: 首先,要建立TCP连接,我们需要理解TCP/IP协议栈的...

    VC TCP多连接

    本主题将深入探讨如何在Visual C++(简称VC++)环境中使用Winsock库实现TCP多连接。 首先,让我们理解什么是Winsock。Winsock是Windows操作系统提供的一个API(应用程序编程接口),用于实现TCP/IP协议栈。它使得...

    两台设备的TCP通讯_Codesys的两台设备之前的TCP通讯_

    在Structured Text中,你可以使用系统提供的库函数来建立TCP连接、发送数据和接收数据。 1. 建立TCP连接:使用`TCP_CONNECT`函数打开到指定IP和端口的连接。你需要提供连接请求的目标IP地址、端口号和连接超时时间...

    vc实现向指定ip端口发送数据或文件,获取本机ip

    在VC++环境中,实现向指定IP和端口发送数据或文件以及获取本机IP的功能,主要涉及网络编程、多线程技术以及对话框界面设计。下面将详细解释这些知识点。 1. **网络编程基础**: 网络编程是通过网络在不同设备间...

    vc TCP 连接

    在压缩包中的"TCP+client+server"和"TCP client+server"文件可能包含了示例代码,这些代码通常会演示如何在VC++环境中设置和管理TCP连接,包括如何创建套接字、绑定、监听、接受连接、发送和接收数据等步骤。...

    socket编程之tcp连接代码

    在本主题中,我们将深入探讨TCP(传输控制协议)连接的Socket编程,包括服务器端和客户端的实现代码。 TCP是一种面向连接的、可靠的传输层协议,它确保了数据在发送到目的地之前是完整且有序的。TCP连接的建立过程...

    TCP客户端和服务端代码

    - **发送与接收数据**:连接成功后,客户端同样使用`send()`发送数据,`recv()`接收数据。在完成通信后,客户端关闭socket连接。 在实际开发中,需要注意以下几点: - 错误处理:对于可能出现的网络异常,如连接...

    c++编程TCP的发送与接收

    在IT行业中,网络通信是至关重要的一个领域,而TCP(传输控制协议)作为网络通信的基础协议之一,扮演着数据可靠传输的重要角色。本篇将详细探讨C++编程中如何实现TCP的发送与接收,主要针对VC++6.0环境下进行讨论。...

    linux下网络编程TCP客户端和服务器端数据传输代码

    在Linux环境下进行网络编程,TCP协议是最常用的传输层协议之一,因为它提供了面向连接、可靠的数据传输服务。本篇文章将深入探讨如何使用C语言在Linux下编写TCP客户端和服务器端的数据传输代码。 首先,TCP服务器端...

    TCP通讯类封装

    - 接收数据:客户端通过`recv()`或`recvfrom()`方法接收服务器返回的数据,这些函数通常是阻塞式的,直到有数据到达才会返回。 - 断开连接:完成通信后,客户端需要调用`close()`函数关闭连接。 2. **TCP服务器类...

    变长数据接收

    在Windows网络编程中,"变长数据接收"是一个关键的概念,尤其在使用Socket套接字进行通信时。这个过程涉及到如何有效地处理不确定长度的数据包,这些数据包可以在网络上发送和接收。以下是对这一主题的详细说明。 1...

    linux下多线程网络编程TCP服务器端数据传输代码

    6. **数据传输**:在线程中,使用`recv()`和`send()`函数进行数据的读取和发送。`recv()`用于接收客户端发送的数据,`send()`用于将数据发送回客户端。 7. **关闭资源**:处理完一个连接后,记得关闭相关套接字和...

    TCP.zip_letter4tt_purposest2_tcp_windows网络编程_基于流式套接字的客户端设计

    在TCP客户端设计中,我们需要创建一个套接字并连接到服务器,然后通过recv函数读取指定长度的数据。recv函数会阻塞直到指定数量的字节被接收,或者遇到错误或连接关闭。 接着,我们要实现变长数据的接收功能。与定...

    TCP通信支持多个客户端连接服务器

    在IT行业中,网络通信是至关重要的一个领域,特别是在开发服务器应用程序时。TCP(Transmission Control Protocol)是一种面向连接的、可靠的传输协议,广泛用于确保数据的完整性和顺序。本篇文章将详细探讨如何在...

    c语言tcp通讯.zip

    在C语言中,我们可以使用`socket`库来实现TCP通信,这个库提供了创建套接字、绑定地址、监听连接请求、接受连接以及收发数据等功能。 1. **创建套接字**:使用`socket()`函数创建一个套接字,它需要指定协议族(如...

    C++实现的TCP协议的文件传输

    在IT领域,网络通信是不可或缺的一部分,而TCP(Transmission Control Protocol)协议作为传输层的核心协议,为应用程序提供了可靠的、基于连接的数据传输服务。本话题主要关注如何使用C++语言实现TCP协议进行文件...

    TCP.rar_TCP 服务器端_TCP 聊天_site:www.pudn.com

    4. **数据收发**:服务器使用recv和send函数接收和发送数据,这两个函数会阻塞直到有数据可读或可写。 5. **多线程/异步处理**:为了同时处理多个客户端连接,服务器通常使用多线程、多进程或者异步I/O模型,如...

    linux的tcp服务端与客户端demo源码

    2. **设置非阻塞模式**: 使用`fcntl()`函数,将套接字设置为非阻塞模式,这样在调用`accept()`或`recv()`等函数时,如果数据未准备好,不会导致进程阻塞。 3. **绑定与监听**: 使用`bind()`函数将套接字绑定到特定的...

    TCP.Socket.rar_socket tcp_tcp socket 协议

    TCP(Transmission Control Protocol)是一种面向连接、可靠的传输协议,它确保了数据的正确顺序传输和错误检查,而Socket则是TCP/IP协议族中的应用编程接口(API),它为应用程序提供了创建和使用TCP连接的手段。...

    TCP server程序

    在TCP连接建立后,数据的传输是通过`read()`和`write()`(或其变体如`recv()`和`send()`)函数进行的。服务器通常会在接收完客户端的数据后进行处理,然后再发送响应数据。这个过程可以是简单的数据交换,也可以是...

Global site tag (gtag.js) - Google Analytics