tcp套接字粘包解决办法

粘包只会出现在tcp,udp传输不会产生粘包现象。解决粘包的原理就是服务器预先向客户端发送客户端即将获取文件的大小。

第一版解决方案:

服务器:

 1 # Author : Kelvin
 2 # Date : 2019/2/2 17:38
 3 from socket import *
 4 import subprocess
 5
 6 ip_conf = ("127.0.0.1", 8888)
 7 buffer_capacity = 1024
 8 tcp_server = socket(AF_INET, SOCK_STREAM)
 9 tcp_server.bind(ip_conf)
10 tcp_server.listen(5)
11 while True:
12     conn, addr = tcp_server.accept()
13     while True:
14         try:
15             cmd = conn.recv(buffer_capacity)  # 如果强制断开连接会触发try,try正是解决强制中断连接的问题
16             print("收到的cmd:%s" % cmd)
17             if not cmd:  # 如果使用quit断开连接,服务器会死循环收到空,该判断正是解决此问题
18                 break
19             res = subprocess.Popen(cmd.decode("utf8"), shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
20                                    stderr=subprocess.PIPE)
21             err = res.stderr.read()
22             if err:
23                 back_msg = err
24             else:
25                 back_msg = res.stdout.read()
26             if not back_msg:
27                 back_msg = "acute successful!".encode("gbk")
28             length = len(back_msg)
29             conn.send(str(length).encode("gbk"))
30             re_ready = conn.recv(buffer_capacity).decode("utf8")
31             if re_ready == "ready":
32                 conn.send(back_msg)
33         except Exception as e:
34             print(e)
35             break
36 tcp_server.close()

客户端:

 1 # Author : Kelvin
 2 # Date : 2019/2/2 17:38
 3 from socket import *
 4
 5 ip_conf = ("127.0.0.1", 8888)
 6 buffer_capacity = 1024
 7 tcp_client = socket(AF_INET, SOCK_STREAM)
 8 tcp_client.connect(ip_conf)
 9 while True:
10     cmd = input("Please input cmd : ")
11     if not cmd:
12         continue
13     if cmd == "quit":
14         break
15     tcp_client.send(cmd.encode("utf8"))
16     re_size = int(tcp_client.recv(buffer_capacity).decode("utf-8"))
17     print("大小:", re_size)
18     tcp_client.send("ready".encode("utf8"))
19     recved_size = 0
20     recved_data = b""
21     while recved_size < re_size:
22         recved_data += tcp_client.recv(buffer_capacity)
23         recved_size = len(recved_data)
24     back_msg = recved_data.decode("gbk")
25     print(back_msg)
26 tcp_client.close()

升级版:

服务器:

 1 # Author : Kelvin
 2 # Date : 2019/2/2 17:38
 3 from socket import *
 4 import subprocess
 5 import struct
 6
 7 ip_conf = ("127.0.0.1", 8888)
 8 buffer_capacity = 1024
 9 tcp_server = socket(AF_INET, SOCK_STREAM)
10 tcp_server.bind(ip_conf)
11 tcp_server.listen(5)
12 while True:
13     conn, addr = tcp_server.accept()
14     while True:
15         try:
16             cmd = conn.recv(buffer_capacity)  # 如果强制断开连接会触发try,try正是解决强制中断连接的问题
17             print("收到的cmd:%s" % cmd)
18             if not cmd:  # 如果使用quit断开连接,服务器会死循环收到空,该判断正是解决此问题
19                 break
20             res = subprocess.Popen(cmd.decode("utf8"), shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
21                                    stderr=subprocess.PIPE)
22             err = res.stderr.read()
23             if err:
24                 back_msg = err
25             else:
26                 back_msg = res.stdout.read()
27             if not back_msg:
28                 back_msg = "acute successful!".encode("gbk")
29             length = len(back_msg)
30             re_length = struct.pack("i", length)
31             conn.send(re_length)
32             conn.send(back_msg)
33         except Exception as e:
34             print(e)
35             break
36 tcp_server.close()

客户端:

 1 # Author : Kelvin
 2 # Date : 2019/2/2 17:38
 3 from socket import *
 4 import struct
 5 ip_conf = ("127.0.0.1", 8888)
 6 buffer_capacity = 1024
 7 tcp_client = socket(AF_INET, SOCK_STREAM)
 8 tcp_client.connect(ip_conf)
 9 while True:
10     cmd = input("Please input cmd : ")
11     if not cmd:
12         continue
13     if cmd == "quit":
14         break
15     tcp_client.send(cmd.encode("utf8"))
16     re_size = struct.unpack("i",tcp_client.recv(4))[0]
17     print("大小:", re_size)
18     recved_size = 0
19     recved_data = b""
20     while recved_size < re_size:
21         recved_data += tcp_client.recv(buffer_capacity)
22         recved_size = len(recved_data)
23     back_msg = recved_data.decode("gbk")
24     print(back_msg)
25 tcp_client.close()

