C/Linux TCP Socket Server - c

I'm implementing a TCP socket server in C and Linux. It will be a chat server handling many requests simultaneously. Here is the pseudo code for how it is setup
create a socket
bind to a well-known port
use listen to place in passive mode
while (1)
{
accept a client connection
fork
if (child)
{
communicate with new socket
close new socket
exit
}
else
{close new socket}
}
From what I've seen, the "communicate with new socket" part consists of reading the buffer and then possibly writing to the buffer, then the socket closes. I thought sockets were suppose to be a persistent connection? If the client has to reconnect every time it wants to send more data to the server, isn't this inefficient and defeating the purpose of sockets?

If the client has to reconnect every time it wants to send more data to the server, isn't this inefficient and defeating the purpose of sockets?
It's impossible to say without knowing more about the nature of your application:
In some cases, it makes sense to maintain a persistent connection for the duration of the client's lifetime.
In other cases, connecting on every message would also work well.
You are quite right on the efficiency front: there is quite a lot of overhead involved in establishing a TCP connection. Therefore, if the messages are frequent it may turn out to be very costly to set up a new connection for each message.

Don't close the socket. Put the code which receives and responds to the messages in a loop and using blocking I/O ( the default ) to block on reading the socket until a request arrives. This way you'll have a forked process dealing with each client and using minimal resources. You only close the socket and exit the child process when the client explicitly closes the connection because it's done.
Use UDP instead of TCP. This way there is no "connection" between the server and the client. You multiplex multiple clients to a single socket without forking. If you care about reliability you'd need to add a sequence number to each message to keep them straight and allow retransmission on failures.
Keep a single process using TCP, but store a socket descriptor set and use select to check for readable sockets. You can then retransmit that data on each or some of the other client sockets.
I'd point out that forking a child for each client in a chat server seems like a poor implementation. How do two people who want to chat communicate? Each one will be served by a separate process - how do the processes communicate with each other so that chat data can pass between clients?

Related

select() issue with a push server - c/c++

I'm writing a server in C ++ for both Windows and Unix systems.
A key feature of this server is that it must be able to receive and send network packets at any time.
Specifically, the server must be able to send data to the client not only in response to their messages, but also be able to send packets to them asynch in push.
I'm having difficulty in implementing a solution that uses the select() function in the scenario described above.
The solution I have currently implemented does not convince me at all and I think it can be implemented with better patterns/solutions.
I currently have a dedicated thread (selector) that performs the select by listening on events in the reading for the server socket (to accept new connections) and for the sockets connected to the server.
This is the main select() loop:
if((sel_res_ = select(nfds_+1, &read_FDs_, NULL, &excep_FDs_, &sel_timeout)) > 0){
if(FD_ISSET(serv_socket, &read_FDs_)){
//we have to handle a newly connection.
...
if(sel_res_ > 1){
//in addition to the newly connection, there is also some other message incoming on client sockets.
...
}
}else{
//we have to handle incoming messages on client sockets
...
}
}
This solution works well for receiving the data and to respond to client requests in synchronous form.
However, the server must also be able to send asynchronous data, and send when necessary, packets in push.
To do this I currently use separate threads that perform directly the send() on the client sockets.
This solution does not convince me, and I would like to centralize the packets receiving and sending on the selector thread.
The main difficulty is that the select() by its nature is blocking and I have no control until a client does not send any packet or the timeout is triggered.
The solution to set a timeout very low does not convince me; I see it as an easy solution that is actually doing active wait, and not only, however, the worst case I would pay the price of the timeout before sending the push packet.
I thought a more 'elegant' solution; I think, will work well, but only for a Unix/Linux platform.
I thought to use an anonymous pipe and insert into the select() read_FDs_ the anonymous pipe read descriptor.
In this way, when a thread wants to send a data in push, it writes something on this pipe, interrupting the select() and returning control to the selector that can then predispose to send the data to the client, without significant loss of time.
I think that this solution, unfortunately, cannot be implemented on Windows because the select() function on that system works only with fds that are actually sockets.
So the question is: Is there some well known solution that can be used to address this kind of scenario (both Linux and Windows)?
You can create a self connected UDP socket, this works equally well on Windows and Linux.
Basically, you create a UDP socket, bind() it to INADDR_LOOPBACK and port 0, and connect() it to itself (with the address taken from getsockname()).
At this point, you can send yourself a single byte message (or something more specific) to wake yourself up.

