I need help getting mutex
to work the way I want. I am making a simple bank system with a server and multiple clients.
The server has two threads. One thread listens for connections. The second thread is created when a client connects to the server.
The client has 3 threads. There is the main thread that makes the other two. The second thread just receives messages from the server and outputs them. The third thread only takes input and sends them to the server.
I am trying to use mutex
on a customer session after they login. For example, if one client logs into the server with their account, I want to lock that account session with mutex
. So if any other client tries to login to the same account they would have to wait on the client that's already logged into it.
The above scenario works perfectly with my code. The problem I have currently is with multiple accounts. Lets say client1 logs into their account and starts doing stuff. Then client2 tries to login into an account different from client1. It will not let client2 inside because of the lock
from mutex
on client1's account.
I want to make it so if client1 logs into their account, no other client can login to client1's account until client1 is done. Though, other clients should be able to login to other accounts and have separate locks on them.
Here is my server code (lock
inside curr_acc()):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <unistd.h>
#include <pthread.h>
// Mutex var
pthread_mutex_t lock;
int main(int argc, char *argv[])
{
pthread_mutex_init(&lock, NULL);
server_listen();
pthread_mutex_destroy(&lock);
return 0;
}
int server_listen()
{
int socket_desc, client_sock, c, *new_sock;
int portno = 8888;
struct sockaddr_in server, client;
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(portno);
bind(socket_desc, (struct sockaddr *) &server, sizeof(server))
listen(socket_desc, 5);
c = sizeof(struct sockaddr_in);
// Accept connection
while((client_sock = accept(socket_desc, (struct sockaddr *) &client, (socklen_t *) &c)))
{
// Create new thread and sock
pthread_t sniffer_thread;
new_sock = malloc(1);
*new_sock = client_sock;
pthread_create(&sniffer_thread, NULL, handle_client, (void *) new_sock)
}
}
void *handle_client(void *new_sock)
{
// Convert void
int sock = *((int *) new_sock);
// Prepare to receive and send
int read_size, index;
char *msg = malloc(10);
while(recv(sock, msg, 10, 0) > 0)
{
if(strcmp(msg, "open") == 0)
new_acc(sock);
else if(strcmp(msg, "start") == 0)
curr_acc(sock);
else
write(sock, "Invalid input", 25);
memset(msg, 0, sizeof(msg));
}
free(new_sock);
free(msg);
// Exit the thread
pthread_exit(0);
}
void curr_acc(int sock)
{
int lock_ret;
// Get account name here and check if it's in array of accounts.
// Then try below
// Try and lock the thread then go inside
lock_ret = pthread_mutex_trylock(&lock);
if(!lock_ret)
{
// Show customer menu
write(sock, "\n Welcome!", 20);
cus_menu(sock);
// Unlock the thread
lock_ret = pthread_mutex_unlock(&lock);
}
else
{
printf("Cannot open account");
write(sock, "Cannot open account. Try again or wait...", 50);
}
}
This is a stripped down version of my server, but it should be enough to understand what I'm doing. If you want more, let me know.
My client sends a char
pointer to the server to check the input. If you need to see the client code, let me know as well. But it is pretty straight forward as described above.
Any help would be appreciated. I really want to understand mutex
better. Thank you!