socket(套接字) - 解决粘包问题 # 28

TCP协议类似打电话
UDP协议类似发短信
今日内容:
1."socket" 套接字
 1 """
 2 socket套接字
 3 """
 4 1.127.0.0.1本机回环地址,
 5     只能识别自己,其他人无法访问
 6 2.send与recv对应,
 7     不要出现两边都是相同的情况
 8 3.recv是跟内存要数据,
 9     至于数据的来源,你无需考虑
10 4.TCP特点:(自动优化机制)
11     会将数据量较小的并且时间间隔较短的数据,打包好,一次性发送给对方(造成粘包的原因之一)
12 
13 重点*************
14 1.socket简单版本:
15 服务器:
16     import socket
17     # 1.买手机,创建一个对象
18     server = socket.socket()
19     # 2.插卡 ,绑定IP+port
20     server.bind(("127.0.0.1",8089))
21     # 3.监听电话
22     server.listen()  # 参数为半连接数,为了保护传输路径
23     # 4.拨打电话 ,建立连接,获取连接地址和用户
24     client,addr = server.accpet()
25     # 5.通话,听,收
26     date = client.recv(1024)
27     date = date.decode('utf-8')
28     print(date)
29     # 6.通话,说,发
30     client.send(b'hello')
31     # 7.挂断电话
32     client.close()
33     # 8.关机
34     server.close()
35 客户端:
36     # 1.买手机,创建一个对象
37     client = socket.socket()
38     # 2.拨打电话
39     client.connect(("127.0.0.1",8089))
40     # 3.喂,说话,发
41     client.send(b'hhhaaa')
42     # 4.等别人回话
43     date = client.recv(1024)
44     date = date.decode('utf-8')
45     print(date)
46     # 5.挂电话
47     client.close()
48 2.socket解决粘包问题的最复杂版本
49 
50 3.知识点补充:
51 socket server实现tcp允许多个用户连接
52 1)在这里先介绍一个点
53 
54 有时候操作系统会运行的比较慢,造成你再用这个套接字的端口时,会刷新不过来
55 一般会在重启服务器时可能会遇到[Winerror 10048]通常套接字地址只允许使用一次
56 解决方案:
57 import socket
58 from socket import SOL_SOCKET,SO_REUSEADDR
59 sk = socket.socket()
60 sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
61 #在bind前面加这句话
62 sk.bind(('127.0.0.1',8090))
63 sk.linsten()
64 
65 4.解决粘包问题
66 服务器:
67     1,先制造一个发送给客户端的字典
68     2,制作字典的报头
69     3,发送字典的包头
70     4,发送字典
71     5,在发送真实数据
72 客户端:
73     1.先接收字典的报头
74     2.解析拿到字典的数据长度
75     3.接收字典
76     4.从字典中获取正式数据的长度
77     5.接收真实数据
78 5.作业:
79 写一个上传电影的功能
80     1.循环打印某一个文件夹下面的所有的文件
81     2.用户选取想要上传的文件
82     3.将用户选择的文件上传到服务端
83     4.服务端保存该文件
笔记

2.粘包问题
 1 4.解决粘包问题
 2 服务器:
 3     1,先制造一个发送给客户端的字典
 4     2,制作字典的报头
 5     3,发送字典的包头
 6     4,发送字典
 7     5,在发送真实数据
 8 客户端:
 9     1.先接收字典的报头
10     2.解析拿到字典的数据长度
11     3.接收字典
12     4.从字典中获取正式数据的长度
13     5.接收真实数据
解决粘包问题

1.复习-网络编程
  1.网络编程

 1 1.网络编程:
 2     计算机之间基于网络实现数据交互
 3 
 4 2.实现远程数据通信的必备条件:
 5     1.物理连接介质
 6     2.统一交互语言
 7 
 8 3.OSI七层架构协议:
 9     应用层
