1、socket模块使用要分为服务端及客户端,服务端用于接收并处理请求,然后把请求数据回传回到客户端,客户端用于读取数据、关闭连接、最后结束交互
2、服务端socket模块使用步骤:
1 import socket 2 3 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 4 phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # 5 phone.bind(('127.0.0.1',8080)) #绑定(主机,端口号)到套接字 6 7 phone.listen(5) #开始TCP监听 8 9 conn,client_addr=phone.accept() #被动接受TCP客户的连接,(阻塞式)等待连接的到来 10 11 client_data=conn.recv(1024) # 接收TCP数据 最大1024字节 12 conn.send(client_data.upper()) #发送TCP数据 13 14 15 conn.close() #关闭TCPl连接 16 17 phone.close() #关闭套接字
3、客户端socket模块使用步骤:
1 import socket 2 3 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 4 phone.connect(('127.0.0.1',8080)) #连接服务端的ip+port 5 6 7 msg=input('>>:').strip() 8 9 phone.send(msg.encode('utf-8')) #向服务端发送信息 10 server_data=phone.recv(1024) #接收服务端的信息 11 12 13 phone.close() #关闭连接
4、socket模块是基于TCP或UDP协议实现的,由于TCP协议是流式数据,所以基于tcp协议的socket会出现粘包现象,解决粘包现象需要使用 struct模块。
struct模块的用途:把一个类型,如数字,转成固定长度的bytes
使用方法:a=struct.pack('i',123123123123) # 将123123123123装换成4个bytes长度;
stauct.unpack('i',a)[0] #提取123123123123
详细类型转换如图:
处理粘包问题:
我们可以把报头做成字典,字典里包含将要发送的真实数据的详细信息,然后json序列化,然后用struck将序列化后的数据长度打包成4个字节(4个自己足够用了)
发送时:先发报头长度
再编码报头内容然后发送
最后发真实内容
接收时:先手报头长度,用struct取出来
根据取出的长度收取报头内容,然后解码,反序列化
从反序列化的结果中取出待取数据的详细信息,然后去取真实的数据内容
1 import socket,struct,json 2 import subprocess 3 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 4 phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #就是它,在bind前加 5 6 phone.bind(('127.0.0.1',8080)) 7 8 phone.listen(5) 9 10 while True: 11 conn,addr=phone.accept() 12 while True: 13 cmd=conn.recv(1024) 14 if not cmd:break 15 print('cmd: %s' %cmd) 16 17 res=subprocess.Popen(cmd.decode('utf-8'), 18 shell=True, 19 stdout=subprocess.PIPE, 20 stderr=subprocess.PIPE) 21 err=res.stderr.read() 22 print(err) 23 if err: 24 back_msg=err 25 else: 26 back_msg=res.stdout.read() 27 28 29 conn.send(struct.pack('i',len(back_msg))) #先发back_msg的长度 30 conn.sendall(back_msg) #在发真实的内容 31 32 conn.close() 33 34 服务端(自定制报头)
1 #_*_coding:utf-8_*_ 2 import socket,time,struct 3 4 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 5 res=s.connect_ex(('127.0.0.1',8080)) 6 7 while True: 8 msg=input('>>: ').strip() 9 if len(msg) == 0:continue 10 if msg == 'quit':break 11 12 s.send(msg.encode('utf-8')) 13 14 15 16 l=s.recv(4) 17 x=struct.unpack('i',l)[0] 18 print(type(x),x) 19 # print(struct.unpack('I',l)) 20 r_s=0 21 data=b'' 22 while r_s < x: 23 r_d=s.recv(1024) 24 data+=r_d 25 r_s+=len(r_d) 26 27 # print(data.decode('utf-8')) 28 print(data.decode('gbk')) #windows默认gbk编码 29 30 客户端(自定制报头)