1

I have been trying to get a basic chat application working for months in python 2.7 (Using Geany IDE), and finally got a basic application working using UDP. I can connect and broadcast communications, but if a client connects and then closes later, the server crashes the next time it tries to broadcast a message to all of the clients. The issue is that it crashes without returning an error message or a traceback so I can't tell exactly what's happening. Here is the code (it will only work on windows due to the getch() code in the client).

Server:

from socket import *
s = socket(AF_INET,SOCK_DGRAM)
s.bind(("25.150.175.48",65437))
maxsize = 4096
listeners = []
while True:
    data, addr = s.recvfrom(maxsize)
    if addr not in listeners:
        listeners.append(addr)
        #print addr[1]
        print "new client added from %s on port %i" % (addr[0],addr[1])
    for l in listeners:
        try:
            s.sendto(data,l)
        except:
            listeners.remove(l)

Client:

from socket import *
import select
import msvcrt
s = socket(AF_INET,SOCK_DGRAM)
s.bind(("25.150.175.48",65438))#change port to 65439 for the second client
maxsize = 4096
waitseconds = 0.001
server = ("25.150.175.48",65437)
s.sendto(raw_input(">"),server)
while True:
    ready = select.select([s], [], [], waitseconds)
    if ready[0]:
        data = s.recv(maxsize)
        print data
    else:
        if msvcrt.kbhit():
            char = msvcrt.getch()
            if char == "\r":
                s.sendto(raw_input(">"),server)

My theory is that if I can have the server recognize when a person closes the client, I can remove the client address from the list of listeners and it will work fine. Unfortunately, it's not working correctly, and I don't know how to have the server send out a test packet of some sort that I can use to verify connection. All the examples I've read on the internet seem to just verify that the port exists. If anyone has any idea on how to handle this, I would greatly appreciate the help.

EDIT:

After tooling around a bit I finally managed to receive a traceback by running the server program in IDLE. the traceback is as follows:

Traceback (most recent call last):
  File "G:\Python\Miscellaneous\Examples\UDP Chat Server & Client\UDP server.py", line 7, in <module>
    data, addr = s.recvfrom(maxsize)
error: [Errno 10054] An existing connection was forcibly closed by the remote host

I need some help handling this, as my try/except statement seems to fail to catch this when I run it (Which I'm seriously concerned about; python bug?). After returning this traceback the program quits. Any suggestions?

Ben Schwabe
  • 1,283
  • 1
  • 21
  • 36
  • The trace back is showing the exception in the recvfrom() call and not the sendto(). Maybe put a try block there and print the exception. You may be able to then ignore/handle that. – pcm Aug 01 '13 at 01:42
  • it prints out the exception as expected, but I don't know how to handle that issue now. Is there some way for the code to return WHICH client was forcibly closed? or at least an IP? – Ben Schwabe Aug 01 '13 at 02:09
  • Continued at http://stackoverflow.com/questions/17984610/python-error-10054-client-forcibly-closed-get-ip-of-error – Ben Schwabe Aug 01 '13 at 03:08
  • If you add a try block around the recvfrom() call, what exception information do you get in the Exception object? – pcm Aug 01 '13 at 10:23
  • @pcm I get this if I print it out: `error: [Errno 10054] An existing connection was forcibly closed by the remote host`. Can I get the IP of the client at fault from this somehow? – Ben Schwabe Aug 02 '13 at 05:41

1 Answers1

0

You won't get any traceback with your try\except block. Unless you really know what you're doing you shouldn't ignore errors like that.

try:
    s.sendto(data,l)
except Exception as e:
    print(e)
    listeners.remove(l)

As for the crash it's hard to say. UDP is not connection oriented, so the client being running or not shouldn't crash your server, or even stop it from sending the packages.

The only way you can check if a client is online, using UDP exclusively, is by sending a package and removing it from the list if it doesn't respond in a period of time.

Joe Junior
  • 176
  • 5
  • 1
    I added the exception afterwards to try to fix the crash but it kept occurring anyway. – Ben Schwabe Jul 31 '13 at 23:59
  • I updated the question. I managed to get a traceback error by running my initial code in IDLE. Your suggestion doesn't work as the code appears to never make it to the print line. it seems like s.sendto() is manually closing the program and bypassing the except. – Ben Schwabe Aug 01 '13 at 00:11