网络编程之粘包问题使用socketserver实现并发(代码片段)

ageliu ageliu     2022-12-31     195

关键词:

一、粘包问题

注意:粘包问题只有tcp协议并且udp协议永远不会粘包

粘包问题的产生:

简述:粘包问题的产生主要是由于tcp协议传输数据(其内置的nagle算法来进行的)会将数据较小的且发送时间较短的合并成一个包从发送端发送出去,接收端不知道该怎么去想要的数据拿出来这样造成了粘包问题,另一方面是由于时间太短接收端没有及时拿干净

传来的数据造成数据混乱(这是因为tcp协议又叫流氏协议指的是其就像水流一样传输数据)才产生的粘包问题。

1、发送端由于时间太短造成多个包合在一起发送产生粘包问题的实例如下:

服务端:

技术分享图片
from socket import *
ip_port=(127.0.0.1,8080)

tcp_socket_server=socket(AF_INET,SOCK_STREAM)
tcp_socket_server.bind(ip_port)
tcp_socket_server.listen(5)


conn,addr=tcp_socket_server.accept()


data1=conn.recv(10)
data2=conn.recv(10)

print(----->,data1.decode(utf-8))
print(----->,data2.decode(utf-8))

conn.close()
View Code

客户端:

技术分享图片
import socket
BUFSIZE=1024
ip_port=(127.0.0.1,8080)

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
res=s.connect_ex(ip_port)


s.send(hello.encode(utf-8))
s.send(feng.encode(utf-8))
View Code

2、由于接收端没有接收干净发送端发来的数据造成的粘包问题的实例如下:

服务端:

技术分享图片
from socket import *
ip_port=(127.0.0.1,8080)

tcp_socket_server=socket(AF_INET,SOCK_STREAM)
tcp_socket_server.bind(ip_port)
tcp_socket_server.listen(5)


conn,addr=tcp_socket_server.accept()


data1=conn.recv(2) #一次没有收完整
data2=conn.recv(10)#下次收的时候,会先取旧的数据,然后取新的

print(----->,data1.decode(utf-8))
print(----->,data2.decode(utf-8))

conn.close()
View Code

客户端:

技术分享图片
import socket
BUFSIZE=1024
ip_port=(127.0.0.1,8080)

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
res=s.connect_ex(ip_port)


s.send(hello feng.encode(utf-8))
View Code

3、粘包现象出现的实例如下:
3.1基于subprocess模块产生的粘包现象

服务端:

技术分享图片
from socket import *
import subprocess

ip_port=(127.0.0.1,8080)
BUFSIZE=1024

tcp_socket_server=socket(AF_INET,SOCK_STREAM)
tcp_socket_server.bind(ip_port)
tcp_socket_server.listen(5)

while True:
    conn,addr=tcp_socket_server.accept()
    print(客户端,addr)

    while True:
        cmd=conn.recv(BUFSIZE)
        if len(cmd) == 0:break

        res=subprocess.Popen(cmd.decode(utf-8),shell=True,
                         stdout=subprocess.PIPE,
                         stdin=subprocess.PIPE,
                         stderr=subprocess.PIPE)

        stderr=act_res.stderr.read()
        stdout=act_res.stdout.read()
        conn.send(stderr)
        conn.send(stdout)
View Code

客户端:

技术分享图片
import socket
BUFSIZE=1024
ip_port=(127.0.0.1,8080)

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
res=s.connect_ex(ip_port)

while True:
    msg=input(>>: ).strip()
    if len(msg) == 0:continue
    if msg == quit:break

    s.send(msg.encode(utf-8))
    act_res=s.recv(BUFSIZE)

    print(act_res.decode(utf-8),end=‘‘)
View Code

3.2使用struct模块的解决方案
服务端:

