TDK
TDK

Reputation: 355

Python - 1 program, send and receive on different ports but same host, Is it possible?

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

Upvotes: 4

Views: 6338

Answers (2)

LSerni
LSerni

Reputation: 57408

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

Upvotes: 5

Lukas Graf
Lukas Graf

Reputation: 32610

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.

Upvotes: 1

Related Questions