Will a disconnected udp socket still receive traffic from a port that another socket is connected to?

I'm trying to write a server/client pair to run over udp, and the only way i've been able to get it going is having the server aware of the client's ip and port before the connection starts. My new design involves waiting for a packet to come in, recording the sender address, forking to a child process (the parent loops around and continues listening), which then connect's to the client the transmitted the packet. The child should then only receive packets from the associated client, but the documentation is unclear is the parent socket will continue receive traffic from that client. I'm working on a program to try it, but i figured i could ask the question at the same time.
EDIT: It seems that when the child's socket is connected'd it will connect the parent's socket too.
UDP protocol does not operate connections, it's a connection-less protocol. It is enough for one side to listen and other side to just send datagrams for data channel to work.
On the question (sorry, didn't got the point before): forking is not the way out when working with UDP. Connection-based protocols are widely used with that technique. That is possible because:
you can fork right after listen()
the first process accepts connection works with it (and only that process posesses the newly created connected socket.
When you work with UDP you don't have such gap (as before accept() with TCP) to know when exactly to fork (especially when you have intensive datagram flow).
So, when you design UDP service, you need either
use non-blocking I/O with event loop or
design threaded solution.

creating two sockets at udp server at a time, how to bind()?

I want two functionalities to be implemented on my udp server application.
Creating thread that continuously receives data coming from any client.
Creating a thread that continuously sends data on server socket after specific time period and waits for reply from client. (I implemented this to make aure that whenever any client goes down, the data is not received back from client and server comes to know that client is down.)
Now, the problem I am facing is that since two threads are sharing same connected socket, whenever both threads try to access this socket simultaneously, a deadlock is established.
One of the solution I found was to create two sockets. One that continuously receives data, and the other socket that is meant for sending data from server time to time to clients and wait for their response, but since Server can must be bind()ed and I have bind()ed my socket to INADDR_ANY once, how would I create a separate socket for sending data from server and waiting for replies from client.
Please help me with this complication.
Also do let me know if there is some other better way of its implementation.
Thanks in advance :)
You will have to use non-blocking net functions and use a mutex to ensure no two threads access the socket at once.
A single thread may, however, be enough, if you use non-blocking functions. Using many threads will probably not improve performance, but may make the code more readable.

Two-way communication in socket programming using C

I have a small doubt in socket programming. i am able to send my data from client to server and my server processes the data. The o/p of the data processed, I want to send back to my client. So can we "write" the data back to the client using the same socket. I mean a server listens on a port before accepting connection and receiving data, so similarly, do i need to make my client listen to some other port (bind it some other socket) and make my server connect to that socket and transfer the data back. Any kind of example or explanation or references would be appreciated. Thanks a lot in advance.
Check out Beej's Network Programming Guide first of all.
The basic screenplay of a server/client connection goes like this:
Server listen()s on a fixed port, with a given socket.
Client connect()s to a the server port; client obtains a socket.
Server accept()s the connection, and accept() returns a new socket for the connection.
(Server continues listening on the original port with the original socket.)
For the specific connection with the client, the server write()s to the new socket it obtained when accept()ing the incoming connection. A busy server will have many, many sockets, but it will only ever need to bind() to one port. All connections come in to that one port, but the OS's networking protocol stack separates the data and makes it available at the connection-specific socket.
You don't need a new socket.
A socket is a duplex connection you can send data in both directions and you can even close the socket from one direction (don't want to write anymore) but still send data from the other direction.
Your socket is bi-directional, so there is no need to create another socket. Unless you are using some sort of middleware, such as Pub/Sub, there is no need to create another socket to enable bi-directional communication.
Technically it is right, the socket is duplex and you can send the data to the same socket you read from:
SOCKET s = socket()
... //Connect
int size = receive(s,...);
//make response
send(s, ...);
But in practice it depends on what are you going to do. It is possible to hang out socket if you have the following situation:
Process 1 sends very big data (<100K) over the socket by one send
operation
Process 2 receives data from 1 by portions and sends small packets to 1 (~20b). It is not a
confirmations, but some external events.
The situation goes into hangout, where the sending buffer of the 2 is full and it stops sending confirmations to 1.
2 and 1 are hanging in their send operations making a deadlock.
In this case I'd recommend using two sockets. One for read, one for write.
(Late answer, so mainly for anyone else who comes here looking for help)
I recently put up an example client/server application that closely follows Beej's Guide to Network Programming (which was also recommended by Kerrek SB in his answer). If you're looking for a simple working example of client/server communication, maybe this will help:
https://github.com/countvajhula/dummyclientserver
In particular, no, your client does not need to set up a separate listening socket to receive data from the server -- after the server has accepted the connection from the client, the server can simply send data back to the client on the same socket.

Passing control information between client-server in socket programming in C

I am coding for a server-client programming in C using socket API where I am trying to send control information to client for using different TCP connection.
Whenever the server has created new socket(TCP), I want it to notify the client to use the new socket for further communication.Currently I have thought of sending UDP packet to the client to be notified. Once the client receives the packet, it sends back the ACK to the server and at the same time switches to the another TCP connection.
I want to know, is there a better to communicate the control data across the network besides using UDP as it is unreliable.Thnx
I would like elaborate on what I am trying to achieve. I am going to measure the parameters like bandwidth,latency, receive window etc. as metric for a Ipv4 and IPv6 TCP connection. Based on the observed performance I will be switching between the two protocols whoever provides better performance.Once the decision is made to switch , I have to notify the partner(may be client or server based on type of bandwidth I am measuring upload, download). I start with IPv4 connection and at the same time open another connection - IPv6 for measuring the bandwidth and latency.
If the IPv6 connection provides better performance, I need to tell the client to switch to IPv6. In this case both the connections are open for monitoring the bandwidth periodically to decide on switching. So I have two queries on this aspect. 1.Is it a good idea to keep two connections at a time.I can create the other connection only when I need to measure the metric as the path followed between two machines will hardly change.If yes, I can pass the control information using the other TCP connection to tell the client to switch. In this way I can also measure the bandwidth and notify client
It it is not a good idea two have two TCP connections, I can use UDP to send the control information. I am avoiding to send control information on the conn used to transfer actual data as it will be an overhead. My code will work like a middleware for transfer the data, where the application will call my functions/macros to transfer the data, and the internal code will take care of measuring the bandwidth and decision to switch.I hope I am clear on what I want achieve. Thank for your feedback in advance
The normal sequence of operations for a server-side listening TCP socket is:
int fd1 = socket(...); // Create socket - assuming TCP, not UDP
bind(fd1, ...); // Bind it to a local address
listen(fd1, ...); // Set it in listen mode
int fd2;
while ((fd2 = accept(fd1, ...)) != -1) // Accept an incoming connection
{
...communicate with client via fd2...
close(fd2); // When finished
}
close(fd1);
Now, at the point when you get fd2, that has a socket with a different local ephemeral port from the port that fd1 is connected to (correction per EJP). There is no need to communicate any specific information back to the client; the TCP/IP implementation deals with that for you. The client will have a socket that is connected to fd2, with a port (probably an ephemeral port) on its machine connected to the server and the server's ephemeral port.
The point is that the completed connection will have a unique 4-tuple of (client IP address, client port, server IP address, server port).
When it comes to the processing, there are various ways of dealing with it. You can use an iterative server which deals with one request before dealing with any others. Or you can create a concurrent server in either of two different ways. One way is with a threaded server where a thread (from a pool, or newly created for each incoming connection) deals with the new request while the main thread goes back to accept new incoming requests. The alternative is that you create a forking server where the main server process forks and the child process deals with the new connection while the parent process closes the connection and goes back to listening for the next connection request.

Resources