Nadav
Nadav

Reputation: 1110

Create UDP client socket without socket listening

I'm using the standard way, shown in many examples, to create a UDP socket in C++, keep it alive and keep sending stuff over it.

I only call sendto. I never call recvfrom. In this code fragment I only use sendto once and then sleep for 5 seconds:

C code:

static int do_the_rest( int sock )
{
    struct sockaddr_in server_addr;

    bzero(&server_addr,sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr=inet_addr("192.168.32.32");
    server_addr.sin_port=htons(32000);

    char sendline[100];
    bzero(sendline,sizeof(sendline));

    const struct sockaddr * addr = (const struct sockaddr*)&server_addr;

    sendto(sock,sendline,sizeof(sendline),0,addr,sizeof(server_addr));

    sleep( 5 );

    return 0;
}

int main(int argc, char**argv)
{
    int sock;

    sock=socket(AF_INET,SOCK_DGRAM,0);
    if( sock < 0 ) {
        perror( "socket" );
        return 1;
    }

    int ret = do_the_rest( sock );
    close( sock );

    return ret;
}

Now, if I run "netstat -na", I can identify that the system seems to listen on the local port of the socket (I remove the lines in my program that print the local port, for clarity):

netstat -na:

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State
...
udp        0    304 0.0.0.0:53735               0.0.0.0:*

When I try something similar in Java, I also seem to get some listening, although it looks a bit different (perhaps IPv6?):

Java code:

import java.io.*;
import java.net.*;

class Udp {
    public static void main(String[] args) throws Throwable {
        DatagramSocket sock = new DatagramSocket(null);

        try {
            InetAddress ipAddress = InetAddress.getByName("192.168.32.32");

            byte[] sendData = new byte[50000];

            DatagramPacket sendPacket = new DatagramPacket(
                sendData, sendData.length, ipAddress, 32000);

            sock.send(sendPacket);

            Thread.sleep(5000);

        } finally {

            sock.close();
        }
    }
}

netstat -na:

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State
...
udp        0      0 :::37053                    :::*

I understand this is done in order to support a possible recvfrom (receive in Java) that may follow. However, is there a way to tell the socket not to listen to incoming packets at all?

Thanks

Upvotes: 0

Views: 1173

Answers (3)

user207421
user207421

Reputation: 310913

It is not only 'listening' on that port, it is sending via that port. The port allocation is required. The socket gets bound to a port as soon as you call sendto(), unless it is already bound.

Upvotes: 0

Remy Lebeau
Remy Lebeau

Reputation: 596256

You can use shutdown() with its how parameter set to SHUT_RD to disable reads on the socket, which may have the intended behavior of stopping the listening, maybe even freeing the kernel's receive buffer. But the receive port has to remain allocated for the socket's lifetime, as it is used as the source port for the outgoing packets you are sending with sendto(). You cannot avoid that.

Upvotes: 1

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136256

Now, if I run "netstat -na", I can identify that the system seems to listen on the local port of the socket

UDP sockets have a kernel buffer for incoming messages. This buffer is maintained by the kernel regardless whether you call recv/recvfrom/recvmsg from user-space code.

Upvotes: 1

Related Questions