Howto combine TCP and UDP in a single Server? - c

I am totally new to socket programming and I want to program a combined TCP/UDP-Server socket in C but I don't know how to combine those two.
So at the moment, I do know how TCP- and UDP-Server/-Clients work and I have already coded the Clients for TCP and UDP. I also know that I have to use the select()-function somehow, but I don't know how to do it.
I have to read two numbers, which are sent to the TCP-/UDP-Server with either TCP- or UDP-Clients and then do some calculations with these numbers and then print the result on the server.
Does anyone know a tutorial for that or an example code or can help me with that?
Or at least a good explanation of the select() function.

Basically, use an event loop. It works like this:
Is there anything I need to do now? If so, do it.
Compute how long until I next need to do something.
Call select specifying all sockets I'm willing to read from in the read set and all sockets I'm trying to write to in the write set.
If we discovered any sockets that are ready for reading, read from them.
If we discovered any sockets that are ready from writing, try to write to them. If we wrote everything we need to write, remove them from the write set.
Go to step 1.
Generally, to write to a socket, you follow this logic:
Am I already trying to write to this socket? If so, just add this to the queue and we're done.
Try to write the data to the socket. If we sent it all, we're done.
Save the leftover in the queue and add this socket to our write set.
Three things to keep in mind:
You must set all sockets non-blocking.
Make sure to copy your file descriptor sets before you pass them to select because select modifies them.
For TCP connections, you will probably need your own write queue.

The idea is to mix inside your server a TCP part and a UDP part.
Then you multiplex the inputs. You could use the old select(2) multiplexing call, but it has limitations (google for C10K problem). Using the poll(2)
multiplexing call is preferable.
You may want to use some event loop libraries, like libev (which uses select or poll or some fancier mechanisms like epoll). BTW, graphical toolkits (e.g. GTK or Qt) also provide their own even loop machinery.
Read some good Linux programming book like the Advanced Linux Programming
book (available online) which has good chapters about multiplexing syscalls and event loops. These are too complex to be explained well in a few minutes in such an answer. Books explain them better.

1) Simple write a tcp/udp server code, and when receive the message, just print it out.
2) substitute print code to process_message() function.
Then you have successfully combine TCP and UDP server to the same procedure.
Be careful with your handling procedure, it's should be cope with parellel execution.

You may try this stream_route_handler, it is c/c++ application, you can add tcp/udp handler in your single c/c++ application. This has been using by transportation heavy traffic route, and logging service purpose.
Example of using
void read_data(srh_request_t *req);
void read_data(srh_request_t *req) {
char *a = "CAUSE ERROR FREE INVALID";
if (strncmp( (char*)req->in_buff->start, "ERROR", 5) == 0) {
free(a);
}
// printf("%d, %.*s\n", i++, (int) (req->in_buff->end - req->in_buff->start), req->in_buff->start);
srh_write_output_buffer_l(req, req->in_buff->start, (req->in_buff->end - req->in_buff->start));
// printf("%d, %.*s\n", i++, (int) (req->out_buff->end - req->out_buff->start), req->out_buff->start);
}
int main(void) {
srh_instance_t * instance = srh_create_routing_instance(24, NULL, NULL);
srh_add_udp_fd(instance, 12345, read_data, 1024);
srh_add_tcp_fd(instance, 3232, read_data, 64);
srh_start(instance);
return 0;
}
If you are using C++ program, you may like this sample code.
stream route with spdlog

Related

Read, write and exception fd_set handling with select() in C

