网络编程 06.27
1.粘包问题
tcp协议才会有粘包问题,udp协议没有粘包问题
粘包问题的几种情况:
- D1 和D2间隔时间长,两者数据量小,不会发生粘包问题
- D1和D2间隔时间非常短,数据量小,会发生粘包问题
- D2比较大,D1比较小,间隔时间也短,服务端一次性读取D1和D2的一部分,出现了粘包问题
- D1大,D2比较小,获取D1的一部分,然后获取了D1的剩余部分和D2,出现了粘包问题
解决方案:
- 两者间隔时间边长
- 发送之前告诉客户端数据的大小,大小的位置必须得固定。
2.解决粘包问题
#tcp服务端.py
import socket
import struct
import subprocess
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('127.0.0.1',8000))
server.listen(5)
print('start...')
while True:
conn, client_address = server.accept()
print(client_address)
while True:
try:
cmd = conn.recv(1024)
print(cmd)
pipeline = subprocess.Popen(cmd.decode('utf8'),
shell=True,
stderr=subprocess.PIPE, stdout=subprocess.PIPE)
stdout = pipeline.stdout.read()
stderr = pipeline.stderr.read()
count_len = len(stdout)+len(stderr)
guding_bytes = struct.pack('i',count_len)
conn.send(guding_bytes)
conn.send(stderr + stdout)
except ConnectionResetError:
break
conn.close
#tcp客户端.py
import struct
from socket import *
client = socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8000))
while True:
cmd = 'dir'
client.send(cmd.encode('utf8'))
guding_bytes = client.recv(4)
count_len = struct.unpack('i',guding_bytes)[0]
data = client.recv(count_len)
print(data.decode('gbk'))
3.UDP套接字简单示例
#udp服务端.py
import socket
server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
server.bind(('127.0.0.1',8000))
print('start...')
while True:
data, client_addr = server.recvfrom(1024)
print(client_addr)
print(data)
server.sendto(data.upper(),client_addr)
#udp客户端.py
import socket
client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
msg = input('please enter your msg')
client.sendto(msg.encode('utf8'),('127.0.0.1',8000))
data = client.recvfrom(1024)
print(data)
- UDP是无链接的,先启动哪一端都不会报错
- UDP协议是数据报协议,发空的时候也会自带报头,因此客户端输入空,服务端也能收到
- UPD协议一般不用于传输大数据。
- UDP套接字虽然没有粘包问题,但是不能替代TCP套接字,因为UPD协议有一个缺陷:如果数据发送的途中,数据丢失,则数据就丢失了,而TCP协议则不会有这种缺陷,因此一般UPD套接字用户无关紧要的数据发送,例如qq聊天。
4.基于socketservver实现并发的socket套接字编程
#服务端.py
import socketserver
import subprocess
import struct
class MyHandler(socketserver.BaseRequestHandler):
# 通信循环
def handle(self):
while True:
try:
cmd = self.request.recv(1024)
print(cmd)
pipeline = subprocess.Popen(cmd.decode('utf8'),
shell=True,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)
stdout = pipeline.stdout.read()
stderr = pipeline.stderr.read()
count_len = len(stdout) + len(stderr)
guding_bytes = struct.pack('i', count_len)
self.request.send(guding_bytes) # 4
self.request.send(stderr + stdout)
except ConnectionResetError:
break
# 使用socketserver的连接循环(并发),但是使用了自己的通信循环
# myhandler = MyHandler()
if __name__ == '__main__':
s = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyHandler, bind_and_activate=True)
s.serve_forever()
#客户端.py
import socket
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connet(('127.0.0.1',8000))
while True:
msg = input(please enter your msg ).strip()
msg = 'client'
if len(msg) == 0: continue
client.send(msg.encode('utf8'))
data =client.recv(1024)
print(data)
#客户端1.py
import socket
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connet(('127.0.0.1',8000))
while True:
msg = input(please enter your msg ).strip()
msg = 'client'
if len(msg) == 0: continue
client.send(msg.encode('utf8'))
data =client.recv(1024)
print(data)
#客户端2.py
import socket
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connet(('127.0.0.1',8000))
while True:
msg = input(please enter your msg ).strip()
msg = 'client'
if len(msg) == 0: continue
client.send(msg.encode('utf8'))
data =client.recv(1024)
print(data)

浙公网安备 33010602011771号