一、socket通信
1.客户端 import socket client = socket.socket() # 拿电话 client.connect(('127.0.0.1', 8080)) # 拨号 写的是对方的ip和port client.send(b'hello world!') # 对别人说话 data = client.recv(1024) # 听别人说话 print(data) client.close() # 挂电话
2.服务端 import socket server = socket.socket() # 买手机 不传参数默认用的就是TCP协议 server.bind(('127.0.0.1', 8080)) # bind((host,port)) 插电话卡 绑定ip和端口 server.listen(5) # 开机 半连接池 conn, addr = server.accept() # 接听电话 等着别人给你打电话 阻塞 data = conn.recv(1024) # 听别人说话 接收1024个字节数据 阻塞 print(data) conn.send(b'hello baby~') # 给别人回话 conn.close() # 挂电话 server.close() # 关机
二、连接循环+通讯循环
1.客户端 import socket client = socket.socket() # 拿到电话 client.connect(("127.0.0.1", 8080)) # 拨号 里面是访问的ip和端口 while True: msg = input("客户端说:").encode("utf8") if len(msg) == 0: continue client.send(msg) if msg.decode("utf8") == "bye": break data = client.recv(1024) # 听别人讲 print(data.decode("utf-8")) client.close()
2.服务端 import socket server = socket.socket() # 买个手机,不传参数就是默认TCP协议 server.bind(("127.0.0.1", 8080)) # 绑定ip地址和8080端口 server.listen(5) # 开机 半连接池(可以接收五个等待传输客户端) while True: # conn 是传输的数据 addr:客户端传输过来的ip和端口 conn, addr = server.accept() # 接通通讯,等待别人传输数据 data = conn.recv(1024).decode("utf8") # 接收数据,且最大能接收1024字节 print(data) if data == "bye": conn.close() # 挂机电话 server.close() break msg = input("服务器说:").encode("utf8") conn.send(msg) # conn.close() # 挂机电话 # server.close() # 关闭服务器
三、TCP粘包问题
同时执行多条命令之后,得到的结果很可能只有一部分,在执行其他命令的时候又接收到之前执行的另外一部分结果,这种显现就是黏包。
粘包:
1.传输过程中发送过快,内容比较小,会粘在一起
1.客户端 import socket client = socket.socket() # 拿电话 client.connect(('127.0.0.1',8080)) # 拨号 写的是对方的ip和port client.send(b'hello') client.send(b'world') client.send(b'baby') 2.服务端 import socket server = socket.socket() # 买手机 不传参数默认用的就是TCP协议 server.bind(('127.0.0.1', 8080)) # bind((host,port)) 插电话卡 绑定ip和端口 server.listen(5) # 开机 半连接池 conn, addr = server.accept() # 接听电话 等着别人给你打电话 阻塞 data = conn.recv(1024) # 听别人说话 接收1024个字节数据 阻塞 print(data) data = conn.recv(1024) # 听别人说话 接收1024个字节数据 阻塞 print(data) data = conn.recv(1024) # 听别人说话 接收1024个字节数据 阻塞 print(data) #三次接收可能一次就接收完
四、struck模块
import struct # res = 'akdjsladlkjafkldjfgsdafhjksdfhfdgfdsgdfgssgdglkjdfsfdsadkfjlksdjf;klsdkl;fk;lsfdgklj;sfkldgj;kldfg;lfkd;lgk;lsdkfg;lkfd;glskljdklsajkldsa' # print('最原始的', len(res)) # res1 = len(res) # print(res1) # 137 # res2 = struct.pack("i", len(res)) # print(len(res2)) # 4 # res3 = struct.unpack("i", res2)[0] # print(res3) # 解包之后137 # 当原始数据特别大的时候 i模式打包不了 需要更换模式? # 如果遇到数据量特别大的情况 该如何解决? d = { 'name': 'jason', 'file_size': 3455435435345354524534532456546546565466564366463654543453454353455, 'info': '为大家的骄傲' } import json json_d = json.dumps(d) print(len(json_d)) res1 = struct.pack('i', len(json_d)) print(len(res1)) res2 = struct.unpack('i', res1)[0] print('解包之后的', res2)
五、解决粘包问题
1.客户端 import socket import struct import json client = socket.socket() client.connect(('127.0.0.1', 8080)) while True: msg = input('>>>:').encode('utf-8') if len(msg) == 0: continue client.send(msg) # 1.先接受字典报头 header_dict = client.recv(4) # 2.解析报头 获取字典的长度 dict_size = struct.unpack('i', header_dict)[0] # 解包的时候一定要加上索引0 # 3.接收字典数据 ,字符串转成二进制中长度就等于字节大小 dict_bytes = client.recv(dict_size) dict_json = json.loads(dict_bytes.decode('utf-8')) # 4.从字典中获取信息 print(dict_json) recv_size = 0 real_data = b'' while recv_size < dict_json.get('file_size'): # real_size = 102400 data = client.recv(1024) real_data += data recv_size += len(data) print(real_data.decode('gbk')) 2.服务端 import socket import subprocess import struct import json server = socket.socket() server.bind(('127.0.0.1', 8080)) server.listen(5) while True: conn, addr = server.accept() while True: try: cmd = conn.recv(1024) if len(cmd) == 0: break cmd = cmd.decode('utf-8') obj = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) res = obj.stdout.read() + obj.stderr.read() d = {'name': 'jason', 'file_size': len(res), 'info': 'asdhjkshasdad'} json_d = json.dumps(d) # 1.先制作一个字典的报头 header = struct.pack('i', len(json_d)) # 2.发送字典报头 conn.send(header) # 3.发送字典 conn.send(json_d.encode('utf-8')) # 4.再发真实数据 conn.send(res) # conn.send(obj.stdout.read()) # conn.send(obj.stderr.read()) except ConnectionResetError: break conn.close()