Search code examples
socketsnetwork-programmingudpclient-serversendto

When will one socket suffice, when do I need to create more?


The "connectionless" aspect of UDP has thrown me for a loop...

If I setup a UDP socket set to INADDR_ANY, then bind that to port 33445 on the local machine, the machine will accept incoming connections from various clients. All of these connections will be serviced by that one socket, since this is not TCP and I cannot spawning a new child sockets to handle each connection directly. I am able to reply to any, some, or all of these connected clients, from their latest message.

So where things get a little fuzzy for me is here...

Am I able to also send out messages at any time to any of these clients? or can I only send messages that in response of recvfrom() ?

Separately, if I wanted that server (while it is serving clients) to connect to another server and have a conversation about something else, I assume I will need to create a new socket for this purpose? I cannot just use the existing server socket and specify a new destination address?

Many thanks to this wonderful community.

Edit: Let me put it another way.. It seems to be that I can only use the bound socket for responding to clients that have previously reached me on that socket. To initiate a conversation with a new host, I cannot simply use the bound socket for that purpose? I must create a new socket in order to reach a server that is listening, correct?


Solution

  • UDP sockets can operate in two different modes:

    • default not-connected mode: all datagrams sent to the port/address of your process are received; you need to specify destination address for each send you do.
    • connected mode: only the datagrams sent from the address/port you connected to are received; you don't need to specify destination address on each send.

    Here's a small review of connected UDP sockets.

    Edit:

    Here's a little python UDP server that accepts packets from any client and copies them to a second server. Everything is done with one not-connected UDP socket.

    #!/usr/bin/env python
    import sys, socket, string
    
    if len( sys.argv ) != 4:
            print "Usage: udptee <local-listen-port> <copy-host> <copy-port>"
            exit( 1 )
    
    copy = ( sys.argv[2], int( sys.argv[3] ))
    
    s = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
    #s.bind(( 'localhost', int( sys.argv[1] )))
    s.bind(( '', int( sys.argv[1] )))
    
    print "listening on ", s.getsockname()
    print "copying to", copy
    
    while True:
            line, addr = s.recvfrom( 1024 )
            print "received: ", line, " from ", addr
            s.sendto( line, addr ) # echo to source
            s.sendto( line, copy ) # copy to tee
            if string.strip( line ) == "exit": break
    
    print "Goodbye and thanks for all the fish"
    s.close()
    

    Run it in one terminal as:

    ~$ ./udptee 9090 <IP-of-copy-server> 9999
    

    Then start netcat in server mode in second term. This one will accept copies of the datagrams:

    # this used to be "nc -ul 127.0.0.1 9999" which only listened on loopback
    ~$ nc -ul 9999
    

    Start netcat client in third term to send stuff to the first server:

    ~$ nc -u <IP-of-tee-server> 9090
    

    Start typing and see both servers echo what you type.