LINUX.ORG.RU

Как в С узнать об обыве сокетного соединения


0

0

Такая беда

у меня есть самый преметивный сервер ,,,,, server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); sockaddr_in local; memset(&local, 0, sizeof(local)); local.sin_family = AF_INET; local.sin_port = htons(4012); local.sin_addr.s_addr = htonl(INADDR_ANY); ,,,,, if( bind(server, (sockaddr*)(&local), sizeof(local))!=0 ) {....} if( listen(server, 10)!=0 ) {....} while client = accept(server,(sockaddr*)&from, (socklen_t*)&fromLen); while (1) { sizein = recv (client,in,1000*sizeof(char)); ..... if ((strncmp (in,"quit",4))==0) { break;} ....

send(client, out, strlen(out)+1, 0); } ..............

конекчусь к нему телнетом/ И если просто рву соединение (закрываю окно в котором телнет ) то сервер перестает останавливаться на recv и бесконечно крутиться в цикле!

Как отследить такой момент и выйти из цикла в данном случае!

PS! Пробовал перехватывать сигнал SIGPIPE - не спасает его нет/

anonymous

>Пробовал перехватывать сигнал SIGPIPE - не спасает его нет

у тебя ведь и пайпов нет ;-)

лови -1 от recv а дальше смотри errno.

а ещё тебе может помочь select().

cvv ★★★★★
()
Ответ на: комментарий от cvv

>>Пробовал перехватывать сигнал SIGPIPE - не спасает его нет

>у тебя ведь и пайпов нет ;-)

Почему? Согласно man recv:

НАЗВАНИЕ
recv, recvfrom, recvmsg - получить сообщение из сокета

...

Аргумент flags системного вызова recv формируется с помощью объединения
логической операцией ИЛИ одного или бол

...

MSG_NOSIGNAL
Этот флаг отключает возникновение сигнала SIGPIPE на потоковых
сокетах, если другая сторона вдруг исчезает.

Тоже самое, если записываем в ресетнутое соединение. В errno по логике вещей будет EINTR.

seiken ★★★★★
()
Ответ на: комментарий от seiken

>>у тебя ведь и пайпов нет ;-)

>Почему? Согласно man recv:

это было что-то типа шутки

Eсли тебе нужен sigpipe то ты должен разрешить его посылку не только сбрасыванием MSG_NOSIGNAL но и соответствующими флагами sigaction().

>Тоже самое, если записываем в ресетнутое соединение. В errno по логике вещей будет EINTR.

нет.

этот вопрос не раз обсуждался. поройся в архиве. там есть толковые обьяснения

cvv ★★★★★
()

>PS! Пробовал перехватывать сигнал SIGPIPE - не спасает его нет/ Он появится если ты попробуешь записать что-то в сокет, закрытый противоположной стороной. Ошибки чтения всплывают при записи. И наоборот.

OxiD ★★★★
()
Ответ на: комментарий от OxiD

Вот тебе примерчик:

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
	int server,client;
	struct sockaddr_in local,from;
	socklen_t sl=sizeof(from);
	
	bzero(&local,sizeof(local));
	local.sin_family=AF_INET;
	local.sin_port=htons(4012);
	local.sin_addr.s_addr=htonl(INADDR_ANY);

	if((server=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==-1)
	{
		perror("socket");
		exit(1);
	}
	
	if(bind(server,(struct sockaddr*)(&local),sizeof(local)))
	{
		perror("bind");
		exit(1);
	}
	
	if(listen(server,1000)!=0)
	{
		 perror("listen");
		 exit(1);
	}

	for(;;)
	{
		int rc;
		char in[1024];
	
		client=accept(server,(struct sockaddr*)(&from),&sl);
	        
		if(client==-1)
		 {
	        	perror("accept");
			continue; 
             }
			
		while((rc=recv(client,in,sizeof(in)-1,0))>=0)
				{
					in[rc]='\0';
					if(!strncmp(in,"quit",4))
						break;	
					
					send(client,in,rc,0);
				}
		close(client);
	}
}

OxiD ★★★★
()
Ответ на: комментарий от seiken

не помню

но обьяснял кажись idle а помогал murr

cvv ★★★★★
()
Ответ на: комментарий от OxiD

Так, начал разбираться и совсем запутался :) Значит когда мы убиваем клиента, он посылает FIN и получает от сервера ACK. После этого клиента уже как бы и нет, а сервер переходит в состояние CLOSE_WAIT. recv на сервере возвращает 0, потому что для сервера соединение закрыто на чтение. Прочитав 0 байт, сервер вызывает send, но поскольку в буфере 0 байт, данные не передаются, подтверждать нечего, и сервер зацикливается в recv-send навсегда :) Но если сервер всё же попытается отправить какие-то данные убитому клиенту, он получит сегмент RST. После получения RST попытка записи приведёт к генерации SIGPIPE. Вроде так.
Однако, ни где не сказано, что этот SIGPIPE надо специально разрешать.

seiken ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.