一,发生粘包

服务器端

 from socket import *
phone=socket(AF_INET,SOCK_STREAM) #套接字
phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #解决端口占用
phone.bind(('127.0.0.1',8080)) #绑定端口和Ip到套接字
phone.listen(5)
conn,client_addr=phone.accept() #等待tcp接受 # data1=conn.recv(10)
# print('data1: ',data1)
# data2=conn.recv(4)
# print('data2:',data2)
#接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,
#服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)

客户端

 from socket import *
import time
phone=socket(AF_INET,SOCK_STREAM)
phone.connect(('127.0.0.1',8080)) # phone.send('helloworld'.encode('utf-8'))
# phone.send('egon'.encode('utf-8'))
#发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包)

二,用struct模块解决粘包问题

为字节流加上自定义固定长度报头,报头中包含字节流长度,然后一次send到对端,对端在接收时,先从缓存中取出定长的报头,然后再取真实数据

 #_*_coding:utf-8_*_
#http://www.cnblogs.com/coser/archive/2011/12/17/2291160.html
__author__ = 'Linhaifeng'
import struct
import binascii
import ctypes values1 = (1, 'abc'.encode('utf-8'), 2.7)
values2 = ('defg'.encode('utf-8'),101)
s1 = struct.Struct('I3sf')
s2 = struct.Struct('4sI') print(s1.size,s2.size)
prebuffer=ctypes.create_string_buffer(s1.size+s2.size)
print('Before : ',binascii.hexlify(prebuffer))
# t=binascii.hexlify('asdfaf'.encode('utf-8'))
# print(t) s1.pack_into(prebuffer,0,*values1)
s2.pack_into(prebuffer,s1.size,*values2) print('After pack',binascii.hexlify(prebuffer))
print(s1.unpack_from(prebuffer,0))
print(s2.unpack_from(prebuffer,s1.size)) s3=struct.Struct('ii')
s3.pack_into(prebuffer,0,123,123)
print('After pack',binascii.hexlify(prebuffer))
print(s3.unpack_from(prebuffer,0)) 关于struct的详细用法

服务器端

 import socket
