Поскольку TCP является протоколом потоковой передачи байтов без границ сообщений, одним из решений является обертывание сокета на уровне протокола, который только отправляет и получает полные сообщения.Далее определяется сообщение как «байты в кодировке UTF-8, заканчивающиеся символом новой строки (\ n)»:
from socket import *
class Socket:
def __init__(self,s=None):
'''default create a new socket, or wrap an existing one.
'''
self.sock = socket() if s is None else s
self.buffer = b''
def connect(self,addr):
self.sock.connect(addr)
def bind(self,addr):
self.sock.bind(addr)
def listen(self,n):
self.sock.listen(n)
def accept(self):
c,a = self.sock.accept()
# Wrap the client socket in a Socket.
return Socket(c),a
def get_msg(self):
# Buffer data until a newline is found.
while b'\n' not in self.buffer:
data = self.sock.recv(1024)
if not data:
return b''
self.buffer += data
# split off the message bytes from the buffer.
msg,_,self.buffer = self.buffer.partition(b'\n')
return msg.decode()
def put_msg(self,msg):
self.sock.sendall(msg.encode() + b'\n')
def close(self):
self.sock.close()
Используйте его следующим образом:
import threading
import time
From mysocket import Socket
def server():
s = Socket()
s.bind(('',8000))
s.listen(5)
while True:
c,a = s.accept()
print(f'server: {a[0]}:{a[1]} connected')
while True:
msg = c.get_msg()
if not msg:
break
print(f'server: {msg}')
c.put_msg(f'[{msg}]')
print(f'server: {a[0]}:{a[1]} disconnected')
c.close()
def client():
s = Socket()
s.connect(('localhost',8000))
s.put_msg('Hello')
s.put_msg('马克')
print(f'client: {s.get_msg()}')
print(f'client: {s.get_msg()}')
s.close()
t = threading.Thread(target=server,daemon=True)
t.start()
client()
Вывод:
server: 127.0.0.1:1354 connected
server: Hello
server: 马克
client: [Hello]
client: [马克]
server: 127.0.0.1:1354 disconnected