socket,socketserver,tcp黏包问题,网络编程
程序员文章站
2022-03-19 23:45:11
1,socket的使用 1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # @time : 2019/6/13 19:36 4 # @Author : aolishuai 5 # @File : 服务端 6 7 import socket 8 ......
1,socket的使用
- 基于tcp的socket的使用
tcp是有链接,面向流的,客户端和服务端一旦连接,不在断开的时候是不会断的
简单使用1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # @time : 2019/6/13 19:36 4 # @author : aolishuai 5 # @file : 服务端 6 7 import socket 8 9 #创建一个socket对象 10 server = socket.socket()#创建一个手机 11 12 ip_port = ('192.168.1.9',8001)#创建一张电话卡 13 14 server.bind(ip_port)#插上电话卡 15 16 #监听ip地址和端口 17 server.listen()#开机,listen(10)后面可以有10人等待,超过10人,直接让超过的人数去掉 18 19 20 print(1111) 21 #等待客户端的连接 22 conn, addr =server.accept() 23 #接收消息 24 from_client_msg=conn.recv(1024)#单位大小为b,1kb=1024b 25 #消息字符转换并打印 26 print(from_client_msg.decode('utf-8')) 27 #消息发给客户端 28 conn.send("勇士说的".encode('utf-8')) 29 30 #消息发完断开连接, 31 conn.close() 32 #服务端关机 33 server.close()
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # @time : 2019/6/13 19:36 4 # @author : aolishuai 5 # @file : 客户端 6 import socket 7 client = socket.socket() 8 #拿到服务端ip和端口 9 server_ip_port = ('192.168.1.9',8001) 10 #连接服务端 11 client.connect(server_ip_port) 12 #发消息 13 client.send("kd断了".encode('utf-8')) 14 15 from_server_msg=client.recv(1024) 16 from_server_msg=from_server_msg.decode("utf-8") 17 print(from_server_msg) 18 19 #客户端关闭 20 client.close()
- udp是没有连接,服务端只能在接收客户端发过来的消息获取到客户端的地址之后,才能返回消息
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # @time : 2019/6/14 15:51 4 # @author : aolishuai 5 # @file : server 6 7 import socket 8 9 sk = socket.socket(type=socket.sock_dgram) 10 sk.bind(('127.0.0.1',8081)) 11 12 msg,addr = sk.recvfrom(1024) 13 print(msg.decode('utf-8')) 14 sk.sendto(b'hihao',addr) 15 16 sk.close()
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # @time : 2019/6/14 15:51 4 # @author : aolishuai 5 # @file : client 6 import socket 7 sk = socket.socket(type=socket.sock_dgram) 8 ip_port=('127.0.0.1',8081) 9 10 sk.sendto(b'hi',ip_port) 11 msg,addr=sk.recvfrom(1024) 12 print(msg.decode('utf-8')) 13 sk.close()
简单的udpsock使用,服务端是一个时间服务器,在客户端需要发送的时候,发送对应格式的时间
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # @time : 2019/6/14 16:18 4 # @author : aolishuai 5 # @file : time_server 6 import socket,time 7 8 sk = socket.socket(type=socket.sock_dgram) 9 ip_port=('127.0.0.1',8082) 10 11 sk.bind(ip_port) 12 13 while true: 14 msg,addr = sk.recvfrom(1024) 15 msg=msg.decode('utf-8') 16 print(msg) 17 t =time.localtime(time.time()) 18 give_t = time.strftime(msg,t) 19 sk.sendto(give_t.encode('utf-8'),addr) 20 21 sk.close()
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # @time : 2019/6/14 16:18 4 # @author : aolishuai 5 # @file : time_client 6 7 import socket 8 9 sk = socket.socket(type=socket.sock_dgram) 10 ip_port=('127.0.0.1',8082) 11 while true: 12 geshi = input('请输入时间格式:').encode('utf-8') 13 sk.sendto(geshi,ip_port) 14 msg,addr = sk.recvfrom(1024) 15 msg= msg.decode('utf-8') 16 print('时间是{0}'.format(msg)) 17 sk.close()
- 黏包问题
黏包问题:
tcp协议在进行socket传输的时候,
1,不知道包有多大,接收的时候可能分多次接收
2,连续传递小数据包,自身优化时间算法,将多个小包一块发送
这两种情况会导致黏包
解决黏包问题
1,传输的时候,先传递包大小,根据大小,确定接收值,返回收到后,再进行传输
2,使用struct模块,传输的时候先将包大小传过去,在直接传输数据包
1,不使用struct模块解决黏包问题,需要在发送你要发的数据之前,先计算数据大小,先告诉服务端要发的数据大小,然后服务端通过接受到数据大小来确定接收数值1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # @time : 2019/6/14 22:40 4 # @author : aolishuai 5 # @file : server 6 import socket 7 8 sk = socket.socket() 9 ip_port = ('127.0.0.1', 8010) 10 sk.bind(ip_port) 11 sk.listen() 12 conn, addr = sk.accept() 13 14 while true: 15 cmd = input('请输入命令:').encode('gbk') 16 conn.send(cmd) 17 ret = conn.recv(1024).decode('utf-8') 18 conn.send(b'ok') 19 ret2 = conn.recv(int(ret)).decode('gbk') 20 print(ret2) 21 22 23 conn.close() 24 sk.close()
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # @time : 2019/6/14 22:40 4 # @author : aolishuai 5 # @file : client 6 import socket,subprocess 7 8 sk = socket.socket() 9 ip_port = ('127.0.0.1',8010) 10 sk.connect(ip_port) 11 12 while true: 13 msg = sk.recv(1024).decode('gbk') 14 ret = subprocess.popen(msg,shell=true,stdout=subprocess.pipe,stderr=subprocess.pipe) 15 std_out = ret.stdout.read() 16 std_err = ret.stderr.read() 17 num = str(len(std_out)+len(std_err)).encode('utf-8') 18 sk.send(num) 19 sk.recv(1024) 20 sk.send(std_out) 21 sk.send(std_err) 22 sk.close()
-
使用struct模块解决黏包问题,struct能把一个类型的数据,转换成相应的bytes类
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # @time : 2019/6/15 10:56 4 # @author : aolishuai 5 # @file : server 6 7 import socket,struct 8 9 sk = socket.socket() 10 ip_port = ('127.0.0.1', 8010) 11 sk.bind(ip_port) 12 sk.listen() 13 conn, addr = sk.accept() 14 15 while true: 16 cmd = input('请输入命令:').encode('gbk') 17 conn.send(cmd) 18 #ret = conn.recv(1024).decode('utf-8') 19 ret = conn.recv(4) 20 ret = struct.unpack('i',ret)[0] 21 22 23 #conn.send(b'ok') 24 ret2 = conn.recv(ret).decode('gbk') 25 print(ret2) 26 27 28 conn.close() 29 sk.close()
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # @time : 2019/6/15 10:56 4 # @author : aolishuai 5 # @file : client 6 import socket,subprocess,struct 7 8 sk = socket.socket() 9 ip_port = ('127.0.0.1',8010) 10 sk.connect(ip_port) 11 12 while true: 13 msg = sk.recv(1024).decode('gbk') 14 ret = subprocess.popen(msg,shell=true,stdout=subprocess.pipe,stderr=subprocess.pipe) 15 std_out = ret.stdout.read() 16 std_err = ret.stderr.read() 17 #num = str(len(std_out)+len(std_err)).encode('utf-8') 18 num = len(std_out)+len(std_err) 19 num = struct.pack('i',num) 20 sk.send(num) 21 #sk.recv(1024) 22 sk.send(std_out) 23 sk.send(std_err) 24 sk.close()
- 黏包问题
2,socketserver
使用tcp时,server端和client端只能链一个,通过socketserver能够使多个client与server同时连接
启用的时候,只有server端需要继承socketserver服务
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # @time : 2019/6/16 13:25 4 # @author : aolishuai 5 # @file : socketserver 6 7 import socketserver 8 #必须创建一个类 9 class myserver(socketserver.baserequesthandler): 10 def handle(self): 11 while true: 12 msg = self.request.recv(1024).decode('utf-8') 13 print(msg) 14 info = input('>>>') 15 self.request.send(info.encode('utf-8')) 16 17 18 #print(self.request.recv(1024))#self.request==conn 19 20 21 if __name__ == '__main__': 22 server = socketserver.threadingtcpserver(('127.0.0.1',8090),myserver) 23 server.serve_forever()
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # @time : 2019/6/16 13:33 4 # @author : aolishuai 5 # @file : client 6 import socket 7 sk = socket.socket() 8 sk.connect('127.0.0.1',8090) 9 while true: 10 msg = input('>>>>>') 11 sk.send(msg.encode('utf-8')) 12 ret = sk.recv(1024).decode('utf-8') 13 print(ret) 14 sk.close()