Socket issues in Python

Question:

I’m building a simple server-client app using sockets. Right now, I am trying to get my client to print to console only when it received a specific message (actually, when it doesn’t receive a specific message), but for some reason, every other time I run it, it goes through the other statement in my code and is really inconsistent – sometimes it will work as it should and then it will randomly break for a couple uses.

Here is the code on my client side:

def post_checker(client_socket):
    response = client_socket.recv(1024)

    #check if response is "NP" for a new post from another user
    if response == "NP":
        new_response = client_socket.recv(1024)
        print new_response
    else: #print original message being sent
        print response

where post_checker is called in the main function as simply “post_checker(client_socket)” Basically, sometimes I get “NPray” printed to my console (when the client only expects to receive the username “ray”) and other times it will print correctly.

Here is the server code correlated to this

for sublist in user_list:
    client_socket.send("NP")
    client_socket.send(sublist[1] + " ")

where user_list is a nested list and sublist[1] is the username I wish to print out on the client side.

Whats going on here?

Asked By: bynx

||

Answers:

The nature of your problem is that TCP is a streaming protocol. The bufsize in recv(bufsize) is a maximum size. The recv function will always return data when available, even if not all of the bytes have been received.
See the documentation for details.

This causes problems when you’ve only sent half the bytes, but you’ve already started processing the data. I suggest you take a look at the “recvall” concept from this site or you can also consider using UDP sockets (which would solve this problem but may create a host of others as UDP is not a guaranteed protocol).

You may also want to let the python packages handle some of the underlying framework for you. Consider using a SocketServer as documented here:

Answered By: Brian Cain
buffer = []

def recv(sock):
        global buffer

        message = b""

        while True:
                if not (b"rn" in b"".join(buffer)):
                        chunk = sock.recv(1024)

                        if not chunk:
                                break

                        buffer.append(chunk)

                concat = b"".join(buffer)

                if (b"rn" in concat):
                        message = concat[:concat.index(b"rn")]
                        concat = concat[concat.index(b"rn") + 2:]
                        buffer = [concat]
                        break

        return message

def send(sock, data):
        sock.send(data + b"rn")

I have tested this, and in my opinion, it works perfectly

My use case: I have two scripts that send data quickly, it ends up that one time or another, the buffers receive more than they should, and gather the data, with this script it leaves everything that receives more saved, and continues receiving until there is a new line between the data, and then, it gathers the data, divides in the new line, saves the rest and returns the data perfectly separated

(I translated this, so please excuse me if anything is wrong or misunderstood)

Answered By: Gustavo10Destroyer
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.