TCP的recv问题

在TCP编程中,recv函数的处理方式对于数据的接收至关重要。本文介绍了三种recv策略:1) 通过接收空字符串结束;2) 判断特定结束符结束;3) 设置非阻塞和超时来结束接收。每种方法都有其适用场景,如第一种通常需要额外发送空字符串信号,第二种更节省资源且控制性强,第三种适用于特殊业务需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 TCP编程时,recv()函数默认阻塞等待,返回socket携带的信息,要根据业务场景设计recv的等待和结束机制:

recv阻塞,以接收空字符串结束

  • 如下TcpServer.py,为通常的recv机制:
    • 因为客户端单次send数据长度可能超过设置的1024,所以把recv放到循环体内,以保证接收数据流的完整性。
    • 但是不可能让recv一直阻塞等待这里,通常的做法就是判断数据长度为空则退出循环
    • 在正常传输数据时,recv接收的不可能为空,也就无法触发break退出循环recv
    • 需要额外发送一次,携带空字符串的请求,用来触发break关键字
      import socket
      
      address = ("0.0.0.0", 12346)
      
      
      def tcp_server():
          server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
          server_socket.bind(address)
          server_socket.listen(5)
          print("TcpServer开始监听:{}".format(address))
          while True:
              client_socket, client_address = server_socket.accept()
              data = str()
              while True:
                  msg = client_socket.recv(1024)
                  data += msg
                  if not len(msg):
                      break
              print(client_address, ":", data.decode())
              client_socket.close()
      
      
      if __name__ == '__main__':
          tcp_s
在C语言中,`recv`函数用于从已连接的套接字接收数据。它是用于TCP通信的重要函数之一。以下是`recv`函数的基本介绍和使用方法: ### `recv`函数原型 ```c #include <sys/types.h> #include <sys/socket.h> ssize_t recv(int sockfd, void *buf, size_t len, int flags); ``` ### 参数说明 - `sockfd`:表示接收数据的套接字描述符。 - `buf`:指向缓冲区,用于存储接收到的数据。 - `len`:缓冲区的大小,即可以接收的最大字节数。 - `flags`:指定接收数据时的选项,通常设置为0。 ### 返回值 - 成功时,返回接收到的字节数。 - 连接关闭时,返回0。 - 失败时,返回-1,并设置`errno`来指示错误。 ### 示例代码 ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #define PORT 8080 #define BUFFER_SIZE 1024 int main() { int server_fd, new_socket; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); char buffer[BUFFER_SIZE] = {0}; ssize_t valread; // 创建套接字文件描述符 if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 设置套接字选项 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { perror("setsockopt"); exit(EXIT_FAILURE); } // 定义服务器地址 address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); // 绑定套接字到指定端口 if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // 监听连接 if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } // 接受连接 if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) { perror("accept"); exit(EXIT_FAILURE); } // 接收数据 valread = recv(new_socket, buffer, BUFFER_SIZE, 0); printf("Received: %s\n", buffer); // 关闭套接字 close(new_socket); close(server_fd); return 0; } ``` ### 说明 1. 创建一个TCP套接字。 2. 设置套接字选项以允许重用地址和端口。 3. 绑定套接字到指定的IP地址和端口。 4. 监听连接请求。 5. 接受连接请求。 6. 使用`recv`函数接收数据。 7. 关闭套接字。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值