10     表示层
11     会话层
12     传输层
13     网络层
14     数据链路层
15     物理连接层
16 
17 4.OSI五层架构协议
18     1.精简版
19     应用层
20     传输层
21     网络层
22     数据链路层
23     物理连接层
24     2.详解
25         1.物理连接层
26             把电信号使用二进制转化传输
27         2.数据链路层
28             1.规定电信号转化的二进制的分组(方便读取识别 )
29             2.每个计算机都有唯一网卡
30                 网卡:计算机的唯一标识
31                     12位-16位进制
32                     前六位厂家编号
33                     后六位流水编号
34                     两者合一就是mac地址
35                     又称以太网协议,
36                         特点:通信基本靠吼
37                             广播
38                             单播
39                         1.交换机
40                         2.计算机与计算机通过交换机连接
41                     arp协议--一种算法
42                         根据IP地址获取,mac地址
43                     路由器:
44                         连接局域网
45         3.网络层
46             IP协议:点分十进制
47             IPV4 IPV6
48             port:0-65535
49             IP最小:0.0.0.0
50             IP最大:255.255.255.255
51             ip是计算机接入网络的标识,分配是随机的
52 
53         4.传输层
54             TCP协议/UDP协议
55             端口协议
56             port是计算机中应用程序接入网络的标识,分配亦是随机的,
57             IP+port 指的是计算机中应用程序与计算机中应用程序交互
58             mysql:3306 Redis:6379 Django:8000 flask:5000
59             域名解析
60     www.baidu.com      >>>     14.215.177.39:80
61             TCP协议可靠协议,流式协议
62             TCP称呼为可靠协议:它内置有反馈机制,客户端发送信息给服务器,客户端必须收到确认,否则,会在限定时间重新发送
63             三次握手建交(双向通道)
64             四次挥手断交
65 
66         5.应用层
67             HTTP协议
68             FTP协议
69             Django学
复习:网络编程


2.socket通信
  

 1 import socket
 2 
 3 # 1.买电话,创建一个socket对象
 4 client = socket.socket()
 5 # 2.拨号   写的是对方的ip和port
 6 client.connect(("127.0.0.1",8080))
 7 # 3.对别人说话
 8 client.send(b'hallo boy')
 9 # 4.听别人说话
10 date = client.recv(1024)
11 # date = date.decode('utf-8')
12 print(date)
13 # 5.挂电话
14 client.close()
client.py
 1 import socket
 2 # 1.买手机,不传参数,默认就是TCP协议
 3 server = socket.socket()
 4 # 2.插电话卡 绑定ip和端口
 5 server.bind(("127.0.0.1",8080))
 6 # 3.开机,监听 参数(半连接池)
 7 server.listen(5)
 8 # 4.接通  阻塞
 9 client,addr = server.accept()
10 # print(client,'1')
11 # print(addr,'2')
12 # 5.# 听别人说话 接收1024个字节数据    阻塞
13 date = client.recv(1024)
14 #date = date.decode('utf-8')
15 print(date)
16 # 6.# 给别人回话
17 client.send(b'hallo')
18 # 7.挂电话
19 client.close()
20 # 8.关机
21 # server.close()
server.py

3.socket循环健壮性
  

 1 import socket
 2 client = socket.socket()
 3 client.connect(("192.168.12.161",8999))
 4 while True:
 5     msg = input("msg>>>:").strip()
 6     if len(msg) == 0:continue
 7     client.send(msg.encode('utf-8'))
 8     date = client.recv(1024)
 9     print(date.decode('utf-8'))
10 
11     #client.close()
socket_client.py
 1 import socket
 2 
 3 # 1.买手机
 4 server = socket.socket()
 5 from socket import SOL_SOCKET,SO_REUSEADDR
 6 server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
 7 server.bind(("192.168.12.158",9000))
 8 server.listen()
 9 while True:
10     client,addr = server.accept()
11     while True:
12         date = client.recv(1024)
13         print(date.decode('utf-8'))
14        #  msg = input("msg>>>:").strip()
15         client.send(date.lower())
16 
17     client.close()
sorket_server.py

4.socket出现粘包问题
  

 1 import socket
 2 client = socket.socket()
 3 client.connect(("127.0.0.1",9125))
 4 while True:
 5     try:
 6         client.send(b'book')
 7         client.send(b'dog')
 8         client.send(b'llx')
 9         date = client.recv(1024)
10         date = date.decode('utf-8')
11         print(date)
12 
13     except EnvironmentError as f:
14         print(f)
15         break
16 
17     client.close()
client.py
 1 import socket
 2 
 3 server = socket.socket()
 4 server.bind(("127.0.0.1",9125))
 5 server.listen(5)
 6 while True:
 7     client,addr = server.accept()
 8     while True:
 9         try:
