Подскажите пожалуйста, в чём же ошибка. Почему я не могу перехватить POLLHUP POLLERR ??
Программа должна при обрыве или завершении связи вызвать return 0;
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <resolv.h>
#include <sys/poll.h>
#include <fcntl.h>
#include <netinet/in.h>#define PORT 6666
#define TIME_OUT 300
struct pollfd fds[1];
int main(void)
{
struct sockaddr_in addr;
int value=1;int cl=1,result,k,addr_len=sizeof(addr),sd;
char buffer[256];
int bytes;
sd = socket(PF_INET, SOCK_STREAM, 0);
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = INADDR_ANY;
setsockopt(sd,SOL_SOCKET,SO_REUSEADDR, &value,sizeof(value));
if ( bind(sd, (struct sockaddr *)&addr, sizeof(addr)) == 0 )
{
listen(sd,5);
fds[0].fd=accept(sd,0,0);
fcntl(fds[0].fd,F_SETFL,O_NONBLOCK);
fds[0].events=POLLIN|POLLHUP;
for (;;)
{
if ( (result = poll(fds, 1, 500)) > 0 )
{
if(((fds[0].revents&POLLHUP) == POLLHUP) ||
((fds[0].revents&POLLERR) == POLLERR) ||
((fds[0].revents&POLLNVAL) == POLLNVAL))
{puts("POLLHUP");return 0;}
if ( (fds[0].revents & POLLIN)==POLLIN )
{
recv(fds[0].fd,buffer,sizeof(buffer),0);
puts(buffer);
printf("POLLIN\n");
}
}
else if ( result < 0 )
{perror("poll() error");exit(0);}
}
}
return 0;
}
>Подскажите пожалуйста, в чём же ошибка. Почему я не могу перехватить POLLHUP
> POLLERR ??
>Программа должна при обрыве или завершении связи вызвать return 0;
>
>
>#include <stdio.h>
>#include <unistd.h>
>#include <sys/socket.h>
>#include <resolv.h>
>#include <sys/poll.h>
>#include <fcntl.h>
>#include <netinet/in.h>
>
>#define PORT 6666
>#define TIME_OUT 300
>struct pollfd fds[1];
>int main(void)
>{
>struct sockaddr_in addr;
>int value=1;int cl=1,result,k,addr_len=sizeof(addr),sd;
>char buffer[256];
>int bytes;
>sd = socket(PF_INET, SOCK_STREAM, 0);
>bzero(&addr, sizeof(addr));
Тут советую юзать memset (но это так, просто не по теме)>addr.sin_family = AF_INET;
>addr.sin_port = htons(PORT);
>addr.sin_addr.s_addr = INADDR_ANY;
>setsockopt(sd,SOL_SOCKET,SO_REUSEADDR, &value,sizeof(value));
>if ( bind(sd, (struct sockaddr *)&addr, sizeof(addr)) == 0 )
>{
>
> listen(sd,5);
>fds[0].fd=accept(sd,0,0);
>fcntl(fds[0].fd,F_SETFL,O_NONBLOCK);
А это-то зачем? У тебя же есть мультиплексор в лице POLL. Не надо играцца с разблокированными сокетами, тока гемору огребешь, да и POLL в классическом варианте юзают на блокированном сокете>fds[0].events=POLLIN|POLLHUP;
>for (;;)
>{
>if ( (result = poll(fds, 1, 500)) > 0 )
>{
> if(((fds[0].revents&POLLHUP) == POLLHUP) ||
>
> ((fds[0].revents&POLLERR)
>== POLLERR) ||
> ((fds[0].revents&POLLNVAL)
>== POLLNVAL))
Тут не совсем верно. Р-евенты заполняются тоже мультиплексорно, т.е. вполне реальна ситуация, что у тебя будет промаскирована и POLLIN и POLLHUP одновременно (тогда условие (fds[0].revents&POLLHUP) == POLLHUP не проканает). Т.е. лучше делать просто if (fds[0].revents&POLLERR || fds[0].revents&POLLHUP || fds[0].revents&POLLNVAL) {}> {puts("POLLHUP");return 0;}
>
>if ( (fds[0].revents & POLLIN)==POLLIN )
>{
>recv(fds[0].fd,buffer,sizeof(buffer),0);
Ну и судя по оформлению вот этого ресива, он ошибки раньше словит, чем poll-мультиплексор. При нормальном разрыве соединения он вернет 0 (странно что ты возврат не проверяешь) а потом только придет р-евент POLLHUP, а при аварийном у тебя прога ваще упадет с SIGPIPE (ибо в ресиве нету флага MSG_NOSIGNAL). Т.е. тут можно классический перехват сделать вроде
if (recv(fds[0].fd,buffer,sizeof(buffer),MSG_NOSIGNAL)<=0) {Типа наелись}И еще, как раз изза мультимаскирования р-евентов лучше сначала проверять полезные флаги (POLLIN POLLOUT) а потом уже ошибочные. Ибо тебе может придти мультисет POLLIN+POLLHUP, к примеру, а ты по POLLHUP'у сразу все прибъешь и похоронишь хвостик данных.
>puts(buffer);
>printf("POLLIN\n");
>}
>}
>else if ( result < 0 )
>{perror("poll() error");exit(0);}
>}
>}
>return 0;
>}
>fds[0].events=POLLIN|POLLHUP;
В догонку - выдержка из мана:
...или событий типа POLLERR, POLLHUP или POLLNVAL (эти три битовых флага не имеют смысла при использовании в поле events и будут установлены в поле revents, если соответствующее условие истинно.)Так что |POLLHUP - это излишество ;)
По поводу игр с блокируемыми сокетами.
Как раз не рекомендуется играться с блокированными сокетами, потому как возможна ситуация, что все нафик заблокируется. При работе с сетью даже при демультиплексировании событий сокеты нужно делать неблокируемыми.
>По поводу игр с блокируемыми сокетами.
>Как раз не рекомендуется играться с блокированными сокетами, потому как возможна ситуация,
>что все нафик заблокируется. При работе с сетью даже при демультиплексировании
>событий сокеты нужно делать неблокируемыми.Ну это уже из области извратов. Получать от ядра сигнал, что есть данные, но на всякий случай деблочить сокет (а вдруг их нету? ;)))... Если уж ядру не доверять, то нах ты выбрал данную ОС для реализации?