According to poll() man, when the server closes socket, this client will receive POLLHUP event if poll() is used. However my program doesn't get it. When I close the socket from server side, the client receives POLLIN instead of POLLHUP. What's wrong with me? The client and server program both run on the same machine, and someone said POLLHUP doesn't work for local network, is that true? How can client know server close a socket? Here is my code. Please give me some suggestions. Thanks. By the way, my system is CentOS 4.4.
Client program:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <poll.h>
#define MAX_BUFFER 128
#define DAYTIME_SERVER_PORT 2213
void *secondThread(void *arg)
{
int in, index = 0, limit = MAX_BUFFER, nread;
char timebuffer[MAX_BUFFER];
int sd = *((int*) arg);
printf("sd = %d\n", sd);
int count;
struct pollfd fds[100];
fds[0].fd = sd;
fds[0].events = POLLIN | POLLHUP;
while (1) {
if ((count = poll(fds, 1, -1)) > 0) {
if (fds[0].revents & POLLHUP ) {
printf("peer closed. \n");
pthread_exit(NULL);
}
if (fds[0].revents & POLLERR ) {
printf("peer ERR. \n");
pthread_exit(NULL);
}
if (fds[0].revents & POLLNVAL ) {
printf("peer closed. \n");
pthread_exit(NULL);
}
if (fds[0].revents & POLLIN) {
printf("Get a event %d\n", count);
ioctl(sd, FIONREAD, &nread);
if (0 == nread) {
printf("nothing to read.\n");
pthread_exit(NULL);
} else {
if (nread > 3) {
nread = 3;
}
while ((in = read(sd, timebuffer+index, nread)) > 0) {
index += in;
limit -= in;
}
timebuffer[index] = 0;
printf("Read %s from sd (%d). \n", timebuffer, sd);
}
}
}
}
}
int main()
{
int connectionFd, in, index = 0, limit = MAX_BUFFER;
struct sockaddr_in servaddr;
char timebuffer[MAX_BUFFER];
connectionFd = socket(AF_INET, SOCK_STREAM, 0);
printf("socket id %d\n", connectionFd);
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(2214);
pthread_t hThread;
if ( -1 == connect(connectionFd, (struct sockaddr*) &servaddr, sizeof(servaddr)) ) {
printf("Failed to connect.\n");
return 0;
}
pthread_create(&hThread, 0, secondThread, &connectionFd);
fd_set testset;
FD_ZERO(&testset);
FD_SET(connectionFd, &testset);
int status;
while (1) {
if (0 == pthread_join(hThread, (void **)&status)) {
break;
}
}
close(connectionFd);
return 0;
}
Server program:
Code:
#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <poll.h>
#include <string.h>
int main()
{
char buffer[128];
int result, nread, sd, clientsd=-1, nclientlen;
struct sockaddr_in addr, clientaddr;
sd = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family = AF_INET;
addr.sin_port = htons(2214);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(sd, (struct sockaddr*) &addr, sizeof(addr));
listen(sd, 5);
struct pollfd fds[100];
nfds_t nfds = 0;
fds[nfds].fd = 0;
fds[nfds].events = POLLIN;
nfds++;
fds[nfds].fd = sd;
fds[nfds].events = POLLIN;
nfds++;
while(1){
result = poll(fds, nfds, -1);
printf(". ");
switch(result) {
case 0:
printf("timeout\n");
break;
case -1:
printf("select");
break;
default:
if (fds[1].revents & POLLIN) {
nclientlen = sizeof(clientaddr);
clientsd = accept(sd, (struct sockaddr*) &clientaddr, &nclientlen);
}
if (fds[0].revents & POLLIN) {
ioctl(0, FIONREAD, &nread);
if (0 == nread) {
printf("keyboard done.\n");
} else {
nread = read(0, buffer, nread);
buffer[nread-1] = 0;
if (strcmp(buffer, "close") == 0) {
if (-1 != clientsd ) {
printf("close client socket.\n");
close(clientsd);
clientsd = -1;
}
} else if (-1 != clientsd) {
write(clientsd, buffer, nread);
printf("send %s to client.\n", buffer);
}
}
}
break;
}
}
}