原文地址:https://www.cnblogs.com/sun-10387834/p/10348932.html

时间: 2025-01-05 17:07:05

tcp套接字粘包解决办法的相关文章

golang中解决tcp传输中的粘包问题

"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> golang中解决tcp传输中的粘包问题 - Programmer小卫 - 博客频道 - CSDN.NET Programmer小卫 故不积跬步,无以至千里.不积小流,无以成江海. 目录视图 摘要视图 订阅 [活动]2017 CSDN博客专栏评选 &nbsp [5月书

LINUX TCP套接字详细配置

提高服务器的负载能力,是一个永恒的话题.在一台服务器CPU和内存资源额定有限的情况下,最大的压榨服务器的性能,是最终的目的.要提高 Linux系统下的负载能力,可以先启用Apache的Worker模式,来提高单位时间内的并发量.但是即使这么做了,当网站发展起来之后,连接数过多 的问题就会日益明显.在节省成本的情况下,可以考虑修改Linux的内核TCP/IP参数,来最大的压榨服务器的性能.当然,如果通过修改内核参数也无法 解决的负载问题,也只能考虑升级服务器了,这是硬件所限,没有办法的事. Lin

TCP套接字端口复用SO_REUSEADDR

下面建立的套接字都是tcp套接字 1.进程创建监听套接字socket1,邦定一个指定端口,并接受了若干连接.那么进程创建另外一个套接口socket2,并试图邦定同一个端口时候,bind错误返回“Address already in use”(即使使用了SO_REUSEADDR). 2.进程创建监听套接字,邦定一个指定端口,并接受了若干连接,为每个连接创建子进程为连接服务.杀死监听套接字所在进程,然后重新启动.重新启动的进程调用bind重新建立监听套接字.这次邦定只有在bind前指定了SO_REU

第4章 基本tcp套接字编程

4.1 各种套接字api(重要) 4.1.1 socket() 用于创建一个套接字描述符,这个描述符指明的是tcp还是udp,同时还有ipv4还是ipv6 #include <sys/socket.h>?int socket(int family, int type, int protocol);//成功返回描述符,错误-1 family主要是指明的协议族,AF_INET:ipv4.AF_INET6:ipv6 .AF_LOCAL:unix域协议.AF_ROUTE:路由套接字.AF_KEY秘钥套

套接字编程相关函数(2:TCP套接字编程相关函数)

1. 基本TCP客户/服务器程序的套接字函数 2. socket函数 为了执行网络I/O,一个进程必须做的第一件事就是调用socket函数,指定期望的通信协议类型.其定义如下: #include <sys/socket.h> int socket(int family, int type, int protocol); // 返回:若成功则返回非负描述符,若失败则返回-1 其中:family参数指明协议族,它是图4-2中所示的某个常值.该参数也往往被称为协议域. type指明套接字类型,它是图

UNIX网络编程笔记(3)—基本TCP套接字编程

基本TCP套接字编程 主要介绍一个完整的TCP客户/服务器程序需要的基本套接字函数. 1.概述 在整个TCP客户/服务程序中,用到的函数就那么几个,其整体框图如下: 2.socket函数 为了执行网络I/O,一个进程必须要做的事情就是调用socket函数.其函数声明如下: #include <sys/socket.h> int socket(int family ,int type, int protocol); 其中: family:指定协议族 type:指定套接字类型 protocol:指

TCP协议的初始化及socket创建TCP套接字描述符

我们依然从start_kernel说起,它最后会执行: arch_call_rest_init() --> rest_init() --> Kernel_init() --> Kernei_init_freeable() --> do_basic_setup() --> do_initcalls() --> do_initcall_level(level) do_initcall_level(level)会根据level从0级开始以次执行相应先后等级的初始化函数. 第一

Unix网络编程之基本TCP套接字编程(上)

TCP客户/服务器实例 服务器程序 #include "unp.h" int main(int argc, char **argv) { int listenfd, connfd; pid_t childpid; socklen_t clilen; struct sockaddr_in cliaddr, servaddr; listenfd = Socket(AF_INET, SOCK_STREAM, 0); //1 bzero(&servaddr, sizeof(servad

《网络编程》基于 TCP 套接字编程的分析

本节围绕着基于 TCP 套接字编程实现的客户端和服务器进行分析,首先给出一个简单的客户端和服务器模式的基于 TCP 套接字的编程实现,然后针对实现过程中所出现的问题逐步解决.有关基于 TCP 套接字的编程过程可参考文章<基本 TCP 套接字编程>.该编程实现的功能如下: (1)客户端从标准输入读取文本,并发送给服务器: (2)服务器从网络输入读取该文本,并回射给客户端: (3)客户端从网络读取由服务器回射的文本,并通过标准输出回显到终端: 简单实现流图如下:注:画图过程通信双方是单独的箭头,只