技术分享图片
import socket,json,struct,subprocess
ip_port=(127.0.0.1,2206)
ip_base=1024
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(ip_port)
server.listen(5)
while True:
    conn,adder=server.accept()
    while True:
        try:
            data=conn.recv(ip_base)
            if len(data)==0:
                break
            res=subprocess.Popen(data.decode(utf-8),shell=True,stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
            stdout=res.stdout.read()
            stderr=res.stderr.read()
            head_dic=filname:dir,md5:fffff,head:len(stdout)+len(stderr)
            head_json=json.dumps(head_dic)
            head_bytes=head_json.encode(utf-8)
            conn.send(struct.pack(i,len(head_bytes)))
            conn.send(head_bytes)
            conn.send(stdout)
            conn.send(stderr)
        except ConnectionResetError:
            break
    conn.close()
server.colse()
View Code

客户端:

技术分享图片
import socket,json,struct
ip_port=(127.0.0.1,2206)
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(ip_port)
while True:
    mag=input(>>>:).strip()
    if len(mag)==0:
        continue
    client.send(mag.encode(utf-8))
    #先拿到报头的固定长度(4bytes)
    head_len=struct.unpack(i,client.recv(4))[0]
    #再拿到报头
    head_bytes=client.recv(head_len)
    head_json=head_bytes.decode(utf-8)
    head_dic=json.loads(head_json)
    #拿到报头的中数据的长度
    total=head_dic[head]
    rb=b‘‘
    stawith=0
    while stawith<total:
        data=client.recv(total)
        stawith+=len(data)
        rb+=data
    print(rb.decode(gbk))
client.close()
View Code

补充:为何udp协议不会发生粘包问题是由于udp协议不是通过连接进行数据传输的并且基于udp协议发送的数据都会自带报头,
所以接收端可以通过每条数据的报头去取出数据并且udp协议传输数据是传一个数据就立马删除掉这样不会让接收端由于接受不

急时而造成数据混乱。(udp协议也可以叫数据报协议)

二、使用socketserver模块实现并发

1、基于tcp协议通信实现并发

服务端:

技术分享图片
import socketserver
class Myudpheadler(socketserver.DatagramRequestHandler):
    def handle(self):
        while True:
            data,sock=self.request()
            sock.sendto(data,self.client_address)
if __name__ == __main__:
    sever=socketserver.ThreadingUDPServer((127.0.0.1,2221),Myudpheadler)
    sever.serve_forever()
View Code

客户端:

技术分享图片
from socket import *
ip_port=(127.0.0.1,2221)
client=socket(AF_INET,SOCK_DGRAM)
while True:
    mad=input(>>>>:).strip()
    if len(mad)==0:
        continue
    client.sendto(mad.encode(utf-8),ip_port)
    adder,sock=client.recvfrom(1024)
    print(adder)
    print(sock)
client.close()
View Code

2、基于udp协议通信实现并发
服务端:

技术分享图片
import socketserver
class mudphead(socketserver.DatagramRequestHandler):
    def handle(self):
        while True:
            data,sock=self.request()
            sock.sendto(data,self.client_address)
if __name__ == __main__:
    server=socketserver.ThreadingUDPServer((127.0.0.1,2220),mudphead)
    server.serve_forever()
View Code

客户端:

技术分享图片
from socket import *
ip_port=(127.0.0.1,2206)
client=socket(AF_INET,SOCK_DGRAM)
while True:
    client.sendto(hello.encode(utf-8),ip_port)
    adder,scok=client.recvfrom(1024)
    print(adder)
client.close()
View Code

补充:基于udp协议其自身就可以实现通信实现并发。

 





网络编程之粘包(代码片段)

一、什么是粘包须知:只有TCP有粘包现象,UDP永远不会粘包粘包不一定会发生TCP发生粘包的两种情况:      1.由于Nagle算法,将多次间隔小且数量小的数据,合并成一个数据块      2.数据量发送大,接受少首先需... 查看详情

socket之粘包

什么是粘包粘包是一种现象 这种现象只出现在TCP中而不会出现在UDP中(TCP和UDP都是传输层中的协议)粘包:粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的粘包概念详解:当发... 查看详情

网络编程基础之粘包现象(代码片段)

一、粘包现象原理分析  1、我们先来看几行代码,从现象来分析:    测试程序分为两部分,分别是服务端和客户端    服务端.py 1#!/usr/bin/envpython32#-*-coding:utf-8-*-3#writebycongcong456importsocket78server=socket.socket(family=sock... 查看详情

netty之粘包拆包bytetomessagedecoder(代码片段)

目录拆包粘包处理的方式netty的处理方式netty实现编码解码1、cumulator.cumulate()拼接数据包2、callDecode()解析数据包总结LengthFieldBasedFrameDecoder拆包粘包粘包产生的原因:两个包小于缓存区的大小,传送数据会将两个包都放在... 查看详情

netty之粘包拆包bytetomessagedecoder(代码片段)

目录拆包粘包处理的方式netty的处理方式netty实现编码解码1、cumulator.cumulate()拼接数据包2、callDecode()解析数据包总结LengthFieldBasedFrameDecoder拆包粘包粘包产生的原因:两个包小于缓存区的大小,传送数据会将两个包都放在... 查看详情

netty之粘包拆包bytetomessagedecoder(代码片段)

目录拆包粘包处理的方式netty的处理方式netty实现编码解码1、cumulator.cumulate()拼接数据包2、callDecode()解析数据包总结LengthFieldBasedFrameDecoder拆包粘包粘包产生的原因:两个包小于缓存区的大小,传送数据会将两个包都放在... 查看详情

socket之粘包发生问题

粘包注意注意注意:res=subprocess.Popen(cmd.decode(‘utf-8‘),shell=True,stderr=subprocess.PIPE,stdout=subprocess.PIPE)的结果的编码是以当前所在的系统为准的,如果是windows,那么res.stdout.read()读出的就是GBK编码的,在接收端需要用GBK解码且只能从... 查看详情

socket网络编程之粘包问题详解(代码片段)

一,粘包问题详情1,只有TCP有粘包现象,UDP永远不会粘包   你的程序实际上无权直接操作网卡的,你操作网卡都是通过操作系统给用户程序暴露出来的接口,那每次你的程序要给远程发数据时,其实是先把数据从用户态co... 查看详情

day32udp协议socketserver模块,并发编程基础(代码片段)

一.粘包现象  1.为什么会出现粘包现象    1.只有在TCP协议中才会出现粘包现象,因为TCP协议是流式协议    2.TCP协议的特点是将数据量小、时间间隔比较短的数据一次性打包发送    3.粘包现象的本质是因为不知... 查看详情

网络编程路线

一客户端/服务端架构二osi七层模型定义三socket定义四套接字原理  一、套接字发展史及分类  二、套接字工作流程五套接字的实现  一、基于TCP的套接字  二、基于UDP的套接字六粘包  一、什么是粘包  二、粘包... 查看详情

网络编程(代码片段)

阅读目录一客户端/服务器架构二osi七层三socket层四socket是什么五套接字发展史及分类六套接字工作流程七基于TCP的套接字八基于UDP的套接字九粘包现象十什么是粘包十一解决粘包的low比处理方法十二峰哥解决粘包的方法十三认... 查看详情

socketserver编程

socket粘包                  原理:服务器端或客户端连续调用2次send时,数据其实并没有立刻被发送出去,而是放到了系统的socket发送缓冲区里,等缓冲区满了、或者数... 查看详情

socket补充(代码片段)

...通讯 引入:为什么一定要先学习网络协议?之所以学习网络编程就是为了让我们的程序能够利用网络来传输数据,开发出C/S构架的应用程序而网络的核心,就是协议,没有协议就 查看详情

进度条---socket---socketserver(代码片段)

TCP:UDP:粘包现象:socket socketserversocketserver内部使用io多路复用,以及多线程和多进程,从而实现并发处理多个客户端请求的socket服务端即:每个客户端请求连接到服务器时,socket服务端都会在服务器端创建一个线程或者进... 查看详情

socketserver模块使用与源码分析(代码片段)

socketserver模块使用与源码分析前言  在前面的学习中我们其实已经可以通过socket模块来建立我们的服务端,并且还介绍了关于TCP协议的粘包问题。但是还有一个非常大的问题就是我们所编写的Server端是不支持并发性服务的,在... 查看详情

socketserver实现并发(代码片段)

  在python编程中,一般可以通过使用socketserver简化操作并实现并发操作。socketserver实际上是对socket的再封装,在基于tcp的编程中主要是两个循环:1.链接循环,2.通讯循环。链接循环负责tcp的四次握手,建立服务器端和客户端... 查看详情

使用newlife网络库管道模式解决数据粘包(代码片段)

...一个基本的Newlife网络服务端这边我们来讲一下如何解决粘包的问题在上一篇总我们注册了Newlife的管道处理器,我们来看看他是如何实现粘包处理的svr.Add<ReciveFilter>();//粘包处理管道首先看一下我们设备的上传数据协议 &n... 查看详情

python网络编程socketserver模块

1、socketserver模块socketserver是标准库中的一个高级模块(Python2.x中名为SocketServer)。socketserver的目标是简化创建网络客户端和服务器的代码。(隐藏了实现细节)socketserver是使用类来编写应用程序。以面向对象的方式处理事务有... 查看详情