TCP multi-threaded concurrent server
multithreaded servers are improvements to multi-process servers, because the multi-process server consumes large system resources when it creates the process, so instead of a process with threads, the service handlers can be created more quickly. According to statistics, creating a thread is 10,100 times times faster than creating a process , so the thread is called a "lightweight" process . A thread differs from a process in that all threads within a process share the same global memory, global variables, and so on, and this mechanism brings up synchronization problems.
TCP multi-threaded concurrent Server framework:
When we use multi-threaded concurrent servers, we use the above framework directly, and we only modify the contents of Client_fun (). code Example:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys /socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <pthread.h>/**************** Function name: void *client_fun (void *arg) function function: Thread function, Handling Customer Information function parameters: Connected socket function return: no ************************************************************************/void *client_ Fun (void *arg) {int recv_len = 0;char recv_buf[1024] = "";//Receive buffer int CONNFD = (int) arg; Sent over connected sockets//Receive data while ((Recv_len = recv (CONNFD, Recv_buf, sizeof (RECV_BUF), 0)) > 0) {printf ("Recv_buf:%s\n", recv_ BUF); Print data Send (CONNFD, recv_buf, Recv_len, 0); Back to the client data}printf ("Client closed!\n"); Close (CONNFD);//close connected socket return NULL;} ===============================================================//syntax format: void main (void)//Implement function: main function, establish a TCP concurrent server/ /inlet parameter: none//export parameter: no//===============================================================int main (int argc, char *argv[]) { Int SOCKFD = 0;//socket int CONNFD = 0;int Err_log = 0;struct sockaddr_in my_addr;//server address structural body unsigned short port = 8080; Listening Port pthread_t thread_id;printf ("TCP Server Started at Port%d!\n", port); SOCKFD = socket (af_inet, sock_stream, 0); Create a TCP socket if (SOCKFD < 0) {perror ("socket error"); exit (-1);} Bzero (&my_addr, sizeof (MY_ADDR)); Initialize the server address my_addr.sin_family = Af_inet;my_addr.sin_port = htons (port); my_addr.sin_addr.s_addr = htonl (Inaddr_any); printf ("Binding Server to Port%d\n", port);//Bind Err_log = Bind (SOCKFD, (struct sockaddr*) &my_addr, sizeof (MY_ADDR)); if (Err_log! = 0) {perror ("bind"); Close (SOCKFD); exit (-1);} Listen, socket becomes passive Err_log = Listen (SOCKFD), if (err_log! = 0) {perror ("listen"); Close (SOCKFD); exit (-1);} printf ("Waiting client...\n"); while (1) {char Cli_ip[inet_addrstrlen] = ""; Used to save client IP address struct sockaddr_in client_addr; Used to save the client address socklen_t Cliaddr_len = sizeof (CLIENT_ADDR); The!!! must be initialized Get an already established connection CONNFD = accept (sockfd, struct sockaddr*) &client_addr, &AMp;cliaddr_len); if (CONNFD < 0) {perror ("Accept this Time"); continue;} Print the client's IP and Port inet_ntop (Af_inet, &client_addr.sin_addr, Cli_ip, Inet_addrstrlen);p rintf ("--------------------- -------------------------\ n ");p rintf (" Client ip=%s,port=%d\n ", Cli_ip,ntohs (Client_addr.sin_port)); if (Connfd > 0) {//Because all threads in the same process share memory and variables, special handling and value passing is required when passing parameters. Pthread_create (&thread_id, NULL, (void *) Client_fun, (void *) CONNFD); Create thread Pthread_detach (thread_id); Thread separation, automatic recovery of resources at the end}}close (SOCKFD); return 0;}
Operation Result:
Note :
1. The last parameter of the Pthread_create () function above is the void * Type, why is it possible to pass the value connfd?
while (1) {int connfd = accept (SOCKFD, (struct sockaddr*) &client_addr, &cliaddr_len);p Thread_ Create (&thread_id, NULL, (void *) Client_fun, (void *) CONNFD); Pthread_detach (thread_id); }
because void * is 4 bytes, 4 bytes,
2. The last parameter of the Pthread_create () function above is can I pass an address? Yes, but it can cause unpredictable problems for the server
while (1) {int connfd = accept (sockfd, struct sockaddr*) & CLIENT_ADDR, &cliaddr_len);p thread_create (&thread_id, NULL, (void *) Client_fun, (void *) &CONNFD); Pthread_detach (thread_id);
2. If we want to pass more than one parameter to the thread function, we first consider that is the struct parameter , and then the value is not feasible, can only pass the address .
that's when we need to think about multitasking. Mutex or synchronization problem, here through Mutual exclusion Lock to solve this problem, make sure that the struct parameter value is saved by a temporary variable before it is allowed to be modified.
#include <pthread.h> pthread_mutex_t mutexes; Define mutex, global variable pthread_mutex_init (&mutex, NULL),//Initialize mutex, mutex is open/locked by default, before unlocking, Pthread_mutex_lock () Will block Pthread_mutex_lock (&mutex); int CONNFD = Accept (SOCKFD, (struct sockaddr*) &client_addr, &cliaddr_len); Parameters passed to the callback function, &CONNFD, address pass pthread_create (&thread_id, NULL, (void *) client_process, (void *) &CONNFD); Create thread// thread callback function void *client_process (void *arg ) {int CONNFD = * (int *) arg;//sent over connected socket // Unlock, Pthread_mutex_lock () wake up, do not block Pthread_mutex_unlock (&mutex); return NULL; }
Example code:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys /socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <pthread.h>pthread_mutex_t mutex;//define mutex, global variable/************************************************************************ function name: void *client_ Process (void *arg) function function: thread function, handling client information function parameters: Connected socket function returned: no ************************************************************ /void *client_process (void *arg) {int recv_len = 0;char recv_buf[1024] = "";//Receive buffer int CONNFD = * (int *) arg; Sent over connected sockets//Unlock, Pthread_mutex_lock () wake-up, non-blocking pthread_mutex_unlock (&mutex); Receive data while ((Recv_len = recv (CONNFD, Recv_buf, sizeof (RECV_BUF), 0)) > 0) {printf ("Recv_buf:%s\n", recv_buf);//Print Data S End (CONNFD, Recv_buf, Recv_len, 0); Back to the client data}printf ("Client closed!\n"); Close (CONNFD);//close connected socket return NULL;} ===============================================================//syntax format: void main (void)//Implement function: main function, establish a TCP concurrent server/ /Entry Parameters: none//export parameter: no//===============================================================int main (int argc, char *argv[]) {int SOCKFD = 0;//socket int CONNFD = 0;int Err_log = 0;struct sockaddr_in my_addr;//server address structural body unsigned short port = 8080; Listening Port pthread_t thread_id;pthread_mutex_init (&mutex, NULL); To initialize the mutex, the mutex is turned on by default to printf ("TCP Server Started at Port%d!\n", port), SOCKFD = socket (af_inet, sock_stream, 0); Create a TCP socket if (SOCKFD < 0) {perror ("socket error"); exit (-1);} Bzero (&my_addr, sizeof (MY_ADDR)); Initialize the server address my_addr.sin_family = Af_inet;my_addr.sin_port = htons (port); my_addr.sin_addr.s_addr = htonl (Inaddr_any); printf ("Binding Server to Port%d\n", port);//Bind Err_log = Bind (SOCKFD, (struct sockaddr*) &my_addr, sizeof (MY_ADDR)); if (Err_log! = 0) {perror ("bind"); Close (SOCKFD); exit (-1);} Listen, socket becomes passive Err_log = Listen (SOCKFD), if (err_log! = 0) {perror ("listen"); Close (SOCKFD); exit (-1);} printf ("Waiting client...\n"); while (1) {char Cli_ip[inet_addrstrlen] = ""; Used to save the client IP address of a struct SOCKaddr_in client_addr; Used to save the client address socklen_t Cliaddr_len = sizeof (CLIENT_ADDR); The!!! must be initialized Locked, Pthread_mutex_lock () will block Pthread_mutex_lock (&mutex) before unlocking, and/or get an already established connection CONNFD = accept (SOCKFD, struct sockaddr*) &client_addr, &cliaddr_len); if (CONNFD < 0) {perror ("Accept this Time"); continue;} Print the client's IP and Port inet_ntop (Af_inet, &client_addr.sin_addr, Cli_ip, Inet_addrstrlen);p rintf ("--------------------- -------------------------\ n ");p rintf (" Client ip=%s,port=%d\n ", Cli_ip,ntohs (Client_addr.sin_port)); if (Connfd > 0) {//parameter passed to callback function, &CONNFD, address pass pthread_create (&thread_id, NULL, (void *) client_process, (void *) &CONNFD); Create thread Pthread_detach (thread_id); Thread separation, automatic recovery of resources at the end}}close (SOCKFD); return 0;}
Operation Result:
Note : This mutex has a fatal effect on the operational efficiency of the server.
code Download:
Linux Network Programming--tcp Concurrent Server (multi-threaded)