简体   繁体   中英

Frequent read/write operation from socket in C

I want to write a script for the server (socket programming) in C which will be there in listening mode and read the HTTP requests from client and do some action on that request.

For Example: Suppose the request I got is as below :

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><line2:connectionClearedEvent><cause>normalClearing</cause></line2:connectionClearedEvent></SOAP-ENV:Body></SOAP-ENV:Envelope>

I want to check, if the request has " connectionClearedEvent " string then increment the counter by one.

Problem:

1st Idea Assuming there is load on the server, if the implementation is done to write all the requests from socket to a file then due to frequent write operations, it is skipping some requests.

Second Idea Assuming there is load on the server, if the implementation is to just read the incoming request and search for that keyword, then also due to frequent read operation it is skipping some request.

Can anyone suggest a way out for the same to do the above action while there is loads of request coming to server.

Edit: Code for the same connection_handler() will handle connection for each client but the issue I am facing now is with handling file.

 #include<stdio.h> #include<string.h> //strlen #include<stdlib.h> //strlen #include<sys/socket.h> #include<arpa/inet.h> //inet_addr #include<unistd.h> //write #include<pthread.h> //for threading , link with lpthread //the thread function void *connection_handler(void *); int main(int argc , char *argv[]) { printf("Program name %s\\n", argv[0]); if( argc == 2 ) { printf("The argument supplied is %s\\n", argv[1]); } else if( argc > 2 ) { printf("Too many arguments supplied.\\n"); } else { printf("Server Port not provided..exiting \\n"); // scanf("%s",&argv[1]); return 1; } int socket_desc , client_sock , c , *new_sock; struct sockaddr_in server , client; //Create socket socket_desc = socket(AF_INET , SOCK_STREAM , 0); if (socket_desc == -1) { printf("Could not create socket"); } puts("Socket created"); //Prepare the sockaddr_in structure server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(atoi(argv[1])); //Bind if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0) { //print the error message perror("bind failed. Error"); return 1; } puts("bind done"); //Listen listen(socket_desc , 3); //Accept and incoming connection puts("Waiting for incoming connections..."); c = sizeof(struct sockaddr_in); //Accept and incoming connection puts("Waiting for incoming connections..."); c = sizeof(struct sockaddr_in); while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) ) { puts("Connection accepted"); pthread_t sniffer_thread; new_sock = malloc(1); *new_sock = client_sock; if( pthread_create( &sniffer_thread , NULL , connection_handler , (void*) new_sock) < 0) { perror("could not create thread"); return 1; } //Now join the thread , so that we dont terminate before the thread //pthread_join( sniffer_thread , NULL); puts("Handler assigned"); } if (client_sock < 0) { perror("accept failed"); return 1; } return 0; } /* * This will handle connection for each client * */ void *connection_handler(void *socket_desc) { //Get the socket descriptor int sock = *(int*)socket_desc; int read_size; char *message , client_message[2000]; static char* ok_response = "HTTP/1.1 200 OK\\r\\n" "Content-Length: 101\\r\\n" "Content-type: text/xml; charset=utf-8\\r\\n" "\\r\\n" "<html>\\n" " <body>\\n" " <h1>Bad Request</h1>\\n" " <p>This server understand your request.</p>\\n" " </body>\\n" "</html>\\n"; static char* body = "<html>\\n" " <body>\\n" " <h1>Bad Request</h1>\\n" " <p>This server understand your request.</p>\\n" " </body>\\n" "</html>\\n"; printf("content length : %d\\n",strlen(body)); //Receive a message from client while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 ) { //Send the message back to client puts(client_message); write(sock , ok_response , strlen(ok_response)); memset (client_message,'\\0',2000); } if(read_size == 0) { puts("Client disconnected"); fflush(stdout); } else if(read_size == -1) { perror("recv failed"); } //Free the socket pointer free(socket_desc); return 0; } 

There are three main things to do here (Can be combined):

  1. Increase the listening queue ( listen(socket, <number of pending requests>) ) - This will help dealing with bursts of requests, but if your're not handling requests fast enough, this too will eventually fail

  2. Distribute your workload on many workers to take advantage of modern multi-threaded and multi-processing environments. This can be done either by threads or processes where for each request, after accept ing the incoming connection, the new connection socket is given to a worker thread/process to handle. This way, you don't block the listening socket while processing the requests. This too, can only scale so much as you'll eventually run out of workers if your server is overloaded.

  3. Clustering - Eventually, it's possible that a single server/machine is incapable of handling the incoming load. You'll need to create a load balancing mechanism and divert requests to different machines to process.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM