4

With Python, is it possible to send UDP data on local host and some port, then simultaneously inside same program, listen to different port on local host? I keep getting error 48'address already in use' and have tried using python's reuse address, although I'm pretty sure it won't work for this application anyways.

Background: I don't know anything about software development much less Python, this is just something that someone asked for at work.

I appreciate any help.

from threading import Thread
import time
import socket


HOST = 'localhost'
PORT = 5455
PORT1 = 5457
data1 = "1"

s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST,PORT1))


a = 0
def myfunction(string, *args):
    while 1:
        cmd = int( raw_input("send message: ") )
        if (cmd == 1):
            s.sendto(data1, (HOST,PORT))
            time.sleep(1)

def myfunction2(string, *args):
    while 1:
        print s.recv(30)
        time.sleep(.5)

if __name__=='__main__':

    try:
        Thread(target=myfunction, args=(a, 1)).start()
        Thread(target=myfunction2, args=(a, 1)).start()
    except Exception, errtxt:
        print errtxt
Lukas Graf
  • 30,317
  • 8
  • 77
  • 92
TDK
  • 255
  • 1
  • 3
  • 9
  • 3
    Have you checked if the port is already used by a different process? Also, please post your socket initialization code! – l4mpi Sep 20 '12 at 18:06

2 Answers2

5

Yes, it is. In any language. You are probably listening twice to the same port; TCP and UDP endpoints are characterized by the IP address and the port. "Address already in use" will only appear for a full match, same address and same port.

Also, verify that the listening port isn't already in use with netstat.

UPDATE (thanks to l4mpi): you will get an "access denied" if you try to use a port below 1024 without having superuser privileges.

UPDATE

I have slightly modified your code; one of the problems you had was some confusion about sending and receiving sockets, which was the "client" function and which was the "server".

I have taken the liberty of querying for a message body instead of "1", but it is easy to put things back if necessary.

from threading import Thread
import time
import socket

CONN = ('localhost', 5455)

def fn_client(string, *args):
    cs = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    cs.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    while 1:
        cmd = int( raw_input("command (1 to send): ") )
        if (cmd == 1):
            data = raw_input("message to send: ")
            cs.sendto(data, CONN)
            time.sleep(1)

def fn_server(string, *args):
    ss = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    ss.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    ss.bind(CONN)
    while 1:
        print "Server received '%s'" % (ss.recv(30))
        time.sleep(.5)

if __name__=='__main__':

    a = 0
    try:
        Thread(target=fn_client, args=(a, 1)).start()
        Thread(target=fn_server, args=(a, 1)).start()
    except Exception, errtxt:
        print errtxt
LSerni
  • 55,617
  • 10
  • 65
  • 107
  • I'm using different ports though. I create a socket and send data to (localhost, "port 1") and simultaneously try to bind to (localhost, "port 2") – TDK Sep 20 '12 at 18:11
  • What does `(localhost, "port 2")` mean? (I'll add some code to the answer) – LSerni Sep 20 '12 at 18:23
  • 2
    You should use example ports above 1024, on linux systems you have to be root to create ports below that. – l4mpi Sep 20 '12 at 18:38
  • You're absolutely right. I had copied 1 and 2 from OP's question without stopping to think. – LSerni Sep 20 '12 at 18:54
  • Thanks I will try using the connect() function and repost after lunch. I tried creating two different sockets before this post but did not use the connect(). – TDK Sep 20 '12 at 19:01
1

Your code works for me insofar that it doesn't produce Address already in use.

But your threading code isn't too clean, KeyboardInterrupt doesn't get handled in threads. This is a common problem with multithreading, see this answer or this recipe for an example on how to mitigate it.

This means you can't gracefully terminate your program by using CTRL-C. Instead you probably had to resort to using something like kill [pid], maybe even with -9? My guess is that you got leftover connections from previous runs of the program that caused Address already in use. Use something like netstat -anp | grep 5457 to determine if there are still connections on that port.

Also see Doug Hellman's article for a good introduction to threading.

Community
  • 1
  • 1
Lukas Graf
  • 30,317
  • 8
  • 77
  • 92