robins35
robins35

Reputation: 681

Python Socket Library, Errno 10054 When Client Quits

So I'm messing around with a very simple echo server/client kind of deal. I'm eventually going to be making a game server, but for now I'm just trying to setup the basic parts.

Here's the server: http://pastebin.com/qtfrMGur

Here's the client: http://pastebin.com/3VK3VxPX

So, my problem is that when the client disconnects, I get socket.error: [Errno 10054] An existing connection was forcibly closed by the remote host. I was under the impression that select.select() returned false(or an empty list, whatever) when the readable socket list had no pending information. This seems to be the cause of the error, but then why is select.select() returning true(on line 26) if the client is no longer there? The actual error occurs when I try to retrieve some info in line 27. I'm really confused by this, assuming the client-side of the socket is closed, shouldn't it just return [], and then go to the else on line 31 and destroy that client?

I don't really know what else to post, this seems like a very elementary problem, usually I use a more abstract library like twisted that makes it easy, but for this project I must use traditional BSD sockets. If you guys have any other info you need just ask.

Thanks.

EDIT: So I put a print statement in there to print the value of select.select(...)[0], like so:

for cl in clients:
        ready = select.select([cl], [], [], .1)[0]
        print ready
        if ready:
            data = cl.recv(size)
            if data:
                print data
                #cl.send(data)
            else:
                print "Client Quit\n"
                clients.remove(cl)
                cl.shutdown(socket.SHUT_RDWR)
                cl.close()
                print len(clients)

As you can see I do a proper shutdown now as well. The problem is, that right as the client quits, select.select(...) returns the client socket as a readable source, so cl.recv gets called on it, which then throws an error because cl is closed on the other end. At least this is my suspicion.

So, could somebody please explain what I may be doing wrong here? Why does the client send a last dying message, is it some kind of functionality that I should be taking advantage of?

Thanks

EDIT2: So guys I fired up my debian machine and the code works flawlessly, it's only in windows that it's doing this. Is this some sort of bug? I was under the impression that the socket library abstracted all the stuff beneath the hood to make the interface identical between OS.

Upvotes: 1

Views: 3527

Answers (1)

andrean
andrean

Reputation: 6796

You should call the shutdown method of the socket, before closing it on the client side, like this:

s.shutdown(socket.SHUT_RDWR)
s.close()

That way it won't allow further sending / receiving, check out the Python docs about it, it's nicely explained there.

UPDATE: fixed client code

import socket

host = 'localhost'
port = 50000
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))

msg = ''
while msg !='quit':
        msg = raw_input()
        s.send(msg)
        #data = s.recv(size)
s.shutdown(socket.SHUT_RDWR)
s.close()

Upvotes: 1

Related Questions