socket

基于tcp协议socket

服务端

import socket

phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 买电话
# socket.SOCK_STREAM 流式协议 就是TCP协议
phone.bind(('127.0.0.1', 8080)) # 买电话卡 phone.listen(5) # 开机。
# 5 不是链接数,链接可以产生N个,同一时刻只能监听5个请求。 conn, addr = phone.accept() # 等待接电话 # 阻塞状态
# print(222)
print(conn, addr) # conn 代表的是socket通信的对象,一个管道 client_data = conn.recv(1024) # 交流过程
print(client_data)
conn.send(client_data.upper()) conn.close()
phone.close()

客户端

import socket

phone = socket.socket()  # 买电话

phone.connect(('127.0.0.1', 8080))  # 拨号

msg = input('>>>').strip()
phone.send(msg.encode('utf-8'))
server_data = phone.recv(1024) # 限制的是最大接收字节数。
print(server_data)
phone.close()

服务端与客户端循环 聊

import socket
import subprocess
# socket.SOCK_STREAM 流式协议 就是TCP协议
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 买电话
phone.bind(('127.0.0.1', 8080)) # 绑定电话卡,写自己的IP (俩括号)
phone.listen(5) #开机 5不是限制连接数,而是同一时刻只接受5个请求,可以不写,不写为默认,默认可以开启N个
#运行后停在这里,下边不执行
while 1:
conn,addr = phone.accept() #等待接电话 phone.accept() conn和addr分别接收phone..accept()生成的两个参数
print(addr) #打印连接进来的客户端
while 1:
try:
client_data = conn.recv(1024) #接受的字节数
c = client_data.decode('gbk')
obj = subprocess.Popen(c,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
RET = obj.stdout.read()
RET1 = obj.stderr.read()
print(RET.decode('gbk'))
conn.send(RET+RET1) #返回的信息
except Exception:
break
conn.close()
phone.close()

客户端

import socket
phone = socket.socket()
phone.connect(('127.0.0.1', 8080)) # 拨号,写服务端的IP (俩括号)
while 1:
fasong = input('>>>')
if fasong.upper() == 'Q': break
elif not fasong :continue #如果发送为空,则跳过本次循环 not False3 = True
phone.send(fasong.encode('gbk')) #刚给服务端发信息
server_data = phone.recv(1024) #接收服务端的信息,1024限制的是最大接受的字节数
print(server_data.decode('gbk'))
phone.close()

subprocess模块

subprocess模块用于接收shell界面执行的命令并返回结果

import subprocess
obj = subprocess.Popen('ip a', #输入命令
shell=True, #shell为Tree
stdout=subprocess.PIPE, #stdout接收正确
stderr=subprocess.PIPE) #stderr接收错误返回
RET = obj.stdout.read()
print(RET.decode('utf-8'))

粘包现象

tcp协议

1. 流式协议.数据全部都像水一样连在一起,一次性发送多字节(全部在客户端操作系统的缓存区),客户端每次只取1024字节,剩余字节在缓存区等待下次取

client_data = conn.recv(1024)    
server_data = phone.recv(1024)    

2.针对于(客户端/服务端)发送的连续的小的数据,对方会一次性接收.

客户端

import socket
phone = socket.socket()
phone.connect(('127.0.0.1', )) # 拨号,写服务端的IP (俩括号)
phone.send(b'hello') #先发送hello
phone.send(b'word') #紧接着在发送word
while :
server_data = phone.recv() #接收服务端的信息,1024限制的是最大接受的字节数
print(server_data.decode('gbk'))
phone.close()

服务端

import socket
import subprocess
# socket.SOCK_STREAM 流式协议 就是TCP协议
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 买电话
phone.bind(('127.0.0.1', )) # 绑定电话卡,写自己的IP (俩括号)
phone.listen() #开机 5不是限制连接数,而是同一时刻只接受5个请求,可以不写,不写为默认,默认可以开启N个
#运行后停在这里,下边不执行
conn,addr = phone.accept() #等待接电话 phone.accept() conn和addr分别接收phone..accept()生成的两个参数
print(addr) #打印连接进来的客户端
while :
client_data = conn.recv() #接受的字节数
print(client_data)
conn.send(client_data.upper()) #返回的信息
conn.close()
phone.close() ('127.0.0.1', ) #服务端接收客户端的信息连在了一起
b'helloword'

客户端

import socket
import time
phone = socket.socket()
phone.connect(('127.0.0.1', )) # 拨号,写服务端的IP (俩括号)
phone.send(b'hello')
time.sleep(0.1) #等待0.1秒在发送word
phone.send(b'word')
while :
server_data = phone.recv() #接收服务端的信息,1024限制的是最大接受的字节数
print(server_data.decode('gbk'))
phone.close()

服务端

import socket
import subprocess
# socket.SOCK_STREAM 流式协议 就是TCP协议
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 买电话
phone.bind(('127.0.0.1', )) # 绑定电话卡,写自己的IP (俩括号)
phone.listen() #开机 5不是限制连接数,而是同一时刻只接受5个请求,可以不写,不写为默认,默认可以开启N个
#运行后停在这里,下边不执行
conn,addr = phone.accept() #等待接电话 phone.accept() conn和addr分别接收phone..accept()生成的两个参数
print(addr) #打印连接进来的客户端
while :
client_data = conn.recv() #接受的字节数
print(client_data)
conn.send(client_data.upper()) #返回的信息
conn.close()
phone.close() ('127.0.0.1', ) #接受的字符分开了
b'hello'
b'word'

解决粘包问题

发送固定头部,固定头部包含(数据的总大小) + 数据

struct模块  将一个数据,int 转化为固定的bytes

import struct
ret = struct.pack('i',) #将151923212 转换为固定的bytes类型
print(ret,type(ret) ,len(ret),sep='\n') #sep='\n',将分隔符换为\n ret1 = struct.unpack('i',ret)
print(ret1) b'\x0c*\x0e\t'
<class 'bytes'>
4 #转为固定的4字节
(,)

解决粘包问题代码

low版

一旦数据传入过大则struct模块报错, struct模块不能转译 较长的字符串

服务端:

将数据大小通过struct模块转为固定大小发给客户端

import socket
import subprocess
import struct
# socket.SOCK_STREAM 流式协议 就是TCP协议
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 买电话
phone.bind(('127.0.0.1', 8080)) # 绑定电话卡,写自己的IP (俩括号)
phone.listen(5) #开机 5不是限制连接数,而是同一时刻只接受5个请求,可以不写,不写为默认,默认可以开启N个
#运行后停在这里,下边不执行
conn,addr = phone.accept() #等待接电话 phone.accept() conn和addr分别接收phone..accept()生成的两个参数
print(addr) #打印连接进来的客户端
while 1 : #以下为粘包解决方法
try:
client_data = conn.recv(1024) # 接受的字节数
obj = subprocess.Popen(client_data.decode('utf-8'), #将接收的字节在本地shell执行 并返回结果
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,)
ret = obj.stdout.read() #正确结果
ret1 = obj.stderr.read() #错误结果
ss = len(ret1 + ret) #算返回结果的总长度
ret2 = struct.pack('i',ss) #通过struct将算返回结果的总长度变为固定长度的bytes类型
conn.send(ret2) #发送报头
conn.send(ret) #发送正确结果
conn.send(ret1) #发送错误结果
except Exception:
break
conn.close()
phone.close()

客户端:

客户端根据服务端发来的内容大小取内容

import socket
import time
import struct phone = socket.socket()
phone.connect(('127.0.0.1', 8080)) # 拨号,写服务端的IP (俩括号)
while 1:
msg = input('>>>').strip() #输入发往服务端的内容,如果是q退出,如果是空从新输入
if msg.upper() == 'Q':
break
elif not msg: #not + 空就是 True 执行continue 重新输入
continue
phone.send(msg.encode('utf-8')) #往服务端发送内容
head = phone.recv(4) #接收报头 报头大小为固定4字节
head_size = struct.unpack('i', head)[0] #直接将报头反解为服务端发送内容的长度,返回是元组,取第一个值
datas = 0    #定义一个datas大小为0
res = b'' #定义一个空的bytes类型的变量
while datas < head_size: #如果datas小于发送的内容的总长度为真
data = phone.recv(1024) #取1024字节
res = res + data #将取出的内容追加到res里
datas += len(data) #datas加上取出内容字节的大小
print(res.decode('gbk')) #读出res里的内容 phone.close()
uper版

服务端:

将服务端发送数据大小写到字典,

将字典转为json,

再将json转为字符串,

取字符串长度给struct模块转为固定大小

将固定大小,bytes类型的字典以及所有数据传给客户端

import socket
import subprocess
import struct
import json
# socket.SOCK_STREAM 流式协议 就是TCP协议
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 买电话
phone.bind(('127.0.0.1', 8080)) # 绑定电话卡,写自己的IP (俩括号)
phone.listen(5) #开机 5不是限制连接数,而是同一时刻只接受5个请求,可以不写,不写为默认,默认可以开启N个
#运行后停在这里,下边不执行
conn,addr = phone.accept() #等待接电话 phone.accept() conn和addr分别接收phone..accept()生成的两个参数
print(addr) #打印连接进来的客户端
while 1 :
try:
client_data = conn.recv(1024) # 接受的字节数
obj = subprocess.Popen(client_data.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,)
ret = obj.stdout.read()
ret1 = obj.stderr.read()
ss = len(ret1 + ret)
head_dict = { #定义一个字典,total_size的值为发送数据的大小,字典里可定义多个键值传递多种信息
'total_size':ss
}
head_json = json.dumps(head_dict) #将字典转为json格式
head_bytes = head_json.encode('utf-8') #再将json格式转为bytes格式
ret2 = struct.pack('i',len(head_bytes)) #将转为bytes格式的长度通过struct转为固定字节 conn.send(ret2) #发送固定字节
conn.send(head_bytes) #发送bytes类型的字典
conn.send(ret) #发送内容
conn.send(ret1)
except Exception:
break
conn.close()
phone.close()

客户端:

将服务端发送的头部大小获取字典大小

通过字典大小获取内容大小

通过内容大小获取内容

import socket
import json
import struct phone = socket.socket()
phone.connect(('127.0.0.1', 8080)) # 拨号,写服务端的IP (俩括号)
while 1:
msg = input('>>>').strip()
if msg.upper() == 'Q':
break
elif not msg:
continue
phone.send(msg.encode('utf-8'))
he = struct.unpack('i', phone.recv(4))[0] #将头部的大小(phone.recv(4))通过struct模块解析出字典bytes类型的大小
head_dic_bytes = phone.recv(he) #通过解析出字典bytes类型的大小获取bytes类型字典的数据
head_json = head_dic_bytes.decode('utf-8') #将bytes数据反解为json类型
head_doc = json.loads(head_json) #反解json获得字典
datas = 0
res = b''
while datas < head_doc['total_size']: #将字典total_size键对应的内容大小的值取出,获得内容
data = phone.recv(1024)
res = res + data
datas += len(data)
print(res.decode('gbk')) phone.close()

基于UDP的套接字协议

服务端

import socket
udp_sk = socket.socket(type=socket.SOCK_DGRAM) # (type=socket.SOCK_DGRAM)基于UDP的套接字TCP为socket.AF_INET, socket.SOCK_STREAM udp_sk.bind(('127.0.0.1', 10000)) #绑定服务器套接字 while 1:
msg, addr = udp_sk.recvfrom(1024) #tcp里的accept()里的recv() 是阻塞的 这里的recvfrom(1024)是非阻塞的
print(msg.decode('utf-8')) #打印内容
udp_sk.sendto(b'hi',addr) #返回给客户端的内容

客户端

import socket
ip = ('127.0.0.1',10000) #创建个IP
udp_sk=socket.socket(type=socket.SOCK_DGRAM) #开启udp的socket
while 1:
sd = input('>>>').encode('utf-8')
udp_sk.sendto(sd,ip) #给服务端发送内容
back_msg,addr=udp_sk.recvfrom(1024) #获取服务端回复的内容
print(back_msg.decode('utf-8'),addr) #打印服务端回复的内容
udp_sk.close()

python笔记8 socket(TCP) subprocess模块 粘包现象 struct模块 基于UDP的套接字协议的更多相关文章

  1. (day27)subprocess模块+粘包问题+struct模块+ UDP协议+socketserver

    目录 昨日回顾 软件开发架构 C/S架构 B/S架构 网络编程 互联网协议 socket套接字 今日内容 一.subprocess模块 二.粘包问题 三.struct模块 四.UDP 五.QQ聊天室 ...

  2. python socket的应用 以及tcp中的粘包现象

    1,socket套接字 一个接口模块,在tcp/udp协议之间的传输接口,将其影藏在socket之后,用户看到的是socket让其看到的. 在tcp中当做server和client的主要模块运用 #s ...

  3. 基于UDP的套接字、粘包问题

    一.基于UDP的套接字 UDP服务端 ss = socket() #创建一个服务器的套接字 ss.bind() #绑定服务器套接字 inf_loop: #服务器无限循环 cs = ss.recvfro ...

  4. 8.7 day28 网络编程 socket套接字 半连接池 通信循环 粘包问题 struct模块

    前置知识:不同计算机程序之间的数据传输 应用程序中的数据都是从程序所在计算机内存中读取的. 内存中的数据是从硬盘读取或者网络传输过来的 不同计算机程序数据传输需要经过七层协议物理连接介质才能到达目标程 ...

  5. socket模块粘包现象理解以及解决思路

    粘包现象: 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发两端(客户端和服务器端)都要有成对的socket,因此,发送端为了将多个发往接收端的 ...

  6. Day9 基于TCP的套接字和基于UDP的套接字

    服务端: ss=socket() #创建服务器套接字 ss.bind() #把地址绑定到套接字 ss.listen() #监听套接字, inf_loop: #服务器无限循环 cs=ss.accept( ...

  7. python网络编程-socket套接字通信循环-粘包问题-struct模块-02

    前置知识 不同计算机程序之间数据的传输 应用程序中的数据都是从程序所在计算机内存中读取的. 内存中的数据是从硬盘读取或者网络传输过来的 不同计算机程序数据传输需要经过七层协议物理连接介质才能到达目标程 ...

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

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

  9. socket原理-基于UDP的套接字-基于TCP实现远程命令-粘包

随机推荐

  1. syzkaller安装

    初始环境配置 sudo apt-get install subversion sudo apt-get install g++ sudo apt-get install git sudo apt in ...

  2. 软件测试_Loadrunner_性能测试_脚本优化_关联_手动关联

    在写文章之前写一下自己的心路历程,录制脚本主要是上传图片并返回查询结果的过程.录制完脚本后发现函数中URl地址中有图片ID后台随机生成的32位随机数,并且每次上传图片id都会变化.我就上网搜索了一些解 ...

  3. 算法102----360笔试(m进制不进位相加最大值)

    转自:https://blog.csdn.net/qq_18310041/article/details/99656445 import copy # m进制 m = 5 n = 5 line = [ ...

  4. golang 时间的比较,time.Time的初始值?

    参考: https://golangcode.com/checking-if-date-has-been-set/ https://stackoverflow.com/questions/209243 ...

  5. machine learning(12) -- classification: One-vs-all classfication

    Multiclass classification例子: 邮箱的邮件的分类: 工作邮件,私人邮件,朋友的邮件,兴趣爱好的邮件 医学诊断: 没有生病,患有流感,患有普通感冒 天气: 晴天,兩,多云等 O ...

  6. glog的安装使用

    参考 :https://blog.csdn.net/Pig_Pig_Bang/article/details/81632962 https://blog.csdn.net/cywtd/article/ ...

  7. iptables 相关命令

    1. 清除已有iptables规则 iptables -F iptables -X iptables -Z 2. 开放指定的端口(添加规则) iptables -A INPUT -s 127.0.0. ...

  8. JavaSctipt 常用字符串 方法及使用方式

    1. charAt(x) charAt(x)返回字符串中x位置的字符,下标从 0 开始. //charAt(x) var myString = 'jQuery FTW!!!'; console.log ...

  9. MySql存储过程参考

    Mysql(9)---纪录一次实际开发过程中用到的复杂存储过程 为了尽可能的还原当时为什么需要用到存储过程,下面我写了个详细的文档,我们可以从需求文档出发来分析. 有关存储过程之前也写了两篇文章来做铺 ...

  10. sql的九个常用语句是什么

    一.基础1.说明:创建数据库CREATE DATABASE database-name2.说明:删除数据库drop database dbname3.说明:备份sql server--- 创建 备份数 ...