Skip to content Skip to sidebar Skip to footer

Distinguish Between Messages Python3 Tcp Sockets

So I am trying to make an app where a user client would send messages to a server. I want to find a way to distinguish between one message and the next so that I can loop over sock

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"