import subprocess
import struct
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #就是它,在bind前加
phone.bind(('127.0.0.1',8088)) #绑定手机卡
phone.listen(5) #开机 print('starting...')
while True: #链接循环
conn,client_addr=phone.accept() #等电话 (链接,客户的的ip和端口组成的元组)
print('-------->',conn,client_addr) #收,发消息
while True:#通信循环
try:
cmd=conn.recv(1024)
print(cmd)
if not cmd:break #针对linux
#执行cmd命令,拿到cmd的结果,结果应该是bytes类型
#。。。。
res = subprocess.Popen(cmd.decode('utf-8'), shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout=res.stdout.read()
stderr=res.stderr.read()
print(stdout) #先发报头(转成固定长度的bytes类型)
header = struct.pack('i',len(stdout)+len(stderr))
print(header)
conn.send(header)
#再发送命令的结果
conn.send(stdout)
conn.send(stderr)
except Exception:
break
conn.close() #挂电话
phone.close() #关机

客户端

 import socket
import struct
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
phone.connect(('127.0.0.1',8088)) #绑定手机卡 #发,收消息
while True:
cmd=input('>>: ').strip()
if not cmd:continue phone.send(cmd.encode('utf-8'))
#先收报头
header_struct=phone.recv(4)
print(header_struct)
unpack_res = struct.unpack('i', header_struct)
total_size=unpack_res[0]
print(total_size) #再收数据
recv_size=0 #10241=10240+1
total_data=b''
while recv_size < total_size:
recv_data=phone.recv(1024)
print(recv_data)
recv_size+=len(recv_data)
print(recv_size)
total_data+=recv_data
print(total_data)
# else:
print(total_data.decode('gbk'))
phone.close()

三,大文件粘包问题

服务器端

 import socket
import subprocess
import struct
import json
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #就是它,在bind前加
phone.bind(('127.0.0.1',8082)) #绑定手机卡
phone.listen(5) #开机 print('starting...')
while True: #链接循环
conn,client_addr=phone.accept() #等电话 (链接,客户的的ip和端口组成的元组)
print('-------->',conn,client_addr) #收,发消息
while True:#通信循环
try:
cmd=conn.recv(1024)
if not cmd:break #针对linux
#执行cmd命令,拿到cmd的结果,结果应该是bytes类型
#。。。。
res = subprocess.Popen(cmd.decode('utf-8'), shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout=res.stdout.read()
stderr=res.stderr.read()
#制作报头
header_dic = {
'total_size': len(stdout)+len(stderr),
'filename': None,
'md5': None} header_json = json.dumps(header_dic)
header_bytes = header_json.encode('utf-8')
#发送阶段
#先发报头长度
conn.send(struct.pack('i',len(header_bytes)))
#再发报头
conn.send(header_bytes) #最后发送命令的结果
conn.send(stdout)
conn.send(stderr)
except Exception:
break
conn.close() #挂电话
phone.close() #关机

客户端

 import socket
import struct
import json
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
phone.connect(('127.0.0.1',8082)) #绑定手机卡 #发,收消息
while True:
cmd=input('>>: ').strip()
if not cmd:continue phone.send(cmd.encode('utf-8'))
#先收报头的长度
header_len=struct.unpack('i',phone.recv(4))[0] #再收报头
header_bytes=phone.recv(header_len)
header_json=header_bytes.decode('utf-8')
header_dic=json.loads(header_json)
total_size=header_dic['total_size'] #最后收数据
recv_size=0 #10241=10240+1
total_data=b''
while recv_size < total_size:
recv_data=phone.recv(1024)
recv_size+=len(recv_data)
total_data+=recv_data
print(total_data.decode('gbk'))
phone.close()

四,udp套接字

服务器端

 from socket import *
udp_server=socket(AF_INET,SOCK_DGRAM)
udp_server.bind(('127.0.0.1',8088)) while True:
msg,client_addr=udp_server.recvfrom(1024)
print('has recv %s' %msg)
udp_server.sendto(msg.upper(),client_addr)
print('has send')
udp_server.close()

客户端

 from socket import *
udp_client=socket(AF_INET,SOCK_DGRAM) while True:
msg=input('>>: ').strip()
udp_client.sendto(msg.encode('utf-8'),('127.0.0.1',8088))
print('has send')
# res,server_addr=udp_client.recvfrom(1024)
# print('====>',res.decode('utf-8')) udp_client.close()

udp 套接字不会发生粘包

服务器端

 from socket import *
udp_server=socket(AF_INET,SOCK_DGRAM)
udp_server.bind(('127.0.0.1',8089)) msg1,client_addr=udp_server.recvfrom(5)
print(msg1) msg2,client_addr=udp_server.recvfrom(5)
print(msg2)

客户端

 from socket import *
udp_client=socket(AF_INET,SOCK_DGRAM) udp_client.sendto('hello'.encode('utf-8'),('127.0.0.1',8089))
udp_client.sendto('world'.encode('utf-8'),('127.0.0.1',8089))

五,socketserver套接字

封装了socket,而且解决了Io阻塞问题

服务端

 # socketserver模块多进程,多线程
# 无论你开什么都是开线程,线程就有IO,这个模块帮你解决这个IO问题 # 基础版本,遇到问题,不能无限开线程,而且没有解决IO
# 线程开启跟进程开启一样
from socket import *
from threading import Thread
# s=socket(AF_INET,SOCK_STREAM)
# s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
# s.bind(('127.0.0.1',8090))
# s.listen(5)
# def talk(conn,addr):
# while True: #通信循环
# try:
# data=conn.recv(1024)
# if not data:break
# conn.send(data.upper())
# except Exception:
# break
# conn.close()
# if __name__ == '__main__':
# while True:#链接循环
# conn,addr=s.accept()
# p = Thread(target=talk,args=(conn,addr))
# p.start()
# s.close() # socketserver模块套接字,自动处理IO问题
import socketserver
class MyTCPhandler(socketserver.BaseRequestHandler): #必须继承这个类
def handle(self):
# print(self.request) 打印出来的就是conn
# print(self.client_address) 打印出来的就是addr
while True:
try:
data=self.request.recv(1024)
if not data:break
self.request.send(data.upper())
except Exception:
break
self.request.close()
if __name__ == '__main__':
server=socketserver.ThreadingTCPServer(('127.0.0.1',8082),MyTCPhandler) #多线程
# 三个参数,IP,端口,类
# server=socketserver.ForkingTCPServer(('127.0.0.1',8082),MyTCPhandler) #多进程
server.allow_reuse_address=True #重用地址
server.serve_forever() #永远运行,就是一直开着,相当于while True

客户端

 from socket import *
client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8082)) while True:
msg=input('>>: ').strip()
if not msg:continue
client.send(msg.encode('utf-8'))
data=client.recv(1024)
print(data.decode("utf-8"))

