Search code examples
clinuxsocketstcpfork

Sending from client to client TCP/fork/socket


I'm trying to write a chat, the protocol is TCP, two files are server.c and client.c How to send a message from client to client if they are made via fork and have the same socket descriptor.

No matter how I try to send the message, it comes in the same console window from where it was sent


Solution

  • The problem is that whenever you fork(), the child process that is created is an independent process with its own private memory space and its own separate file-descriptors table. It will inherit the file descriptors of its parent process, but after that, any file descriptors created later in the parent process will not be available in the (already-existing) child process.

    That means that e.g. if your server receives the first TCP connection and creates file descriptor 123 to represent it, and forks a child process to handle it, and then receives a second TCP connection, creates file descriptor 124 to represent it, and forks a second child process to handle that, that the first child process will not be able to use file descriptor 124 at all because that file descriptor was never added to its file-descriptors table.

    If you want to have a child process send data to other child processes, your best bet is for the child process to send the data up to the parent process, and then have the parent process forward that data on to all the other child processes. But note that this is non-trivial to do, as you'd need to either communicate this data over each child process's stdin/stdout file descriptors, or alternatively set up your own connections to each child process using socketpair() or similar.

    If you want to avoid all that complication, you might be better off spawning threads instead of forking child processes, since then all the threads would at least have access to all the file descriptors (since they'd all be executing in the same memory space together). You would then need to deal with locking/synchronization/ownership issues in order to ensure all of those threads access the file descriptors safely, though.

    A third option would be to perform all the server's operations within a single thread, using non-blocking I/O and select() or poll() to multiplex the I/O operations. This is what I usually do by default, since even though it is a bit complex to implement, in my experience it's still the easiest of the three approaches to get 100% right.