Distinguish Between Messages Python3 Tcp Sockets
Solution 1:
Reading from a stream one character at a time is going to be pretty slow. Something you might try is sending one message at a time and then fully reading the stream on the receiving end before sending another message.
Here is some example code you can reference:
defread_all_from_connection(self):
def_read_entire_stream_chunked():
whileTrue:
incremental_bytes = self.sock.recv(1024)
iflen(incremental_bytes) == 0:
returnyield incremental_bytes
full_message = b""for partial_msg_bytes in _read_entire_stream_chunked():
full_message += partial_msg_bytes
self.sock.close()
return full_message.decode("utf-8")
EDIT: I did not state this explicitly, but this strategy would be to read a single message per each connection. The performance hit should be negligible, and it may be easier to avoid half-open/hanging connections. If there are performance reasons for wanting to re-use a socket between messages check out: https://websockets.readthedocs.io/en/stable/intro.html instead.
Solution 2:
Since TCP is a byte streaming protocol with no message boundaries, one solution is to wrap the socket in a protocol layer that only sends and receives complete messages. The following defines a message as "UTF-8 encoded bytes ending in a newline(\n) character":
from socket import *
classSocket:
def__init__(self,s=None):
'''default create a new socket, or wrap an existing one.
'''
self.sock = socket() if s isNoneelse s
self.buffer = b''defconnect(self,addr):
self.sock.connect(addr)
defbind(self,addr):
self.sock.bind(addr)
deflisten(self,n):
self.sock.listen(n)
defaccept(self):
c,a = self.sock.accept()
# Wrap the client socket in a Socket.return Socket(c),a
defget_msg(self):
# Buffer data until a newline is found.whileb'\n'notin self.buffer:
data = self.sock.recv(1024)
ifnot data:
returnb''
self.buffer += data
# split off the message bytes from the buffer.
msg,_,self.buffer = self.buffer.partition(b'\n')
return msg.decode()
defput_msg(self,msg):
self.sock.sendall(msg.encode() + b'\n')
defclose(self):
self.sock.close()
Use it like this:
import threading
import time
From mysocket import Socket
defserver():
s = Socket()
s.bind(('',8000))
s.listen(5)
whileTrue:
c,a = s.accept()
print(f'server: {a[0]}:{a[1]} connected')
whileTrue:
msg = c.get_msg()
ifnot msg:
breakprint(f'server: {msg}')
c.put_msg(f'[{msg}]')
print(f'server: {a[0]}:{a[1]} disconnected')
c.close()
defclient():
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()
Output:
server: 127.0.0.1:1354 connectedserver: Helloserver: 马克client: [Hello]client: [马克]server: 127.0.0.1:1354 disconnected
Post a Comment for "Distinguish Between Messages Python3 Tcp Sockets"