Implementing thread in UDP server using c - c

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.

Related

Multithreaded sender

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.

write()/read() in a Client/Server, pthread application in C returns -1 always when on non-main thread?

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.

how to get client address in a multithreading TCP server for each connection

in a multithreading tcp server, I don't know how to store the client address for each cocnnection.
First, let's consider the case where in each thread, there is only 1 tcp connection(namely only one connfd) at the same time.This client address will be used in each thread.
for multh-threading tcp server, there are three types:
(1) one thread per connection, in this type, I can use thread-specific data to store the client address. Like:
listen(listenfd, backlog);
pthread_key_create(&key, null);
for(;;){
connfd=accept(listenfd, client_addr, socklen);
pthread_create(pid, null, func, null);
..
}
and
func(){
pthread_setspecific(key,(void *)client_addr);
// **and then the client_addr can be obtained by pthread_getspecific(key)**
}
are there any problem in this solution?
I'm afraid that before pthread_setspecific() is called, accept() is called again and client_addr is changed.
(2) Half-syn and half-async: this is similar to (1)
(3) leader-follower type:
connfd=listen(listenfd, backlog);
pthread_key_create(&key, null);
for(i:N){
pthread_create(pid, null, func, null);
}
func(){
accept(listenfd, client_addr, socklen);
pthread_setspecific(key,(void *)client_addr);
}
for this type, still since client_addr may be changed between accept() and pthread_setspecific().
for the case where each thread has many tcp connections at the same time, it is even unimaginable!
so How can I get the client address for each thread?
Are there any work-around for this problem?
thanks!
Just call getpeername(2) on the socket in the handling thread, no need to get all fancy with thread-local storage.

There is a race condition in this code?

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.

Sockets and threads using C

I am new to both sockets and threads. I have this code:
listen(socket_fd, 20);
/* Looooop */
while (1) {
newsocket_fd = accept(socket_fd,
(struct sockaddr *) &client_addr,
&client_len);
if (newsocket_fd < 0) {
error("ERROR on accept");
}
pthread_t thread;
pthread_create(&thread, NULL, run_thread, (void *) newsocket_fd);
pthread_join(thread, NULL);
}
How can I start a new thread for each new connection, rather than for each request? These threads should be started when a new connection comes in, and these threads should then wait for requests, handle those requests, and finally return when the connection is closed. There should be one thread for each connection. Here is the code for run_thread:
void
*run_thread(void *ptr) {
char buffer[256];
bzero(buffer, 256);
int n;
n = read((int) ptr, buffer, 255);
if (n < 0) error("ERROR Reading from socket");
printf("%s\n\n**********\n\n", buffer);
/* Parse buffer and return result */
char *result;
{
/* First, determine command, 4 characters */
/* (much code) */
}
n = write((int) ptr, result, strlen(result));
if (n < 0) error("ERROR Writing to socket");
}
Can anyone help me? Thanks.
There is also a different critical error.
You cast the int to (void*). This does not make sense. Also, you can't pass the address directly since the variable could be changed on the next accept() call before the thread can copy the variable to its local stack. One way to write it would be something like this:
while (1) {
newsocket_fd = accept(socket_fd,
(struct sockaddr *) &client_addr,
&client_len);
if (newsocket_fd < 0) {
error("ERROR on accept");
}
pthread_t thread;
int *newsock = malloc(sizeof(int));
*newsock = newsocket_fd;
pthread_create(&thread, NULL, run_thread, newsock);
pthread_detach(thread);
}
With this approach, the thread will make sure to free() the newsock. E.g a simple
void *handler(void *thread_data) {
int fd = *(int *) thread_data;
free(thread_data);
....
}
Also, I assume pthread_detach() is okay, if the main program doesn't care about syncing up with the thread later with pthread_join().
You almost got it right. The problem is, however, that you are joining the thread right after creation, and pthread_join is actually a blocking call which is waiting for the thread to finish. It means that you will not be able to accept any more connections while that one thread is running. To solve this problem, you might want to use detached threads. You don't have to join detached threads. For this purpose, you have to create thread attributes using pthread_attr_init function and pass those attributes to pthread_create.
Be aware that if you have too many client connections, your application may run out of resources. So, in real world, you have to manage a pool of threads. But the best case scenario for TCP/IP server applications is to use asynchronous I/O. I do not know about C, but there is a very good library in C++ for asynchronous I/O application called boost::asio.
Vlad has good advice.
Also note that your newsocket_fd variable is being reused for each new connection in your accept loop, and then a pointer to it is passed to every worker thread. This will cause problems when you start having multiple clients connected at the same time.
EDIT: Ignore this comment, I misread the mistake you were making. Others have given proper corrections for your handling of newsocket_fd.

Resources