Rata Tara
Rata Tara

Reputation: 27

Sockets: TCP and UDP connections (C language)

I have a process that has to establish a server that accepts TCP connections and create some child processes to do the work. I create a TCP socket (no listen, bind or accept) and THEN fork. I have the following questions:

  1. If I bind that socket to a port and listen to that port, will also the socket, that was forked before those 2 calls, listen and be binded to that same port?

  2. If I use accept on the socket and the socket accepts a connection and links to the client socket: Will also the sockets that were forked be connected to that client socket?

I know that the fd table is shared between father and children but I dont know if any changes that happen to the socket in the father process will also happen to the children.

  1. Can I use a socket opened for TCP connections as a TCP reciever and UDP sender?

  2. Can I use a socket opened for TCP connections as a UDP reciever and TCP sender?

  3. If I have a socket that was opened for TCP connections: Can I use sendto with the last 2 arguments NULL without any problems? I found in the online manual that for connection based sockets the last 2 arguments can be skipped but I dont know if I understand it correctly. If this is possible I want the children to be able to send datagram replies to the client waiting with recvfrom without knowing his address.

  4. Can I use on the client socket that was TCP connected the recvfrom with the last 2 arguments NULL?

Upvotes: 1

Views: 1318

Answers (1)

ikegami
ikegami

Reputation: 385635

1. If I bind that socket to a port and listen to that port, will also the socket, that was forked before those 2 calls, listen and be binded to that same port?

Once you have a file descriptor (as created by socket or accept), changes to that file descriptor are reflected in clones of that descriptor in all processes.

Since you can't bind a socket twice, the following can be used to verify my claim. (It's written in Perl, but a C programmer should be able to read it without problem. die throws an exception, $! is strerror(errno), and $!{EINVAL} is equivalent to errno == EINVAL.)

#!/usr/bin/perl

use 5.014;
use warnings;

use Socket qw( pack_sockaddr_in AF_INET SOCK_STREAM INADDR_ANY SOMAXCONN );

socket(my $socket, AF_INET, SOCK_STREAM, 0)
   or die("socket: $!\n");

defined( my $pid = fork() )
   or die("fork: $!\n");

if (!$pid) {
   bind($socket, pack_sockaddr_in(0, INADDR_ANY))
      or die("bind: $!\n");
   listen($socket, SOMAXCONN)
      or die("listen: $!\n");
   exit;
}

waitpid($pid, 0) > 0
   or die("waitpid: $!\n");

if (bind($socket, pack_sockaddr_in(0, INADDR_ANY))) {
   say "Socket bound again. bind doesn't transcend processes.";
} else {
   if ($!{EINVAL}) {
      say "Socket already bound. bind transcends processes.";
   } else {
      die("bind in parent: $!\n");
   }
}

Output:

Socket already bound. bind transcends processes.

2. If I use accept on the socket and the socket accepts a connection and links to the client socket: Will also the sockets that were forked be connected to that client socket?

No. This question presupposes the existence of a link/connection between a socket created by accept and the socket on which accept was called, but there isn't any such link/connection (in any of the processes).


3. Can I use a socket opened for TCP connections as a TCP reciever and UDP sender?

4. Can I use a socket opened for TCP connections as a UDP reciever and TCP sender?

No. A socket is either a TCP socket or a UDP socket. You can't send/receive UDP packets over a TCP socket, and you can't send/receive TCP packets over a UDP socket. There's no way to even try.

However, TCP and UDP ports are independent, so you could be using TCP port 1234 and UDP port 1234 at the same time (using two different sockets).


5. If I have a socket that was opened for TCP connections: Can I use sendto with the last 2 arguments NULL without any problems?

Yes. send can be called on TCP sockets, and send is defined in terms of sendto with NULL and 0 for the the last two arguments.

According to man 2 send on my (GNU/Linux) system:

send(sockfd, buf, len, flags); is equivalent to sendto(sockfd, buf, len, flags, NULL, 0);

In fact, you must set the last two arguments to NULL and 0 with a TCP socket.

According to man 2 sendto on my (GNU/Linux) system:

If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET) socket, the arguments dest_addr and addrlen are ignored (and the error EISCONN may be returned when they are not NULL and 0)


6. Can I use on the client socket that was TCP connected the recvfrom with the last 2 arguments NULL?

Yes. recv can be called on TCP sockets, and recv is defined in terms of recvfrom with NULL for the last two arguments.

According to man 2 recv on my (GNU/Linux) system:

recv(sockfd, buf, len, flags); is equivalent to recvfrom(sockfd, buf, len, flags, NULL, NULL);

Upvotes: 3

Related Questions