1. TCP协议下的如何解决粘包问题
TCP(transport control protocol 传输控制协议) 使用Nagle算法,将多次间隔较小且数据量小的数据,合并成大的数据块;接受端无法识别每条数据的边界,因此产生粘包现象。
"""
Server
"""
from socket import *
back_log = 5
bufsize = 1024
ip_port = ('127.0.0.1', 8080)
tcp_server = socket(AF_INET, SOCK_STREAM) # 数据流
tcp_server.bind(ip_port)
tcp_server.listen(back_log)
while True:
print('服务端开始处理连接。。。')
conn, addr = tcp_server.accept()
print('客户端连接', conn)
print('客户端地址', addr)
while True:
try:
data = conn.recv(bufsize)
if not data:
break
print('接收到的数据', data)
conn.send(data.upper())
except Exception as e:
print(e)
break
"""
Client
"""
from socket import *
bufsize = 1024
ip_port = ('127.0.0.1', 8080)
tcp_client = socket(AF_INET, SOCK_STREAM)
tcp_client.connect(ip_port)
tcp_client.send('hello'.encode('utf-8'))
tcp_client.send('world'.encode('utf-8'))
response = tcp_client.recv(bufsize)
print('response is ==> ', response) # response is ==> b'HELLOWORLD'
解决思路:告知接收端数据长度,导入struct模块,将字节长度封装成4个字节发送给接收方;
服务端 =====》TCP实现远程操作命令
from socket import *
import subprocess,struct
bufsize = 1024
back_log = 5
ip_port = ('127.0.0.1', 8080)
tcp_server = socket(AF_INET, SOCK_STREAM)
tcp_server.bind(ip_port)
tcp_server.listen(back_log)
while True:
conn, addr = tcp_server.accept()
print('current connection', conn)
while True:
try:
cmd = conn.recv(bufsize)
if not cmd:
break
print('data from client', cmd)
res = subprocess.Popen(cmd.decode('utf-8'), shell=True,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
cmd\_res = res.stderr.read()
if not cmd\_res:
cmd\_res = res.stdout.read()
print('response is:', cmd\_res)
data\_length = struct.pack('i', len(cmd\_res))
conn.send(data\_length)
conn.send(cmd\_res)
except Exception as e:
print(e)
break
# conn.close()
客户端 ====》
from socket import *
import struct
bufsize = 100
ip_port = ('127.0.0.1', 8080)
tcp_client = socket(AF_INET, SOCK_STREAM)
tcp_client.connect(ip_port)
while True:
cmd = input('>>>> ').strip()
if not cmd:
continue
if cmd == 'quit':
break
tcp_client.send(cmd.encode('utf-8'))
length\_data = tcp\_client.recv(4)
length = struct.unpack('i', length\_data)\[0\]
print(length)
response = b''
recsize = 0
while recsize < length:
response += tcp\_client.recv(bufsize)
recsize = len(response)
# print('execute result is:', response) # 接受字节长度小于发送数据长度,产生粘包
print('execute result is:', response.decode('gbk'))
tcp_client.close()
2. TCP协议如何实现多个客户端连接(并发处理)
导入socketserver模块,实现ocketserver.BaseRequestHandler,重写 handle 方法
使用
ThreadingTCPServer,线程实现并发
import socketserver
class MyServer(socketserver.BaseRequestHandler):
def handle(self): print('conn is', self.request) # conn
print('addr is', self.client_address) # addr
while True:
try:
data = self.request.recv(1024)
if not data:
break
self.request.sendall(data.upper())
except Exception as e:
print(e)
break
if __name__ == '__main__':
ip_port = ('127.0.0.1', 8080)
s = socketserver.ThreadingTCPServer(ip_port, MyServer)
s.serve_forever()
3. 基于UDP套接字
UDP 与TCP 不同,使用socket时用的时 SOCK_DGRAM 数据报
sendto()发送的是元组数据类型,包含数据以及连接
recvfrom()接收的也是数据以及连接
服务端 ====》
from socket import *
ip_port = ('127.0.0.1', 8080)
buf_size = 1024
udp_server = socket(AF_INET, SOCK_DGRAM) # datagram 数据报
udp_server.bind(ip_port)
while True:
data, addr = udp_server.recvfrom(buf_size)
print(data)
udp_server.sendto(data.upper(), addr)
客户端====》
from socket import *
ip_port = ('127.0.0.1', 8080)
buf_size = 1024
udp_client = socket(AF_INET, SOCK_DGRAM) # datagram 数据报
while True:
msg = input('==>: ').strip()
udp_client.sendto(msg.encode('utf-8'), ip_port)
response, addr = udp_client.recvfrom(buf_size)
print(response.decode('utf-8'))
手机扫一扫
移动阅读更方便
你可能感兴趣的文章