python开发socket套接字:粘包问题&udp套接字&socketserver的更多相关文章

  1. Python之路 - 网络编程之粘包

    Python之路 - 网络编程之粘包 粘包

  2. tcp粘包,udp丢包

    TCP是面向流的, 流, 要说明就像河水一样, 只要有水, 就会一直流向低处, 不会间断. TCP为了提高传输效率, 发送数据的时候, 并不是直接发送数据到网路, 而是先暂存到系统缓冲, 超过时间或者 ...

  3. python笔记8 socket(TCP) subprocess模块 粘包现象 struct模块 基于UDP的套接字协议

    socket 基于tcp协议socket 服务端 import socket phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 买 ...

  4. Python开发【socket篇】解决粘包

    客户端 import os import json import struct import socket sk = socket.socket() sk.connect(('127.0.0.1',8 ...

  5. python socket网络编程之粘包问题详解

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

  6. (网络编程)基于tcp(粘包问题) udp协议的套接字通信

    import   socket 1.通信套接字(1人1句)服务端和1个客户端 2.通信循环(1人多句)服务端和1个客户端 3.通信循环(多人(串行)多句)多个客户端(服务端服务死:1个客户端---&g ...

  7. python 全栈开发,Day35(TCP协议 粘包现象 和解决方案)

    一.TCP协议 粘包现象 和解决方案 黏包现象让我们基于tcp先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd)执行远程命令的模块 需要用到模块subprocess sub ...

  8. tcp套接字粘包解决办法

    粘包只会出现在tcp,udp传输不会产生粘包现象.解决粘包的原理就是服务器预先向客户端发送客户端即将获取文件的大小. 第一版解决方案: 服务器: # Author : Kelvin # Date : ...

  9. python全栈开发day28-网络编程之粘包、解决粘包,上传和下载的作业

    一.昨日内容回顾 1. tcp和udp编码 2. 自定义mysocket解决编码问题 二.今日内容总结 1.粘包 1)产生粘包原因: (1).接收方不知道消息之间的边界,不知道一次性要取多少字节的数据 ...

随机推荐

  1. Ant Design

    https://ant.design/components/form-cn/    (Ant Design of React 中文网) 1.Ant Design of react (相关资料) htt ...

  2. centos 使用yum安装MySQL 5.7

    想在centos上安装一个MySQL,使用yum install mysql-server 安装提示仓库没有包,也是醉了. 找了很多博客,发现一个很好用的,推荐给大家. 地址:https://blog ...

  3. 24-THREE.JS 镜面高光材质

    <!DOCTYPE html> <html> <head> <title>Example 04.07 - Mesh Phong material< ...

  4. 使用Jenkins自动编译我的 java 项目 git maven jenkins

    之前的项目已经将jenkins部署好,现在添加maven项目 准备工作 安装插件 Git plugin Publish Over SSH 全局设置  key: 是 linux服务器的私钥 Global ...

  5. Struts10---拦截器

    01.创建一个登录界面 <%@ page language="java" import="java.util.*" pageEncoding=" ...

  6. javascript: 代码优化

    一.避免全局查找 在一个函数中会用到全局对象存储为局部变量来减少全局查找,因为访问局部变量的速度要比访问全局变量的速度更快些 function search() { //当我要使用当前页面地址和主机域 ...

  7. react: next-redux-saga

    instead of using the Provider component, you can use the withRedux higher order component to inject ...

  8. I/O的方法、输入流和输出流

    1.文件常见方法 boolean flag=f.exists();   //文件是否存在 flag=f.isFile();     //是否是文件 flag=f.isDirectory(); //是否 ...

  9. canvas 绘制文本

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  10. 人生苦短之我用Python篇(基础)

    Python简介 Python,是一种面向对象的解释型计算机程序设计语言,由荷兰人Guido van Rossum于1989年发明,第一个公开发行版发行于1991年. Python是纯粹的自由软件, ...