socket套接字及粘包问题
socket套接字
1、什么是socket
socket是一个模块,又称套接字,用来封装互联网协议(应用层以下的层)
2、为什么要有socket
实现应用层以下的层的工作,提高开发效率
3、怎么使用socket
先导入socket模块,先启动服务端套接字,再启动客户端套接字
# 服务端
import socket
# 买手机
server = socket.socket()
# 绑定手机号(IP,port)
# IP单机模式是127.0.0.1,局域网内使用cmd中ipconfig查询IPV4
# port设置8000以后的数据
server.bind(('127.0.0.1', 9876))
# 设置半连接池
server.listen(4)
# 可接收多个客户端数据连接,实现循环通信
while True:
# 接收客户端连接
conn, addr = server.accept()
# 查看对方地址
print(addr)
while True:
# 捕获异常机制
try:
# 接收客户端发来的数据,可一次接收1024bytes的数据
data = conn.recv(1024)
if len(date) == 0:
break
if data.decode('utf-8') == 'q':
break
print(data.decode('utf-8'))
# 向客户端发送消息
send_data = input('请输入向客户端发送的数据:')
conn.send(send_data.encode('utf-8'))
# 捕获异常,并打印出错误信息
except Exception as e:
print(e)
break
# 挂电话
conn.close()
# 客户端
import socket
# 买手机
client = socket.socket()
# 建立连接(IP,port)
client.connect(('127.0.0.1',9876))
while True:
try:
# 向对方发送数据
data = input('请输入向服务端发送的数据')
client.send((data.encode('utf--8')))
# 接收对方发来的数据可设置一次接收的bytes数,并打印
res_data = client.recv(1024)
if len(res_data) == 0:
break
if res_data.decode('utf-8') == 'q':
break
print(res_data.decode('utf-8'))
# 捕获异常,并打印出异常
except Exception as e:
print(e)
break
client.close()
粘包问题
问题1:
无法确认对方发送过来数据大小
问题2:
在发送数据间隔短并且数据量小的情况下,会将所有数据一次性发送
解决:需要确认对方发送的数据大小
# 客户端
# 问题1
import socket
client = socket.socket()
client.connect(('127.0.0.1', 9876))
while True:
try:
cmd = input('请输入向服务端发送的命令:')
client.send(cmd.encode('utf-8'))
# 接收服务端返回的数据
# 由于不知道会返回多少个bytes所以有问题1
date = client.recv(11910)
print(len(date))
print(date.decode('gbk'))
except Exception as e:
print(e)
break
client.close()
# 客户端
# 问题2
# 时间间隔短,并数据量小的情况下,会将所有的数据一次性发送,接收时不知道具体有几个
import socket
client = socket.socket()
client.connect(('127.0.0.1', 9876))
client.send(b'hello')
client.send(b'hello')
client.send(b'hello')
client.send(b'hello')
client.send(b'hello')
# 服务端
import socket
import subprocess
server = socket.socket()
server.bind(('127.0.0.1', 9876))
server.listen(4)
while True:
conn, addr = server.accept()
print(addr)
while True:
try:
# 接收客户端的数据,具体值不知道多大,所有有可能不能完全接收,有可能浪费资源
cmd = conn.recv(12)
if len(cmd) == 0:
break
cmd = cmd.decode('utf-8')
if cmd == 'q':
break
# 调用subprocess连接终端,对终端进行操作,并获取正确和错误的结果
obj = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# 拿到结果,并打印
result = obj.stdout.read() + obj.stderr.read()
print(result.decode('gbk'))
# 将结果返回给客户端
conn.send(result)
except Exception as e:
print(e)
break
conn.close()
解决粘包问题
使用struct模块
struct 是一个python内置的模块,它可以将固定长度的数据,打包成固定格式的长度
模式:i:4,或其他模式
作用:将真实数据做成一个固定长度的报头,发送给服务端,服务端接收报头,然后进行解包,获取真实数据的长度,进行接收数据即可
import struct
data = input('请输入传的数据').strip()
data = data.encode('utf-8')
# 制作报头,需要 i 的字符串和传入数据的长度
header = struct.pack('i',len(data))
print(header)
print(len(header))
# 解包( i 的字符串和报头)获取真实长度,得到一个元组,拿到元组第一个数就是真实长度
res = struct.unpack('i', header)[0]
print(res)
# utf-8中一个中文是3个bytes,一个英文是1个bytes
客户端:
1.先制作报头,并发送
2.发送真实数据
服务端:
1.接收报头,并且解包获取真实数据长度
2.根据真实数据长度,接收真实数据
# 客户端
import socket
import struct
client = socket.socket()
client.connect(('127.0.0.1', 9876))
while True:
try:
cmd = input('请输入向服务端发送的命令')
cmd_bytes = cmd.encode('utf-8')
# 做一个报头
header = struct.pack('i', len(cmd_bytes))
# 发送报头
client.send(header)
# 发送真实数据
client.send(cmd_bytes)
# 接受服务端返回的报头
reheader = client.recv(4)
# 解包
data_len = struct.unpack('i', reheader)[0]
result = client.recv(data_len)
print(result.decode('gbk'))
except Exception as e:
print(e)
break
client.close()
# 服务端
import socket
import subprocess
import struct
server = socket.socket()
server.bind(('127.0.0.1', 9876))
server.listen(5)
while True:
conn, addr = server.accept()
while True:
try:
# 获取报头
header = conn.recv(4)
# 获取真实数据长度
data_len = struct.unpack('i', header)[0]
# 准备接受真实数据
cmd = conn.recv(data_len)
cmd = cmd.decode('utf-8')
if cmd == 'q':
break
if len(cmd) == 0:
break
obj = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
result = obj.stdout.read() + obj.stderr.read()
print(len(result))
print(result.decode('gbk'))
# 将结果返回给客户端
header = struct.pack('i', len(result))
conn.send(header)
conn.send(result)
except Exception as e:
print(e)
break
conn.close()
# 客户端
import socket
import struct
import json
client = socket.socket()
client.connect(('127.0.0.1', 9876))
while True:
# 伪装电影数据
movie_name = input('请输入电影名称:')
movie_len = 10000101
send_dic = {
'movie_name': movie_name,
'movie_len': movie_len
}
# 序列化
json_data = json.dumps(send_dic)
# 制作报头
json_bytes = json_data.encode('utf-8')
header = struct.pack('i', len(json_bytes))
# 发送报头
client.send(header)
# 发送真实数据
client.send(json_bytes)
# 服务端
import socket
import json
import struct
server = socket.socket()
server.bind(('127.0.0.1', 9876))
server.listen(5)
while True:
conn, addr = server.accept()
print(addr)
while True:
try:
# 接收报头
header = conn.recv(4)
# 解包获取真实长度
json_len = struct.unpack('i', header)[0]
# 接收真实长度
json_bytes_data = conn.recv(json_len)
json_data = json_bytes_data.decode('utf-8')
# 反序列化得到数据
back_dic = json.loads(json_data)
print(back_dic)
except Exception as e:
print(e)
break
conn.close()
socket套接字及粘包问题的更多相关文章
- 网络编程——TCP协议、UDP协议、socket套接字、粘包问题以及解决方法
网络编程--TCP协议.UDP协议.socket套接字.粘包问题以及解决方法 TCP协议(流式协议) 当应用程序想通过TCP协议实现远程通信时,彼此之间必须先建立双向通信通道,基于该双向通道实现数 ...
- 网络编程 TCP协议:三次握手,四次回收,反馈机制 socket套接字通信 粘包问题与解决方法
TCP协议:传输协议,基于端口工作 三次握手,四次挥手 TCP协议建立双向通道. 三次握手, 建连接: 1:客户端向服务端发送建立连接的请求 2:服务端返回收到请求的信息给客户端,并且发送往客户端建立 ...
- 02网络编程( socket套接字+TCP粘包 )
目录 02 网络编程 一.socket套接字编程 二.简易代码模板 2.1 服务端 2.2 客户端 三.通信循环及代码优化 四.黏包现象 五.struct模块 六.简易版本报头 七.上传文件数据 * ...
- python开发socket套接字:粘包问题&udp套接字&socketserver
一,发生粘包 服务器端 from socket import * phone=socket(AF_INET,SOCK_STREAM) #套接字 phone.setsockopt(SOL_SOCKET, ...
- TCP Socket 套接字 和 粘包问题
一.Scoket 套接字 Scoket是应用层(应用程序)与TCP/IP协议通信的中间软件抽象层,它是一组接口.也可以理解为总共就三层:应用层,scoket抽象层,复杂的TCP/IP协议 基于TCP协 ...
- python基础--socket套接字、粘包问题
本地回环地址:127.0.0.1 简易版服务端: import socket server = socket.socket() # 就比如买了一个手机 server.bind(("127 ...
- day34 基于TCP和UDP的套接字方法 粘包问题 丢包问题
TCP 基于流的协议 又叫可靠性传输协议 通过三次握手 四次挥手 来保证数据传输完毕 缺点效率低 正因为是基于流的协议 所以会出现粘包问题粘包问题:原因一:是应为数据是先发送给操作系统,在操作系统中有 ...
- Day09: socket网络编程-OSI七层协议,tcp/udp套接字,tcp粘包问题,socketserver
今日内容:socket网络编程 1.OSI七层协议 2.基于tcp协议的套接字通信 3.模拟ssh远程执行命令 4.tcp的粘包问题及解决方案 5.基于udp协议的套接字 ...
- 基于UDP的套接字、粘包问题
一.基于UDP的套接字 UDP服务端 ss = socket() #创建一个服务器的套接字 ss.bind() #绑定服务器套接字 inf_loop: #服务器无限循环 cs = ss.recvfro ...
随机推荐
- SpringBoot第四篇:整合JDBCTemplate
作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/10868954.html 版权声明:本文为博主原创文章,转载请附上博文链接! 引言 前面几篇文 ...
- WebStorm开发Vue自定义标签提示是未知标签解决办法
打开 File -> Settings -> File Types 在右侧的窗口中找到Vue.js Template 并选中,在下面的窗口中添加 *.vue 即可解决问题. 修改后
- linux重定向 null和zero
文件描述符 linux下一切皆文件 文件描述符,是内核为了高效管理已经被打开的文件所创建的索引,用于指向被打开的文件,所有执行I/O操作的系统调用都通过文件描述符; 文件描述符是一个简单的非负整数,用 ...
- 19条常用的MySQL优化方法(转)
本文我们来谈谈项目中常用的MySQL优化方法,共19条,具体如下:1.EXPLAIN命令做MySQL优化,我们要善用EXPLAIN查看SQL执行计划.下面来个简单的示例,标注(1.2.3.4.5)我们 ...
- git本地代码管理
git真的是一个代码管理神器,帮助我们在代码开发过程中更好的进行版本管理,如果没有版本管理器,就要不停的复制粘贴,一个项目开发下来,一堆的版本文件夹,最后都不知道是哪个版本了. 用git之后,每一次的 ...
- linux 开机mount nfs
mount -t nfs 10.208.1.235:/home/gis/bigrasterdata/mxds/uploads /usr/local/website/upload/pythonmxds ...
- 【linux】CentOS 查看系统时间,修改时区
===============CentOS 7.6================ 1.查看系统时间 date 查看当前系统时间以及时区结果是: Mon Jul 8 09:23:31 UTC 2019 ...
- Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理
Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理 本文链接:https://blog.csdn.net/puhaiyang/article/details/78146620 ...
- C#中几种单例模式
1.静态代码块 /// <summary> /// 静态代码块 /// 仅在第一次调用类的任何成员时自动执行 /// </summary> public class Singl ...
- 【C#】Winform 令人困擾的畫面閃爍問題解法
DoubleBuffered = true 如果 Control 沒有這個屬性,可以使用我下列擴充函式進行設定︰ public static void SetDoubleBuffered<T&g ...