I am working on sending traffic (such as UDP/TCP packets) from one machine to another. I am writing a C application which has 1 thread for each traffic type. I want these two threads to concurrently send packets.
Do I need to use any synchronization primitives such as a mutex lock within the sendMsg function since it is being called from each thread?
sockaddr_in dest;
void * udp(void * arg){
struct * info = arg;
int fd = socket(AF_INET, SOCK_DGRAM, 0);
//set up socket info
while(1){
sendMsg(udpInfo, fd);
}
}
void * tcp(void * arg){
struct * info = arg;
int fd = socket(AF_INET, SOCK_STREAM, 0);
// set up socket info
while(1){
sendMsg(tcpInfo, fd);
}
}
void sendMsg(struct * info, int fd){
sendTo(fd, "hello", strlen("hello") + 1, 0, (struct sockaddr*)&dest, sizeof(dest));
}
You seem to be a little unclear about how mutex works. A mutex is not applied on a piece of code, but a piece of data used within the code. Here the function is called by both threads, but there is no shared data between the threads. So as #Sami Kuhmonen said in a comment above, you don't need to use mutexes here.
You might need a mutex in future if, say, in case there was a third thread that pushed data into a (say) queue which your thread would then access from the queue and send to the connected computer. Then you would need to synchronise the way these threads push and pop data into and from the queue.
If you read the manpage for sendmsg you might see the following sentence:
If the message is too long to pass atomically through the underlying protocol, the error EMSGSIZE is returned, and the message is not transmitted.
Atomically means that the package is always send in one blob with no other data being able to insert itself in the middle. So no matter how many threads use sendmsg the kernel will mix packets.
Related
I created a multithreaded C TCP server. It seems to work (as a client I type a message and the message is sent to the server and the server prints what the client sent in a thread (and send back the client id).
Do I respect the "best practices" of a C multithreaded TCP server ?
Maybe I should use a semaphore to access / use the client_counter variable ?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h> // disable close() warning
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <pthread.h>
#define MAX_CONNECTIONS 5
static int client_counter = 0;
void* serverWorker(void* context)
{
char client_response[256];
int sock = *(int*)context;
char message[256] = "\n Hello dear client, you are the client number \n";
char numero[12];
sprintf(numero, "%d", client_counter); // SHOULD I USE A SEMAPHORE HERE FOR client_counter ?
while(1)
{
memset(client_response, 0, sizeof(client_response)); // clean string
recv(sock, &client_response, sizeof(client_response), 0);
printf("client number %s sent: '%s' \n", numero, client_response);
if (send(sock, numero , strlen(numero) , 0) < 0)
{
printf("ERROR while sending response to client from worker \n");
}
}
return NULL;
}
int main()
{
printf("Waiting for incoming connections ...\n");
// socket creation
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
// dserver address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(9002);
server_address.sin_addr.s_addr = INADDR_ANY;
// bind the socket to IP and port
bind(server_socket, (struct sockaddr*) &server_address, sizeof(server_address));
listen(server_socket, MAX_CONNECTIONS);
int client_socket;
while((client_socket = accept(server_socket, NULL ,NULL)))
{
client_counter++;
pthread_t thread_id;
pthread_create(&thread_id, NULL, serverWorker, (void*)&client_socket);
printf("new client ! \n");
}
close(server_socket);
return 0;
}
There are several problems in your code... you create a thread on an incoming connection and pass all the created threads a reference (the same reference) to the variable in which you have stored the socket descriptor. This will make all threads to share the same variable to store all the socket descriptors you'll get from the wildcard one. Probably you think well, i make a copy just on thread start, so this is not going to happen, but think two connections that come in almost simultaneously, thread main() runs and processes both. Then the first and second threads get scheduled and both get the same descriptor stored (the second one) and the first connection is leaked.
Another thing is that while this variable is local to main, it will cease to exist as soon as main() returns (which is not the end of the program, if the threads are to survive past main()'s return) but as you are in an endless loop (you probably don't know, but the only means for the server_socket to give an error is if you destroy (close() it) in a thread, or you drop the interface it is attached to.) This could lead to a SIGSEGV trap.
You can freely pass an int value casted to (void *) without problem, as the thread body function will convert it back to an int before use, which reduces to a noop at all, as pointer types are normally greater in size (or equal, but not lesser) than int. Anyway, this is strictly undefined behaviour, but probably that will work (as legacy software is full of such conversions, so all compilers normally implement to try to respect this) The right way to do this is to declare a struct of information to be passed to the thread on start and return from it. Then you can store on it whatever you want, but think that, as you have a dynamic amount of threads to come, you need the structs to be dynamically allocated.
In respect to the use of the client_counter variable, the only thread touching that variable is the one running main() code. This plants no major problem than the risk presented above, two updates in quick sequence can make both threads to get the values updated in main after main has made both updates.
Another issue is that you need to declare it volatile as the thread code will not assume it is only changed by it between accesses and will probably cache it as a register variable.
The messages passed between main() and the different threads you are getting can be implemented in two ways. This is the reason of the routines to get a void * on input and returning a void * on return:
The first uses a dynamic struct of local data (malloc()ed, passed from main() to the thread, and back on termination, (when you join the thread to main). This way allows you to collect result info from the thread in main and then you have to free(3) the struct in main. The struct is used as a communication message between the thread and the main routine in both directions, and you can store there any information you need to pass or to return back. Once the thread has finished, you can free() the structure in main (don't do it in the thread, as it has to survive its death)
The second involves no more communication with main() and the threads must deallocate the structure, once it is finished. This is simpler, and more adequate to your example. In this way, you can destroy the struct in the thread, or in main, but only if you have already joined the thread and are sure the struct is not going to be used by it.
One common mistake is that you do not examine the return values of send and recv calls. These calls may send and receive less then the entire buffer and such cases must be handled, as well as disconnects. That will also remove the need to use memset and strlen on received data.
Generally, dedicating a thread to each client is considered non-scalable. You may like to read the famous The C10K problem for a good treatment of I/O strategies for handling many clients. The article is old but the advice is timeless.
So, I have this client/server application, where the server has a producer/consumer architecture. I have 2 functions that handle writting and reading to the socket. The main thread of the server (the Producer) handles connections and passes socket descriptors via a Stack to the second thread, the Consumer, for processing.
The problem is, whenever I try to write() or read() the socket from a different-than-main thread, it always returns -1 and causes a Connection reset by peer error on client and Transport endpoint is not connected error on the server. Surpirsingly, it works perfectly when socket is read/written from the main thread.
Why does this happen? Is this official behaviour? How do I go about replying to the client with the Consumer thread? I don't believe it's because of the code I wrote, since the Consumer thread only calls the read/write-to-socket functions.
If you have any suspicion on which part could be a culprit, ask me to post some of the code.
EDIT:
typedef struct s_stack {
int * c_stack;
int base;
int top;
unsigned char is_full;
unsigned char is_empty;
int max_size;
} s_stack_t;
s_stack_t stack;
void * producer_routine(void * arguments) {
/* socket(), bind(), listen(), etc.,
socket fd on "socket_fd",
new connection fd on "new_fd" */
for(;;) {
new_fd = accept(socket_fd, (struct sockaddr *)&client_addr, &clen);
pthread_mutex_lock(&mutex);
while (stack.is_full) {
pthread_cond_wait(&stack_not_full, &mutex);
}
if (stack.is_full){
push(&stack, new_fd);
pthread_cond_signal(&stack_not_empty);
}
pthread_mutex_unlock(&mutex);
}
close(new_fd);
}
void * consumer_routine(void *args) {
for(;;) {
int socket_fd;
/* same mutex lock as above, just reversed, pop to socket_fd */
write_a_message_to_client(socket_fd);
}
}
int main() {
stack_init(&stack, 1024); // (s_stack_t * stack, int max_size)
pthread_t tidp, tidc;
int prc = pthread_create(&tidp, NULL, producer_routine, NULL);
int crc = pthread_create(&tidc, NULL, consumer_routine, NULL);
stack_destroy(&stack);
return 0;
}
The client just sends a message, and waits to receive one. If write_a_message_to_client() is called within any of those threads, even with the socket_fd passed as a parameter, I get the same errors. If it's called directly in main, it has no problem.
EDIT #2:
I tested this, and found my stack implementation to not work on Cygwin. Cygwin adds gibberish after the 3rd element for some reason, so the socket fds were invalid. Also, I was testing this in a Debian 6 VM and the server was crashing after connection from client. But I tested it in Arch, Kali and my Uni servers (Debian 7) and works as it should have been. A whole lot of trouble for a whole lot of nothing. Thanks Cygwin!
You should not call stack_destroy() until after both threads have completed. I think your entire program is running using a destroyed stack.
Use pthread_join() to wait for the threads to complete before destroying the stack.
I am trying to implement a multithreaded UDP server by creating thread.
The following method is used for creating thread.
pthread_create(&threadID, NULL, ThreadMain, threadArgs);
ThreadMain method is,
void *ThreadMain(void *threadArgs) {
pthread_detach(pthread_self());
int sock = ((struct ThreadArgs *) threadArgs)->sock;
free(threadArgs);
HandleUDPClient(sock);
return (NULL);
}
In the HandleUDPClient method is like this,
void HandleUDPClient(int sock) {
struct sockaddr_storage clntAddr; // Client address
// Set Length of client address structure (in-out parameter)
socklen_t clntAddrLen = sizeof(clntAddr);
// Block until receive message from a client
char buffer[MAXSTRINGLENGTH]; // I/O buffer
// Size of received message
ssize_t numBytesRcvd = recvfrom(sock, buffer, MAXSTRINGLENGTH, 0, (struct sockaddr *) &clntAddr, &clntAddrLen);
...
...
When I am creating socket and running the HandleUDPClient method it handles requests from client perfectly. But when I am trying to use thread, after entering the HandleUDPClient method it does not process the recvfrom method. Actually it does not wait for the client to receive any request. Program just terminates.
Can anybody tell me why this problem occurring and how can I resolve it?
The problem is that you detach your threads, meaning that you will not have to wait for your threads to exit. Instead the main program continues its work, until it reaches its end and then exit, with no regard for the (detached) threads still running.
Either don't detach the threads, and use pthread_join to "join" the threads, or use pthread_exit from the main thread to make sure it will wait for all detached threads to finish.
Is it possible to bind and listen to multiple ports in Linux in one application?
For each port that you want to listen to, you:
Create a separate socket with socket.
Bind it to the appropriate port with bind.
Call listen on the socket so that it's set up with a listen queue.
At that point, your program is listening on multiple sockets. In order to accept connections on those sockets, you need to know which socket a client is connecting to. That's where select comes in. As it happens, I have code that does exactly this sitting around, so here's a complete tested example of waiting for connections on multiple sockets and returning the file descriptor of a connection. The remote address is returned in additional parameters (the buffer must be provided by the caller, just like accept).
(socket_type here is a typedef for int on Linux systems, and INVALID_SOCKET is -1. Those are there because this code has been ported to Windows as well.)
socket_type
network_accept_any(socket_type fds[], unsigned int count,
struct sockaddr *addr, socklen_t *addrlen)
{
fd_set readfds;
socket_type maxfd, fd;
unsigned int i;
int status;
FD_ZERO(&readfds);
maxfd = -1;
for (i = 0; i < count; i++) {
FD_SET(fds[i], &readfds);
if (fds[i] > maxfd)
maxfd = fds[i];
}
status = select(maxfd + 1, &readfds, NULL, NULL, NULL);
if (status < 0)
return INVALID_SOCKET;
fd = INVALID_SOCKET;
for (i = 0; i < count; i++)
if (FD_ISSET(fds[i], &readfds)) {
fd = fds[i];
break;
}
if (fd == INVALID_SOCKET)
return INVALID_SOCKET;
else
return accept(fd, addr, addrlen);
}
This code doesn't tell the caller which port the client connected to, but you could easily add an int * parameter that would get the file descriptor that saw the incoming connection.
You only bind() to a single socket, then listen() and accept() -- the socket for the bind is for the server, the fd from the accept() is for the client. You do your select on the latter looking for any client socket that has data pending on the input.
In such a situation, you may be interested by libevent. It will do the work of the select() for you, probably using a much better interface such as epoll().
The huge drawback with select() is the use of the FD_... macros that limit the socket number to the maximum number of bits in the fd_set variable (from about 100 to 256). If you have a small server with 2 or 3 connections, you'll be fine. If you intend to work on a much larger server, then the fd_set could easily get overflown.
Also, the use of the select() or poll() allows you to avoid threads in the server (i.e. you can poll() your socket and know whether you can accept(), read(), or write() to them.)
But if you really want to do it Unix like, then you want to consider fork()-ing before you call accept(). In this case you do not absolutely need the select() or poll() (unless you are listening on many IPs/ports and want all children to be capable of answering any incoming connections, but you have drawbacks with those... the kernel may send you another request while you are already handling a request, whereas, with just an accept(), the kernel knows that you are busy if not in the accept() call itself—well, it does not work exactly like that, but as a user, that's the way it works for you.)
With the fork() you prepare the socket in the main process and then call handle_request() in a child process to call the accept() function. That way you may have any number of ports and one or more children to listen on each. That's the best way to really very quickly respond to any incoming connection under Linux (i.e. as a user and as long as you have child processes wait for a client, this is instantaneous.)
void init_server(int port)
{
int server_socket = socket();
bind(server_socket, ...port...);
listen(server_socket);
for(int c = 0; c < 10; ++c)
{
pid_t child_pid = fork();
if(child_pid == 0)
{
// here we are in a child
handle_request(server_socket);
}
}
// WARNING: this loop cannot be here, since it is blocking...
// you will want to wait and see which child died and
// create a new child for the same `server_socket`...
// but this loop should get you started
for(;;)
{
// wait on children death (you'll need to do things with SIGCHLD too)
// and create a new children as they die...
wait(...);
pid_t child_pid = fork();
if(child_pid == 0)
{
handle_request(server_socket);
}
}
}
void handle_request(int server_socket)
{
// here child blocks until a connection arrives on 'server_socket'
int client_socket = accept(server_socket, ...);
...handle the request...
exit(0);
}
int create_servers()
{
init_server(80); // create a connection on port 80
init_server(443); // create a connection on port 443
}
Note that the handle_request() function is shown here as handling one request. The advantage of handling a single request is that you can do it the Unix way: allocate resources as required and once the request is answered, exit(0). The exit(0) will call the necessary close(), free(), etc. for you.
In contrast, if you want to handle multiple requests in a row, you want to make sure that resources get deallocated before you loop back to the accept() call. Also, the sbrk() function is pretty much never going to be called to reduce the memory footprint of your child. This means it will tend to grow a little bit every now and then. This is why a server such as Apache2 is setup to answer a certain number of requests per child before starting a new child (by default it is between 100 and 1,000 these days.)
I'm trying to grasp the concepts of multithreading programming, and I think I'm doing well, but then I've found the following code for a simple echo server:
http://www.cs.utah.edu/~swalton/listings/sockets/programs/part2/chap7/echo-thread.c
And I'm thinking that the code is wrong, because it uses the same main local variable to store the data socket for each incoming connection. In particular, Im concerned about this part of main():
while (1)
{ int client, addr_size = sizeof(addr);
pthread_t child;
client = accept(sd, (struct sockaddr*)&addr, &addr_size);
printf("Connected: %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
if ( pthread_create(&child, NULL, Child, &client) != 0 )
perror("Thread creation");
else
pthread_detach(child); /* disassociate from parent */
}
As far as I understand, the variable client, local to the while loop, is allocated at exactly the same address in each iteration of the loop. So, when the first client is accepted, the thread receives &client, and when the second client is accepted, the value of client is overwritten with the new data socket, and this can have side-effects in the thread which is already running on the first client.
Observing the code of the function Child, which is the service thread, I can see that the argument is copied into a local variable:
void* Child(void* arg)
{ char line[100];
int bytes_read;
int client = *(int *)arg;
...etc...
and probably the author thought that this copy allows him to later tamper with the main client variable, but IMHO this can cause a race condition. If a second client arrives while the first thread is copying this variable, the value copied can be corrupt.
Am I right?
Yes, you are correct. There are two obvious ways to fix this:
Pass client to the thread instead of &client.
Allocate a new integer on the heap and pass its address to the thread and let the thread free it when it's done with it.
Yes, you are right.
You can demonstrate that you're right by adding a long sleep before int client = *(int*)arg; and connecting to the server two times while the first client thread.