0

so I basically have just a Client & Server application going on here and the server sends out data in a loop that looks like this {"Message": "Status Check From Server"} For some reason after the server sends this out around 3 times, the Client then stops receiving data for about 10 seconds then prints out what looks like multiple merged messages of the same data, it looks something like this {"Message": "Status Check From Server"}{"Message": "Status Check From Server"}{"Message": "Status Check From Server"}{"Message": "Status Check From Server"}{"Message": "Status Check From Server"}{"Message": "Status Check From Server"}{"Message": "Status Check From Serv I literally have no clue what this is, I've tried so hard to debug this and just can't figure it out, I don't know if it's my code or if this is simply how TCP works. I'll put some of the code down below.

SERVER SIDE | HAD TO CHANGE SOME OF THE CODE IN HERE TO MAKE SENSE

# Binding Of The Socket
SOCK = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
SOCK.bind(('0.0.0.0', 777))
SOCK.listen()


# This Is The Function I Have Written Up That Sends That Status Check Message To The Clients
def DeviceChecker():
    global DEVICE_LIST

    while True:
        for DEVICE in DEVICE_LIST:
            try:
                DEVICE.send(json.dumps({'Message': 'Status Check From Server'}).encode())
                
                DATA = DEVICE.recv(4096, socket.MSG_PEEK)
                if len(DATA) == 0:
                    raise BrokenPipeError
            except BrokenPipeError:
                DEVICE_LIST.remove(DEVICE)

CLIENT SIDE

# This Is Where The Client Connects To The Server
SOCK = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
SOCK.connect(('0.0.0.0', 777))

# This Is Where The Client Is Receiving The Data
def DataListener(SOCK):
    while True:
        try:
            DATA = SOCK.recv(4096).strip()
            print(DATA)
        except BrokenPipeError:
            return 
  • 3
    Sockets have buffers, and you should handle them as streams of data. You should expect several messages to be collated and received together, or messages to be received partially (split over multiple receives). That is why protocol design is hard, so the receiver knows when a message is complete (or a new message starts). – Mark Rotteveel Mar 20 '22 at 13:51
  • Does this answer your question? [Decoding tcp packets using python](https://stackoverflow.com/questions/2184181/decoding-tcp-packets-using-python) – Mark Rotteveel Mar 20 '22 at 13:54
  • You are thinking of `'{"Message": "Status Check From Server"}'` as a complete "unit" that is sent and received atomically as a single message. But it isn't: it's just a stream of bytes that have to be reassembled by the receiver before you can decode the resulting JSON object into a `dict`. – chepner Mar 20 '22 at 14:04
  • Yes, this is how TCP works. – user253751 Mar 21 '22 at 10:10

1 Answers1

1

Because of the way TCP sockets work, individual write() calls do not result in individual "messages". TCP is designed to break large data streams into packets for transmission over the internet, and rejoin them on the receiving end. The stream of data from one socket to another, in TCP streams at least, is continuous, and individual write()'s are lumped into the same buffer. This is the same issue as in this answered question which describes creating a file-like object using socket.makefile(), then using write() and then flush() on that object to ensure all the data is sent. If you need to make sure your messages are received one at a time, you can have your client send an acknowlegement after each message it receives, and have your server wait for that acknowlegement before sending the next message. As a side note, the socket.send() method is not guaranteed send all the data you give it, and will return, as an int, the number of bytes it actually sent. If you need to make sure all the data is sent in one function call, use socket.sendall(). That will call send() as many times as it needs to.

Josu
  • 46
  • 3