10             date = client.recv(1024)
11             date = date.decode('utf-8')
12             print(date)
13 
14             client.send(b'book')
15             client.send(b'dog')
16             client.send(b'llx')
17             # 值:bookdogllx
18         except EnvironmentError as f:
19             print(f)
20             break
21     client.close()
server.py

5.socket解决粘包问题subprocess
  

 1 import socket
 2 import struct
 3 import json
 4 
 5 client = socket.socket()
 6 client.connect(('127.0.0.1',9112))
 7 while True:
 8 
 9     msg = input('cmd>>>:').encode('utf-8')
10     if len(msg) == 0:continue
11     client.send(msg)
12     # 1.先接收字典报头
13     header_dict = client.recv(4)
14     # 2.解析报头
15     dict_size = struct.unpack('i',header_dict)[0]  # # 解包的时候一定要加上索引0
16     # 3.接收字典数据
17     dict_bytes = client.recv(dict_size)
18     dict_json = json.loads(dict_bytes.decode('utf-8'))
19     # 4.从字典中获取信息
20     print(dict_json)
21     # 判断是否接受完成
22     # 文件大小
23     recv_size = 0
24     # 文件本身
25     real_date = b''
26     while recv_size < dict_json.get('file_size'):
27         date = client.recv(1024)
28         real_date += date
29         recv_size += len(date)
30     print('文件大小',recv_size)
31     print('文件内容',real_date.decode('gbk'))
client.py
 1 import socket
 2 import struct
 3 import subprocess
 4 import json
 5 server = socket.socket()
 6 server.bind(('127.0.0.1',9112))
 7 server.listen(5)
 8 while True:
 9     conn,addr = server.accept()
10     while True:
11         try:
12             cmd = conn.recv(1024)
13             if len(cmd) == 0:break
14             cmd = cmd.decode('utf-8')
15             obj = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
16             res = obj.stdout.read() + obj.stderr.read()
17             d = {'name':'jason','file_size':len(res),'info':'sdsgfsgdgfdgdfgf'}
18             json_d = json.dumps(d)
19             # 1.先制作一个字典的报头
20             header = struct.pack('i',len(json_d))
21             # 2.发送字典报头
22             conn.send(header)
23             # 3.发送字典
24             conn.send(json_d.encode('utf-8'))
25             # 4.再发真实数据
26             conn.send(res)
27             # conn.send(obj.stdout.read())
28             # conn.send(obj.stderr.read())
29         except ConnectionResetError as f:
30             print(f)
31             break
32     conn.close()
server.py

 补充:

struct模块

 1 import struct
 2 
 3 
 4 # res = 'akdjsladlkjafkldjfgsdafhjksdfhfdgfdsgdfgssgdglkjdfsfdsadkfjlksdjf;klsdkl;fk;lsfdgklj;sfkldgj;kldfg;lfkd;lgk;lsdkfg;lkfd;glskljdklsajkldsa'
 5 # print('最原始的',len(res))
 6 
 7 # 当原始数据特别大的时候 i模式打包不了 需要更换模式?
 8 # 如果遇到数据量特别大的情况 该如何解决?
 9 d = {
10     'name':'jason',
11     'file_size':3455435435345354524534532456546546565466564366463654543453454353455,
12     'info':'为大家的骄傲'
13 }
14 import json
15 json_d = json.dumps(d)
16 print(len(json_d))
17 
18 
19 res1 = struct.pack('i',len(json_d))
20 print(len(res1))
21 
22 res2 = struct.unpack('i',res1)[0]
23 print('解包之后的',res2)
struct模块

subprocess模块

 1 import subprocess
 2 
 3 cmd = input('cmd>>>:')
 4 obj = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
 5 print(obj.stdout.read().decode('gbk'))  # 正确命令返回的结果
 6 print(obj.stderr.read().decode('gbk'))  # 错误的命令返回的结果
 7 
 8 # subprocess获取到的数据 拿完就没有了  不能重复的拿
 9 print(obj.stdout.read().decode('gbk'))  # 正确命令返回的结果
10 print(obj.stderr.read().decode('gbk'))  # 错误的命令返回的结果
subprocess模块

猜你喜欢

转载自www.cnblogs.com/llx--20190411/p/11318444.html