If I am using select() to monitor three file descriptor sets:
if (select(fdmax+1, &read_fds, &write_fds, &except_fds, NULL) == -1) {
perror("select()");
exit(1);
} else {
...
}
Can a particular file descriptor be ready for reading AND writing AND exception handling simultaneously?
Beej's popular networking page shows a select() example in which he tests the members of the read fd_set using a for loop. Since the loop increments by one each iteration, it will necessarily test some integers that don't happen to be existing file descriptors:
for(i = 0; i <= fdmax; i++) {
if (FD_ISSET(i, &read_fds)) { // we got one!!
{
...
}
}
I believe he's doing this for the sake of keeping the example code simple. Might/should one only test existing file descriptors?
Expanding a little bit with examples and #user207421 comment:
1 Can a particular file descriptor be ready for reading AND writing AND exception handling simultaneously?
Good example will be a socket, which will (almost) always be ready for writing, and will be ready for reading when data is available. It is not common to have exceptions - they are used for exceptional situations. For example, availability of out-of-band message on TCP connections, but most applications do not use those features.
Note that 'normal' errors will be indicated in readfds (for example, socket shutdown).
See also: *nix select and exceptfds/errorfds semantics,
Beej's popular networking page shows a select() example in which he tests the members of the read fd_set using a for loop. Since the loop increments by one each iteration, it will necessarily test some integers that don't happen to be existing file descriptors:
I believe that in this case, it is done simplify the code examples, and is a reasonable implementation for most light weight implementations. It works well if the number of non-listen connections is very small.
Worth mentioning that the 'fd_set' is implemented on Linux with a set of bits, but on Windows (winsock) as an array of fd values. A full scan on all FDs will be O(n) on Linux, and O(n*n) on Windows. This can make a big performance hit on large N for Windows app.
In large scale applications, where a server will listen to hundreds (or more) open connections, each require different actions, potentially with multiple states, the common practice will be to have the list of of active connections, and use a callback to invoke the function. This is usually implemented with an 'eventloop'. Examples include X11, rpc servers, etc.
See Also: https://en.wikipedia.org/wiki/Event_loop
Your question: why you would use select() when you only have one socket.
when select is used and you do not want it to block other processing.
Then make use of the timeout parameter.
That way, even with only one file descriptor open, The program will not block forever due to that one file descriptor not receiving any data as it would block if using read() or similar function.
I.E. this is a very good method when, for instance, listening to a serial port, which only has data when some external event occurs.

Why does POSIX not define a mid-layer socket API?

I am looking at socket programming again. I get the details (well, I can copy them from various websites, and I know the code is enabling the Unix low-level procedures), but I don't get the POSIX logic and thinking in its API.
Why have they not defined a slightly higher-level interface built on these lower-level socket functions?
Presumably, such code could factor out code that is repeated often (and error-prone) into more convenient FILE like interfaces. Factoring would seem even more appropriate than just convenient when the lower level use is the same in > 90% of its use. Almost all sockets use that I see in application programs open a socket, read and write to it and close the socket. Also, why does one need to bind, when this is really something that the open call always does?
What cases does the current interface even cover that could not easily be covered by an interface that would look almost like the FILE interface?
One explanation is that there are uses where one would not bind to a socket, for example, or where fgets/fputs/fprintf/fscanf like functionality would need something extra (time-outs)?
There must be a reason that I am missing. Otherwise, 20 years later, there would already be one or more standard libraries that facilitate this and that would be in wide use. I couldn't find one on google that mimics all the FILE routines.
The point is strikingly simple:
Because sockets are not files.
Let me elaborate: recv/send works quite like read/write, if you limit yourself to linearly reading a file from the beginning, and to appending at its end.
However, you'll say, send doesn't let me write arbitrary lengths of data trough! If I try to send more data than fits into a protocol's packet buffer, it will throw an error!
And that's actually the beauty of sockets: you actually send the data away. you can't keep it; it's gone once it's sent, and it's not stored once it's received. Sockets give you a whole different set of abilities (like sending smaller packets than the maximum packet size of the network, for example), which on the other hand demand you take some control yourself.
EDIT: send will not "throw" an error. "throwing" is not a C/Posix way of handling errors. Instead it will return an error (from man 2 send):
If the message is too long to pass atomically through the underlying protocol, the error EMSGSIZE is returned, and the message is not transmitted.
The C programming language is and will likely always be a lightweight one. You need to understand that C runs basically anywhere and some things need a long research and work to get standardized.
Also, I have seen that new libraries are added because C++ went ahead and made them standard so it's a kind of C sharing.
Please do note that you can "bind" a socket to a file through fdopen(3) and consider it as a binary file. Of course you will still need to bind it, make it listen, accept and all the actions you can do on a socket that won't work for a file.
Indeed, despite the similar interface, a socket acts only partially as a UNIX file: there's even an errno value, ENOTSOCK which indicates a socket specific operation on a non-socket file descriptor.
Furthermore, consider buffering. You do want a file write to be done in large chunks, thus a bigger buffering, to make it faster; this won't work for a socket as you need to send data immediately, that is, undelayed.
Consider this example:
char one = '1', two = '2', three = '3';
fwrite(&one, 1, 1, socket_file);
fprintf(socket_file, "%c\n", two);
send(fd, &three, 1, 0);
where fd is a connected socket(AF_INET, SOCK_STREAM, 0) and socket_file = fdopen(fd, "w+"). The receiver will read 312 because there's no flush except upon process termination at the FILE layer, unlike with send where three is sent immediately.

best way to deal with multithreading TCP Server with C on linux

i've read here about this topic in a lot of differents ways, and i want to know whats the best practices of "creating a Linux TCP server with C and Multithreading".
so far i've read :
1-Duplicating process, with Fork().
2-Creating separated threads for each client. multithread server/client implementation in C
3-Creating Asynchronous threads for each connection
i've read that Fork and thread for each connection are not best practices, but, im not sure what really is one?
i have a small server with asynchronous threads for each connection and i have problems with bind() in the time, if i kill the process and start it again, it need like 5 minutes to start again, because i get " ERROR on binding: Address already in use " and i decided to fix it, but with the best practices.
many thanks in advance and sorry for my english .
Regarding your problem binding..
Set the option SO_REUSEADDR to enable binding to a port already in use (under certain circumstances). Set it before bind.
now it will work fine
...
servSock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
int optval = 1;
setsockopt(servSock,SOL_SOCKET,SO_REUSEADDR,(void *)&optval,sizeof(optval));
/* Construct local address structure */
memset(&echoServAddr,0,sizeof(echoServAddr)); /* Zero out the structure */
echoServAddr.sin_family=AF_INET; /* Internet address family*/
echoServAddr.sin_addr.s_addr=htonl(INADDR_ANY); /* Any incoming interface */
echoServAddr.sin_port = htons(echoServPort); /* Local port */
/* Bind to the local address */
bind(servSock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr));
...
Is obsolete since the introduction of threads.
This is the most widely used technique.
You've misread this. You can use asynchronous I/O, but it's a complex programming model and not to be entered into lightly.
You left out non-blocking I/O with select(), poll(), epoll().
If you know what you're doing and you expect very high load you should investigate 3 or 4. Otherwise you should start with 2, as it's the easiest to program and get working, and see by observing it in production whether you have a capacity problem. Odds are than you will never need to progress beyond this model.
I would suggest you to read the doc & code of libev, that is state-of-the-art.

