一,发生粘包

服务器端

 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. debug.js中的length的错误

    记得昨天报了一个错,debug.js文件中的length未定义.前台不定位代码,后天也不报错,而debug.js是框架封装的文件,不是自己写的,无从得知是哪里的问题,而项目也已经重新启动过,无法撤销. ...

  2. LightOJ - 1265 概率

    题意:有t头老虎,d头鹿,每天五种情况,虎虎,虎鹿,鹿鹿,鹿人,人虎,求生存的概率 题意:鹿就是来迷惑你的(结果我就陷进坑了),无论怎么选最后一定只剩下虎虎,虎人两种情况对结果有影响,那么如果有n只虎 ...

  3. redis memcache rabbitMQ

    Python之路[第九篇]:Python操作 RabbitMQ.Redis.Memcache.SQLAlchemy Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动 ...

  4. html03表单

    <!DOCTYPE HTML> <html> <head> <title>用户登录的表单</title> </head> < ...

  5. Ceph与OpenStack整合(仅为云主机提供云盘功能)

    1. Ceph与OpenStack整合(仅为云主机提供云盘功能) 创建: linhaifeng,最新修改: 大约1分钟以前 ceph ceph osd pool create volumes 128 ...

  6. v-if和v-show的区别

    v-if 是“真实”的条件渲染,因为它会确保条件块(conditional block)在切换的过程中,完整地销毁(destroy)和重新创建(re-create)条件块内的事件监听器和子组件. v- ...

  7. (六)java数据类型

      数据类型:决定了变量占据多大的空间,决定了变量存储什么类型的数据 整形: byte     1个字节 short    2个字节 int        4个字节 long     8个字节 浮点型 ...

  8. Cloudera Manager (centos)安装详细介绍

    文章全部来自:Cloudera Manager (centos)安装详细介绍http://www.aboutyun.com/thread-9190-1-1.html(出处: about云开发) 这里已 ...

  9. 剑指offer-第七章面试案例2(树中两个节点的公共祖先节点)

    import java.util.LinkedList; import java.util.Queue; import java.util.Stack; //树中两个节点的最低公共祖先 //第一种情况 ...

  10. OpenWRT mt7620n 系统升级引起的问题

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/qianguozheng/article/details/27237175 OpenWRT系统升级採用 ...