博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
31 socket套接字 struct模块
阅读量:6307 次
发布时间:2019-06-22

本文共 5356 字,大约阅读时间需要 17 分钟。

socket(套接字)

  基于socket实现客户端与服务端通信 

服务端套接字函数

s.bind()    绑定(主机,端口号)到套接字

s.listen()  开始TCP监听

s.accept()  被动接受TCP客户的连接,(阻塞式)等待连接的到来

 

客户端套接字函数

s.connect()    主动初始化TCP服务器连接

s.connect_ex()  connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

 

公共用途的套接字函数

s.recv()       接收TCP数据

s.send()       发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)

 socket初识

  127.0.0.1:本地回环地址,只能本机访问

-----------------------------服务端------------------------------import socketserver = socket.socket()  # 类似于买手机server.bind(('127.0.0.1', 8080))  # 类似于插手机卡   bind((IP,PORT))server.listen(5)  # 开机   半连接池conn, addr = server.accept()  # 待机等待接电话data = conn.recv(1024)  # 接听别人说话 只接收1024个字节 bytesprint(data)conn.send(b'hello!')  # 跟别人说话conn.close()  # 关闭通信连接server.close()  # 关闭服务端-----------------------------客户端------------------------------import socketclient = socket.socket()client.connect(('127.0.0.1', 8080))  # 找服务器client.send(b'hello how much?')data = client.recv(1024)print(data)client.close()

 TCP协议的特点

  会将数据量比较小的,并且时间间隔比较短的数据,一次性打包发送给接收端

-----------------------------服务端------------------------------import socketserver = socket.socket()server.bind(('127.0.0.1',8088))server.listen(5)  # 半连接池conn,addr = server.accept()data = conn.recv(1024)print(data)data = conn.recv(1024)print(data)data = conn.recv(1024)print(data)>>>:b'hellohellohello'   b''   b''-----------------------------客户端------------------------------import socketclient = socket.socket()client.connect(('127.0.0.1',8088))client.send(b'hello')client.send(b'hello')client.send(b'hello')

通信循环

-----------------------------服务端------------------------------import socket"""服务端:要有固定的ip和port24小时不间断提供服务"""server = socket.socket()server.bind(('127.0.0.1', 8080))server.listen(5)conn, addr = server.accept()  # 阻塞while True:    try:        data = conn.recv(1024)  # 阻塞        if len(data) == 0: break  # 针对linux和mac系统 客户端异常断开反复收空的情况        print(data)        conn.send(data.upper())    except ConnectionResetError:        breakconn.close()server.close()-----------------------------客户端------------------------------import socketclient = socket.socket()client.connect(('127.0.0.1', 8080))while True:    msg = input('>>>:').encode('utf-8')    if len(msg) == 0: continue    client.send(msg)    data = client.recv(1024)    print(data)

struct模块

import structdata = 'seionksngjgm,xmdnabnk ko'res = struct.pack('i',len(data))print('res:',res)   # res: b'\x18\x00\x00\x00'print('len(res):',len(res))  # 4ret = struct.unpack('i',res)print('ret:',ret)  # (24,)print('ret[0]:',ret[0])  # 24

链接循环

-----------------------------服务端------------------------------import socketimport subprocessimport structimport json"""服务端:要有固定的ip和port24小时不间断提供服务"""server = socket.socket()server.bind(('127.0.0.1', 8081))server.listen(5)  # 半连接池while True:    conn, addr = server.accept()  # 阻塞    while True:        try:            data = conn.recv(1024).decode('utf-8')  # 阻塞            if len(data) == 0: break  # 针对linux和mac系统 客户端异常断开反复收空的情况            obj = subprocess.Popen(data, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)            stdout = obj.stdout.read()            stderr = obj.stderr.read()            print(len(stdout + stderr))            header_dic = {                'filename': 'cls.av',                'len': len(stdout + stderr)            }            header_bytes = json.dumps(header_dic).encode('utf-8')            # 制作报头            header = struct.pack('i', len(header_bytes))  # 将需要发送给客户端的数据打包成固定4个字节            conn.send(header)            conn.send(header_bytes)            conn.send(stdout + stderr)        except ConnectionResetError:            break    conn.close()server.close()-----------------------------客户端------------------------------import socketimport structimport jsonclient = socket.socket()client.connect(('127.0.0.1', 8081))while True:    msg = input('>>>:').encode('utf-8')    if len(msg) == 0: continue    client.send(msg)    header = client.recv(4)    # 对这个头进行解包,获取真实数据的长度    head_len = struct.unpack('i', header)[0]    head_dic = json.loads(client.recv(head_len).decode('utf-8'))    print(head_dic)    # 对需要接受的数据 进行循环接收    total_size = head_dic['len']    recv_size = 0    res = b''    while recv_size < total_size:        data = client.recv(1024)        res += data        recv_size += len(data)    print(res.decode('gbk'))

粘包问题

-----------------------------服务端------------------------------import socket"""服务端:要有固定的ip和port24小时不间断提供服务"""server = socket.socket()server.bind(('127.0.0.1', 8080))server.listen(5)  # 半连接池while True:    conn, addr = server.accept()  # 阻塞    while True:        try:            data = conn.recv(1024)  # 阻塞            if len(data) == 0: break  # 针对linux和mac系统 客户端异常断开反复收空的情况            print(data)            conn.send(data.upper())        except ConnectionResetError:            break    conn.close()server.close()-----------------------------客户端------------------------------import socketclient = socket.socket()client.connect(('127.0.0.1', 8080))while True:    msg = input('>>>:').encode('utf-8')    if len(msg) == 0: continue    client.send(msg)    data = client.recv(1024)    print(data)

 

为什么会出现粘包现象

首先:只有在TCP协议中才会出现粘包现象,因为TCP协议是流式协议

特点:TCP协议会将数据量小并且时间间隔比较短的数据一次性打包发送出去
本质:其实还是因为我们不知道需要接收的数据的长短
# 如何解决粘包问题?
# 1 发送数据直接先告诉对方数据量的大小
# 2 利用struct模块定制我们自己的消息传输协议 

最终方法:解决粘包问题

 1.先发报头
 2.再发字典
 3.再发你的真实数据
 
 
 1.先收4个长度的报头
 2.解包拿到字典数据长度
 3.接收字典(反序列化) 》》》  获取字典里面所有信息
 4.接收真实数据

转载于:https://www.cnblogs.com/zhouyongv5/p/10797998.html

你可能感兴趣的文章
VLOOKUP+IF 组合用法
查看>>
Windows API 第21篇 DeleteVolumeMountPoint 删除挂载点
查看>>
Node.js:events事件模块
查看>>
C++ 内存分析-valgrind
查看>>
python调试pdb
查看>>
printf 详解 笔记
查看>>
PhotoSwipe-一个好用的图片放大缩小插件
查看>>
Swift 浅谈Struct与Class
查看>>
php ob_start callback failed
查看>>
linqjs
查看>>
apparent
查看>>
开源项目:高级SQL Server监控、性能图、分析与优化、版本控制
查看>>
汕头市队赛SRM07
查看>>
springmvc+jsp引用本地图片文件
查看>>
mysql cluster 安装配置方案
查看>>
文件操作
查看>>
依赖注入(DI)和控制反转(IOC)【回顾】
查看>>
[Reading]01/06/2012
查看>>
C#委托与事件
查看>>
ExtensionMethods Class
查看>>