Non-Blocking Sockets required for a proxy?

i have the following code:
{
send(dstSocket, rcvBuffer, recvMsgSize, 0);
sndMsgSize = recv(dstSocket, sndBuffer, RCVBUFSIZE, 0);
send(rcvSocket, sndBuffer, sndMsgSize, 0);
recvMsgSize = recv(rcvSocket, rcvBuffer, RCVBUFSIZE, 0);
}
which eventually should become part of a generic TCP-Proxy. Now as it stands, it doesn't work quite correctly, since the recv() waits for input so the data only gets transmitted in chunks, depending where it currently is.
What i read up on it is that i need something like "non-blocking sockets" and a mechanism to monitor them. This mechanism as i found out is either select, poll or epoll in Linux. Could anyone give me a confirmation that i am on the right track here? Or could this excercise also be done with blocking sockets?
Regards
You are on the right track.
"select" and "poll" are system calls where you can pass in one or more sockets and block (for a specific amount of time) until data has been received (or ready for sending) on one of those sockets.
"non-blocking sockets" is a setting you can apply to a socket (or a recv call flag) such that if you try to call recv, but no data is available, the call will return immediately. Similar semantics exist for "send". You can use non-blocking sockets with or without the select/poll method described above. It's usually not a bad idea to use non-blocking operations just in case you get signaled for data that isn't there.
"epoll" is a highly scalable version of select and poll. A "select" set is actually limited to something like 64-256 sockets for monitoring at a time and it takes a perf hit as the number of monitored sockets goes up. "epoll" can scale up to thousands of simultaneous network connections.
Yes you are in the right track. Use non-blocking socket passing their relative file descriptors to select (see FD_SET()).
This way select will monitor for events (read/write) on them.
When select returns you can check on which fd has occurred an event (look at FD_ISSET()) and handle it.
You can also set a timeout on select, and it will return after that period even if not events have been occurred.
Yes you'll have to use one of those mechanisms. poll is portable and IMO the most easy one to use. You don't have to turn off blocking in this case, provided you use a small enough value for RCVBUFSIZE (around 2k-10k should be appropriate). Non-blocking sockets are a bit more complicated to handle, since if you get EAGAIN on send, you can't just loop to try again (well you can, but you shouldn't since it uses CPU unnecessarily).
But I would recommend to use a wrapper such as libevent. In this case a struct bufferevent would work particularly well. It will make a callback when new data is available, and you just queue it up for sending on the other socket.
Tried to find an bufferevent example but seems to be a bit short on them. The documentation is here anyway: http://monkey.org/~provos/libevent/doxygen-2.0.1/index.html

Reading from the serial port in a multi-threaded program on Linux

I'm writing a program in linux to interface, through serial, with a piece of hardware. The device sends packets of approximately 30-40 bytes at about 10Hz. This software module will interface with others and communicate via IPC so it must perform a specific IPC sleep to allow it to receive messages that it's subscribed to when it isn't doing anything useful.
Currently my code looks something like:
while(1){
IPC_sleep(some_time);
read_serial();
process_serial_data();
}
The problem with this is that sometimes the read will be performed while only a fraction of the next packet is available at the serial port, which means that it isn't all read until next time around the loop. For the specific application it is preferable that the data is read as soon as it's available, and that the program doesn't block while reading.
What's the best solution to this problem?
The best solution is not to sleep ! What I mean is a good solution is probably to mix
the IPC event and the serial event. select is a good tool to do this. Then you have to find and IPC mechanism that is select compatible.
socket based IPC is select() able
pipe based IPC is select() able
posix message queue are also selectable
And then your loop looks like this
while(1) {
select(serial_fd | ipc_fd); //of course this is pseudo code
if(FD_ISSET(fd_set, serial_fd)) {
parse_serial(serial_fd, serial_context);
if(complete_serial_message)
process_serial_data(serial_context)
}
if(FD_ISSET(ipc_fd)) {
do_ipc();
}
}
read_serial is replaced with parse_serial, because if you spend all your time waiting for complete serial packet, then all the benefit of the select is lost. But from your question, it seems you are already doing that, since you mention getting serial data in two different loop.
With the proposed architecture you have good reactivity on both the IPC and the serial side. You read serial data as soon as they are available, but without stopping to process IPC.
Of course it assumes you can change the IPC mechanism. If you can't, perhaps you can make a "bridge process" that interface on one side with whatever IPC you are stuck with, and on the other side uses a select()able IPC to communicate with your serial code.
Store away what you got so far of the message in a buffer of some sort.
If you don't want to block while waiting for new data, use something like select() on the serial port to check that more data is available. If not, you can continue doing some processing or whatever needs to be done instead of blocking until there is data to fetch.
When the rest of the data arrives, add to the buffer and check if there is enough to comprise a complete message. If there is, process it and remove it from the buffer.
You must cache enough of a message to know whether or not it is a complete message or if you will have a complete valid message.
If it is not valid or won't be in an acceptable timeframe, then you toss it. Otherwise, you keep it and process it.
This is typically called implementing a parser for the device's protocol.
This is the algorithm (blocking) that is needed:
while(! complete_packet(p) && time_taken < timeout)
{
p += reading_device.read(); //only blocks for t << 1sec.
time_taken.update();
}
//now you have a complete packet or a timeout.
You can intersperse a callback if you like, or inject relevant portions in your processing loops.

Resources