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 ...
随机推荐
- 算法马拉松35 E 数论只会Gcd - 类欧几里得 - Stern-Brocot Tree - 莫比乌斯反演
题目传送门 传送门 这个官方题解除了讲了个结论,感觉啥都没说,不知道是因为我太菜了,还是因为它真的啥都没说. 如果 $x \geqslant y$,显然 gcd(x, y) 只会被调用一次. 否则考虑 ...
- oracle--ORA-38760
01,ORA-38760: This database instance failed to turn on flashback 02,问题处理思路 第一步:查看日志文件 查看这次启动的时候alter ...
- OsharpNS轻量级.net core快速开发框架简明入门教程-多上下文配置(多个数据库的使用)
OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...
- linux 修改oracle的字符集
select userenv('language') from dual; 命令可以查看服务端的使用的字符集. ssh登录,切换到oracle用户 切换用户命令:su -oracle 之后 ...
- 明解C语言 入门篇 第七章答案
练习7-1 #include <stdio.h> int main() { int n; printf(,, ); //此行显示结果为 4 3 6 因为1的字节就是为4,而-1的字节也是4 ...
- Vue.js 源码分析(五) 基础篇 方法 methods属性详解
methods中定义了Vue实例的方法,官网是这样介绍的: 例如:: <!DOCTYPE html> <html lang="en"> <head&g ...
- 小记:iterator && auto
小记:iterator && auto iterator 众所周知,我们有一种强大的东西,它叫做STL,比如queue.vector.set.map.multimap .deque等. ...
- springmvc项目转为springboot
说明 如果你的项目连maven项目都不是,请自行转为maven项目,在按照本教程进行. 本教程适用于spring+springmvc+mybatis+shiro的maven项目. 1.修改pom文件依 ...
- pymysql模块常用操作
pymysql安装 pip install pymysql 链接数据库.执行sql.关闭连接 import pymysql user = input('请输入用户名请输入密码:').strip() p ...
- 阅读prettytable 一些代码、get、set 检查参数
阅读代码是因为我发现官方教程里的代码在本地不能用,所以就通过”查看定义“转到了源代码里. 通过阅读源代码,查看方法内是否有教程中所说的方法名和参数名,然后再通过”查看引用“来试图了解函数的流程,如果没 ...