I'm learning my way about socket programming in C (referring to Beej).
Here is a simple multi-user chat server i'm trying to implement:
http://pastebin.com/gDzd0WqP
On runtime, it gives Bus Error. It's coming from the lines 68-78.
Help me trace the source of the problem?
in fact, WHY is my code even REACHING that particular region? I've just run the server. no clients have connected.. :#
ps - i know my code is highly unreliable (no error checks anywhere), but i WILL do that at a later stage, i just want to TEST the functionality of the code before implementing it in all it's glory ;)
line 81
msg[MSG_SIZE] = '\0';`
overruns your buffer. Make it
msg[MSG_SIZE - 1] = '\0';`
You also need to check the return value of all the calls that can fail, that's line 39,42,45,68 and 80
Edit: And if you'd checked for errors, likely you'd seen the accept() call fail, likely due to the socket not being in listen mode - that is, you're missing a call to listen()
Another thing to consider is that you can't necessarily copy fd_set variables by simple assignment. The only portable way to handle them is to regenerate the fd_set from scratch by looping over a list of active file descriptors each time.
Related
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.
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.
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
I'm not an expert in C programming, but I'm trying to write a fairly simple program using sendmsg() and recvmsg() to send a message between a client and a server (both are on the same machine, so basically I'm sending a message to localhost).
After initialising the required structures (as in the iovec and the msghdr) and succesfully connecting the client to the server, my sendmsg() call fails with "no buffer space avaliable" errno.
This is what linux man reports about this type of error:
The output queue for a network interface was full. This generally indicates that the interface has stopped sending, but maybe caused by transient congestion. (Normally, this does not occur in Linux. Packets are just silently dropped when a device queue overflows.)
I looked around on the Internet and as a result I found out that sendmsg() is not widely used, and nobody could relate with this type of error. The only useful advice I found was to check a possible excess of open sockets, but again I always close EVERY socket I create.
So I'm stuck, basically because being quite the noob I don't know exactly where to look to fix this kind of problem.
If anybody knows how to proceed, it would be great.
(And please don't tell me not to use sendmsg(), because the whole purpose of my work is to understand this syscall, and not send a message to myself)
Here's the code I've written so far on pastebin: client and server
--SOLVED--
Thank you very much. I've been able to solve the problem and I fixed other mistakes I made, so here's the functioning code for sendmsg() and recvmsg() working message-passing: Client and Server
As others have pointed out, iovlen should be 1. But also, you want to zero out mh before initializing some of its fields since you're probably sending in garbage in the uninitialized fields and the syscall gets confused. Also, it doesn't really make sense to set msg_name and msg_namelen since you're connected and can't change your mind about where to send the data anyway.
This is what works for me in your client code:
/* The message header contains parameters for sendmsg. */
memset(&mh, 0, sizeof(mh));
mh.msg_iov = iov;
mh.msg_iovlen = 1;
printf("mh structure initialized \n");
The msg_iovlen field contains the number of elements in the iov array, not its size in bytes.
The system interpreted the following uninitialized memory as iov elements, ended up with a packet that is larger than the socket buffer space available, and thus refused to send the data.
Okay, so in your code I found this:
mh.msg_iovlen = sizeof(iov);
Which sets the msg_iovlen member to the size of struct iovec. But the documentation says this about this field:
size_t msg_iovlen; /* # elements in msg_iov */
So your code is wrong, it tells sendmsg() that it's going to send way more elements than you actually initialize.
The basic code sequence I'm interesting for is (pseudocode)
sendto(some host); // host may be unreachable for now which is normal
...
if(select(readfs, timeout)) // there are some data to read
recvfrom();
Since Win2000, ICMP packet, which is sent back after sending UDP datagram to unreachable port, triggers select, after that recvfrom fails with WSAECONNRESET. Such behaviour isn't desirable for me, because I want select to finish with timeout in this case (there are no data to read). On Windows this can be solved with WSAIoctl SIO_UDP_CONNRESET ( http://support.microsoft.com/kb/263823 ).
My questions are:
Is SIO_UDP_CONNRESET the best way in this situation?
Are there some other methods to ignore ICMP for "select" or to filter it for recvfrom (maybe, ignoring WSAECONNRESET error on Windows treating it like timeout, can this error be triggered in some other case)?
Are there similar issues on Linux and Unix (Solaris, OpenBSD)?
select()'s readfds set really just reports that a read() on the socket won't block -- it doesn't promise anything about whether or not there is actual data available to read.
I don't know what specifically you're trying to accomplish with the two-second timeout rather than just sleeping forever -- nor why you can't just add an if block to check for WSAECONNRESET from recvfrom() -- but it feels like you've got an overly-complicated design if it doesn't handle this case well.
The select_tut(2) manpage on many Linux systems has some guidelines for properly using select(). Here's several rules that seem most apropos to your situation:
1. You should always try to use select() without a timeout.
Your program should have nothing to do if there is no
data available. Code that depends on timeouts is not
usually portable and is difficult to debug.
...
3. No file descriptor must be added to any set if you do not
intend to check its result after the select() call, and
respond appropriately. See next rule.
4. After select() returns, all file descriptors in all sets
should be checked to see if they are ready.