LINUX.ORG.RU

Сообщения Suspended

 

Не могу победить TIME_WAIT, как закрывать сокеты?

По определённым причинам, необходимо реализовать свой хттп-сервер, не требовательный к ресурсам (т.е. запуск нового thread на новый коннект - вполне ничо так решение). Всё отлично, кроме одного: мат. ожидание нагрузки - 2 запроса в секунду. Но при этом, закрытые сокеты остаются висеть в памяти в состоянии TIME_WAIT, и где-то через 5-10 минут лимит заканчивается, и на очередном вызове (предположительно) accept основной поток завершается, и вёб-сервер накрывается медным тазом, вместе со всеми своими обязанностями. Спрашивается, как решить эту неприятную ситуацию, если вот апач вполне с ней справляется? Хотя, этот кажется процесс новый запускает каждый раз... но всё равно, форки мне не помогли. В интернете была информацию по этой проблеме, но решения найти не смог. Привожу код сервера. Для исключения возможности проблем с синхронизацией, привожу полностью однопоточный код (который легко возвращается в многопоточный). Открывается на 4747 порту.

#include<stdio.h>  
#include<string.h>  
#include<stdlib.h>  
#include<unistd.h>  
#include<sys/types.h>  
#include<sys/stat.h>  
#include<sys/socket.h>  
#include<arpa/inet.h>  
#include<netdb.h>  
#include<signal.h>  
#include<fcntl.h>  
#include <pthread.h>


#define CONNMAX 1000  
#define BYTES 1024  
#define MAX_PATH 260


char ROOT[MAX_PATH];  
int listenfd;//, clients[CONNMAX];  



void start_listen(char *port)  
{  
	struct addrinfo hints, *res, *p;  

	// getaddrinfo for host  
	memset (&hints, 0, sizeof(hints));  
	hints.ai_family = AF_INET;  
	hints.ai_socktype = SOCK_STREAM;  
	hints.ai_flags = AI_PASSIVE;  
	if (getaddrinfo( NULL, port, &hints, &res) != 0)  
	{  
		perror ("getaddrinfo() error");  
		exit(1);  
	}  
	// socket and bind  
	for (p = res; p!=NULL; p=p->ai_next)  
	{  
		listenfd = socket (p->ai_family, p->ai_socktype, 0);  
		if (listenfd == -1) continue;  
		if (bind(listenfd, p->ai_addr, p->ai_addrlen) == 0) break;  
	}  
	if (p==NULL)  
	{  
		perror ("socket() or bind()");  
		exit(1);  
	}  

	freeaddrinfo(res);  

	// listen for incoming connections  
	if ( listen (listenfd, 1000000) != 0 )  
	{  
		perror("listen() error");  
		exit(1);  
	}  
}  

int init_server()  
{   
	char c;      

	//Default Values PATH = ~/ and PORT=4747  
	char PORT[6];  
	strcpy(PORT,"4747");  
	strcpy(ROOT, getenv("PWD"));  
	strcat(ROOT, "/web");


	printf("%sWeb panel runned at port %s%s%s\n", "\033[92m", "\033[36m", PORT, "\033[0m");

	//	printf("Server started at port no. %s%s%s with root directory as %s%s%s\n","\033[92m",PORT,"\033[0m","\033[92m",ROOT,"\033[0m");  
	// Setting all elements to -1: signifies there is no client connected  
	int i;  

	start_listen(PORT);  

}  


//client connection  
void * respond(void * sock_v)  
{  
	int sock = (int) sock_v;
	char mesg[99999], *reqline[3], data_to_send[BYTES], path[99999];  
	int rcvd, fd, bytes_read;  

	memset( (void*)mesg, (int)'\0', 99999 );  

	rcvd=recv(sock, mesg, 99999, 0);  

	if (rcvd<0)    // receive error  
		fprintf(stderr,("recv() error\n"));  
	else if (rcvd==0)    // receive socket closed  
		fprintf(stderr,"Client disconnected upexpectedly.\n");  
	else    // message received  
	{  
		//printf("%s", mesg);  
		reqline[0] = strtok (mesg, " \t\n");  
		if ( strncmp(reqline[0], "GET\0", 4)==0 )  
		{  
			reqline[1] = strtok (NULL, " \t");  
			reqline[2] = strtok (NULL, " \t\n");  
			if ( strncmp( reqline[2], "HTTP/1.0", 8)!=0 && strncmp( reqline[2], "HTTP/1.1", 8)!=0 )  
			{  
				write(sock, "HTTP/1.0 400 Bad Request\n", 25);  
			}  
			else  
			{  
				if ( strncmp(reqline[1], "/\0", 2)==0 )  
					reqline[1] = (char*)"/status.html";        //Because if no file is specified, index.html will be opened by default (like it happens in APACHE...  

				strcpy(path, ROOT);  
				strcpy(&path[strlen(ROOT)], reqline[1]);  
				//printf("file: %s\n", path);  

				static int resp_num = 0;

				char buff[100];
				sprintf(buff, "Responsed %d times", ++resp_num);

				send(sock, "HTTP/1.0 200 OK\n\n", 17, 0);  
				send (sock, buff, strlen(buff), 0);  

			}  
		}  
	}  

	//Closing SOCKET  
	
	linger l = { 1, 1 };
	setsockopt(sock, SOL_SOCKET, SO_LINGER, &l, sizeof(linger));
	close(sock); 
	
} 


void * http_server_loop (void *)
{
	init_server();

	socklen_t addrlen; 
	int slot=0;  

	// ACCEPT connections  
	while (1)  
	{  
		sockaddr_in clientaddr;  
		addrlen = sizeof(clientaddr);  
		
		int sock = accept (listenfd, (sockaddr *) &clientaddr, &addrlen);  

		if (sock<0)  
			fprintf(stderr, "accept() error num: %d\n", (void*)sock);  
		else  
		{  
/*			if ( fork()==0 )  
			{  
				respond(slot);  
				exit(0);  
			}  */

			//pthread_t thread;
			//pthread_create(&thread, NULL, respond, (void*) sock);

			respond((void *)sock);
		}  

	}  

	return 0;  
}


int start_http_server ()
{
	pthread_t thread;

	int err_code;
	if (err_code = pthread_create(&thread, NULL, http_server_loop, NULL))
	{
		fprintf(stderr, "pthread_create fails with: %d\n", err_code);
		return 2;
	}

	return(0);
}
 


//////////////////////////////////////////////////////////////////////////
// For testing
//////////////////////////////////////////////////////////////////////////


int main () 
{
//	start_http_server();
	http_server_loop(0);

	usleep(0x7FFFFFFF);
}

Suspended
()

RSS подписка на новые темы