C socket recv() error handling - c

I have a question about recv() function in socket (on linux Raspberri Pi)
Why does my program stops at:
if ((numbytes = recv(fd, odp, 100, 0)) == -1) {
printf("\n error while test recv 1");
perror("recv");
reconnect = 1;
}
Yes, there is an error: "Resource remporarily unavaliable"
When i see:
printf("\n error while test recv 1");
i want to handle reconnect what is made later.
But i see on terminal window that my program stops on:
error while test recv 1
I've tried with:
signal(SIGPIPE, SIG_IGN);
than with:
signal(SIGPIPE, my_function);
but it stops at either.
Some code:
int main(int argc, char *argv[])
{
while(1) {
if(reconnect){
close(fd);
fd = createSocket(argv[1]);
reconnect=0;
}
reconnect = connectionTest(fd);
}
int connectionTest(int *fd) {
numbytes=send(fd, buf, 100,0);
if ((numbytes = recv(fd, reply, 100, 0)) == -1) {
/* HERE IT STOPS */
perror("recv");
printf("\n error while test recv 1");
reconnect = 1;
}
return reconnect;
}
int createSocket(char *server_addr){
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
char s[INET6_ADDRSTRLEN];
int set = 1;
signal(SIGPIPE, SIG_IGN);
printf("connect to: %s", server_addr);
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((rv = getaddrinfo(server_addr, PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and connect to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("client: socket");
continue;
}
else printf("socketd created! \n");
int set = 1;
setsockopt(sockfd, SOL_SOCKET, MSG_NOSIGNAL, (void *)&set, sizeof(int));
if (setsockopt( sockfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&set, sizeof(int)) < 0 )
perror("setsockopt failed \n");
struct timeval timeout;
timeout.tv_sec = 4;
timeout.tv_usec = 0;
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0 )
perror("setsockopt failed \n");
if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0 )
perror("setsockopt failed \n");
printf("Try to connect \n");
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("client: connect");
}
else {
printf("i have connection");
break;
}
}
printf("next1");
if (p == NULL) {
fprintf(stderr, "client: failed to connect\n");
return 2;
}
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
s, sizeof s);
printf("client: connecting to %s\n", s);
freeaddrinfo(servinfo); // all done with this structure
return sockfd;
}

read() shall not return EPIPE.
If a write() is issued against a connection which had been shutdown() or even close()d by the other side the issueing process erros in any case.
A SIGPIPE is raised and if not handled nor is blocked the process will terminate. If SIGPIPE is handled or blocked write() shall return -1 and sets errno to EPIPE.

You program may stop at the recv because it receive the SIGPIPE signal.
If you already try ignoring this signal with signal(SIGPIPE, SIG_IGN) note that you should do this before starting any thread otherwise one may be able to catch the signal before you ignore it.
Also note that you may be able to use setsockopt to configure your socket not to generate a SIGPIPE signal :
int optval = 1;
setsockopt(cs, SOL_SOCK, SO_NOSIGPIPE, (void *)&optval, sizeof(int))
This may not be available in your system.
Your system may also allow you to use the MSG_NOSIGNAL option in the recv to avoid the raise of the SIGPIPE signal :
recv(fd, odp, 100, MSG_NOSIGNAL ))
I think it works on Linux 2.2+
Once the signal is correctly ignored, your recv should return and you should be able to handle the error.
EDIT
Also you may have a XY problem here, if you want to detect if the pipe is broken, you don't actually have to read or write to it, you can use poll, also see : Linux: Checking if a socket/pipe is broken without doing a read()/write().

Related

What's the ideal way to write a code for non-blocking connect()?

What is the ideal way to write code for non-blocking connect?
I saw a reference from the other thread in stackoverflow(Linux, sockets, non-blocking connect) where it mentions checking status of the socket by getsockopt(fd, SOL_SOCKET, SO_ERROR, ...) in the end and I cannot find any reference for why this is needed?
Also, it mentions about handling ECONNREFUSED. How and why it needs to be handled?
Can anyone comment?
Thanks.
int nonblocking_connect() {
int flags, ret, res;
struct sockaddr_in serv_addr;
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1) {
return -1;
}
flags = fcntl(fd, F_GETFL, 0);
if (flags == -1) {
goto end;
}
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
goto end;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(8080);
serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
ret = connect(fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
if (ret == -1) {
fd_set wfd, efd;
struct timeval tv;
if (errno != EINPROGRESS) {
goto end;
}
FD_ZERO(&wfd);
FD_SET(fd, &wfd);
FD_ZERO(&efd);
FD_SET(fd, &efd);
// Set 1 second timeout for successfull connect
tv.tv_sec = 1;
res = select(fd + 1, NULL, &wfd, &efd, &tv);
if (res == -1) {
goto end;
}
// timed-out
if (res == 0) {
goto end;
}
if (FD_ISSET(fd, &efd)) {
goto end;
}
}
return fd;
end:
close(fd);
return -1;
}
The code shown in the example is a bit misleading, in that it's not really implementing a non-blocking connect; rather it is implementing a blocking connect with a one-second timeout. (That is, if the code is working as intended, the nonblocking_connect() function might not return for up to one second when it is called).
That's fine, if that's what you want to do, but the real use-case for a non-blocking connect() is when your event-loop needs to make a TCP connection but also wants to be able to do other things while the TCP connection-setup is in progress.
For example, the program below will echo back any text you type in to stdin; however if you type in a command of the form connect 172.217.9.4 it will start a non-blocking TCP connection to port 443 of the IP address you entered. The interesting thing to note is that while the TCP connection is in progress you are still able to enter text into stdin and the program can still respond (it can even abort the TCP-connection-in-progress and start a new one if you tell it to) -- that can be useful, especially when the TCP connection is taking a long time to set up (e.g. because the server is slow, or because there is a firewall between you and the server that is blocking your client's TCP packets, in which case the TCP connection attempt might take several minutes before it times out and fails)
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char ** argv)
{
printf("Type something and press return to have your text echoed back to you\n");
printf("Or type e.g. connect 172.217.9.4 and press return to start a non-blocking TCP connection.\n");
printf("Note that the text-echoing functionality still works, even when the TCP connection setup is still in progress!\n");
int tcpSocket = -1; // this will be set non-negative only when we have a TCP connection in progress
while(1)
{
fd_set readFDs, writeFDs;
FD_ZERO(&readFDs);
FD_ZERO(&writeFDs);
FD_SET(STDIN_FILENO, &readFDs);
if (tcpSocket >= 0) FD_SET(tcpSocket, &writeFDs);
int maxFD = STDIN_FILENO;
if (tcpSocket > maxFD) maxFD = tcpSocket;
if (select(maxFD+1, &readFDs, &writeFDs, NULL, NULL) < 0) {perror("select"); exit(10);}
if (FD_ISSET(STDIN_FILENO, &readFDs))
{
char buf[256] = "\0";
fgets(buf, sizeof(buf), stdin);
if (strncmp(buf, "connect ", 8) == 0)
{
if (tcpSocket >= 0)
{
printf("Closing existing TCP socket %i before starting a new connection attempt\n", tcpSocket);
close(tcpSocket);
tcpSocket = -1;
}
tcpSocket = socket(AF_INET, SOCK_STREAM, 0);
if (tcpSocket < 0) {perror("socket"); exit(10);}
const char * connectDest = &buf[8];
printf("Starting new TCP connection using tcpSocket=%i to: %s\n", tcpSocket, connectDest);
int flags = fcntl(tcpSocket, F_GETFL, 0);
if (flags == -1) {perror("fcntl"); exit(10);}
if (fcntl(tcpSocket, F_SETFL, flags | O_NONBLOCK) == -1) {perror("fcntl"); exit(10);}
struct sockaddr_in serv_addr; memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(443); // https port
if (inet_aton(connectDest, &serv_addr.sin_addr) != 1) printf("Unable to parse IP address %s\n", connectDest);
int ret = connect(tcpSocket, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
if (ret == 0)
{
printf("connect() succeeded immediately! We can just use tcpSocket now\n");
close(tcpSocket); // but for the sake of this demo, I won't
tcpSocket = -1;
}
else if (ret == -1)
{
if (errno == EINPROGRESS)
{
printf("connect() returned -1/EINPROGRESS: the TCP connection attempt is now happening, but in the background.\n");
printf("while that's going on, you can still enter text here.\n");
}
else
{
perror("connect");
exit(10);
}
}
}
else printf("You typed: %s\n", buf);
}
if ((tcpSocket >= 0)&&(FD_ISSET(tcpSocket, &writeFDs)))
{
// Aha, the TCP setup has completed! Now let's see if it succeeded or failed
int setupResult;
socklen_t resultLength = sizeof(setupResult);
if (getsockopt(tcpSocket, SOL_SOCKET, SO_ERROR, &setupResult, &resultLength) < 0) {perror("getsocketopt"); exit(10);}
if (setupResult == 0)
{
printf("\nTCP connection setup complete! The TCP socket can now be used to communicate with the server\n");
}
else
{
printf("\nTCP connection setup failed because [%s]\n", strerror(setupResult));
}
// Close the socket, since for the purposes of this demo we don't need it any longer
// A real program would probably keep it around and select()/send()/recv() on it as appropriate
close(tcpSocket);
tcpSocket = -1;
}
}
}
As for why you would want to call getsockopt(fd, SOL_SOCKET, SO_ERROR, ...), it's simply to determine whether select() returned ready-for-write on the TCP socket because the TCP-connection-setup succeeded, or because it failed (and in the latter case why it failed, if you care about why)

How to properly terminate a pthread?

I have a tcp echo server that creates a pthread for each client that connects to it. For each connection, I have a variable nbOfClients that increments.
When a client closes its connection, I detect it and decrease the number of clients. However the server keeps thinking that the client it alive and keeps on trying to read/write from the socket. I guessed that it was because of the thread that created the client and I tries to kill the thread with pthread_cancel all to non avail.
I want to kill the pthread associated to a certain client that closes its connection.
How can I go about it?
Here's my code :
static int nbOfClients = 0;
static pthread_t tid;
int main (int argc, char *argv[]) {
int bytes_to_read, arg, listen_sd, new_conn, sockfd, client_len, port;
struct sockaddr_in server, client_addr;
char *bp, buf[BUFLEN];
ssize_t n;
sockfd = 0;
switch(argc) {
case 1:
port = SERVER_TCP_PORT; // Use the default port
break;
case 2:
port = atoi(argv[1]); // Get user specified port
break;
default:
fprintf(stderr, "Usage: %s [port]\n", argv[0]);
exit(1);
}
// Create a stream socket
if ((listen_sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
error("Cannot Create Socket!");
// set SO_REUSEADDR so port can be resused imemediately after exit, i.e., after CTRL-c
arg = 1;
if (setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) == -1)
error("setsockopt");
// Bind an address to the socket
bzero((char *)&server, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = htonl(INADDR_ANY); // Accept connections from any client
if (bind(listen_sd, (struct sockaddr *)&server, sizeof(server)) == -1)
error("bind error");
listen(listen_sd, MAX_CONNECTIONS); ///put a define constant indicating the maximum number of clients #define NB_CLIENTS 3
while (TRUE) {
client_len = sizeof(client_addr);
if ((new_conn = accept(listen_sd, (struct sockaddr *) &client_addr, (socklen_t *)&client_len)) == -1)
error("accept error");
if(new_conn > 0) {
if(nbOfClients < MAX_CONNECTIONS) {
printf("just here\n");
printf(">> Initializing remote address: %s\n", inet_ntoa(client_addr.sin_addr));
nbOfClients++;
fclose(fp);
printf("Connections to date: %u \n",nbOfClients);
printf("make thread\n");
pthread_create(&tid,NULL,&echo, (void *)new_conn);
printf("had thread\n");
}
else {
printf("connection limit reached\n");
if(send(new_conn, "Server full!\n", 13, 0) == -1)
perror("send");
close(new_conn);
}
}
}
return(0);
}
void * echo(void *arg) {
char buf[BUFSIZE]; /* message buffer */
int n, i = 0;
bzero(buf, BUFSIZE);
if(send((int)arg, "Welcome!!\n", 20, 0) == -1)
perror("send");
detect_closed_connection(arg);
while(TRUE) {
n = read((int)arg, buf, BUFSIZE);
/**read: read input string from the client*/
if(n < 0) {
perror("error reading from socket");
}
printf("Server received from client, %d bytes: %s\n", n, buf);
/**write: echo the input string in UPPERCASE back to the client*/
int len = strlen(buf);
for(i = 0; buf[i]; i++)
buf[i] = toupper(buf[i]);
n = write((int)arg, buf, len);
if(n < 0) {
error("ERROR writing to socket");
}
}
}
void detect_closed_connection(void * listenSocket) {
struct pollfd pfd;
pfd.fd = (int)listenSocket;
pfd.events = POLLIN | POLLHUP | POLLRDNORM;
pfd.revents = 0;
while(pfd.revents == 0) {
if(poll(&pfd, 1, 100) > 0) {
// if result > 0, this means that there is either data available on the
// socket, or the socket has been closed
char buffer[32];
if (recv((int)listenSocket, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) {
// if recv returns zero, that means the connection has been closed:
nbOfClients--;
pthread_cancel(tid);
}
}
}
}
Thanks.
You should check read() for returning 0 in the thread servering the client, as read() returns 0 in case the peer (client here) closed the connection.
After this line
n = read((int)arg, buf, BUFSIZE);
add
if (0 == n)
{
fprintf(stderr, "The client closed the connection.\n");
break;
}
Just before the thread function leave you could add the statement to decrement the number of running threads.
Also be aware that nbOfClients is accessed concurently by all the "client"-threads as well as by the main thread, so accessing it shall be protected, for example by using a mutex.
There is another issues, as the call to strlen() on the buffer read expects the buffer to be 0-terminate, which does not necessarily needs ot be the case, even if you sent 0-terminated "strings". read() might very well return the "string" the client sent in more then one part. So loop around read() until the 0-terminator had been received.
Do not make the thread end itself by calling pthread_cancel(), use pthread_exit() instead.

Subsequent Messages not Received

I'm working on a networking project. I can successfully send a single message from my client program over to my server program. However, when I send a second message, the server apparently isn't receiving it. I say this because the client program generates output to suggest that the message was sent, but the server shows no reaction at all.
I'm thinking that I am doing something wrong with either select() or FD_ISSET(). Can anyone see what I am doing wrong? Thanks.
int main(int argc, char *argv[]) {
int sockfd, newfd;
struct sockaddr_in clientAddr;
unsigned int recvLen;
socklen_t addr_size = sizeof clientAddr;
fd_set read_set;
struct timeval tv;
char buffer[BUFFSIZE];
// prepare the address struct for the first client
bzero(&clientAddr,sizeof(clientAddr)); //zero the struct
clientAddr.sin_family = AF_INET; //address family (ipv4)
clientAddr.sin_port = htons(SERVER_PORT); //sets port to network byte order
clientAddr.sin_addr.s_addr = INADDR_ANY;
// create a listening connection to listen for requests from clients
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
fprintf(stdout, "Cannot create socket for client 0.\n");
fprintf(stdout, "Terminating program\n\n");
exit(1);
}
if (bind(sockfd, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0) {
fprintf (stdout, "Binding failed for client 0\n\n");
perror("bind failed");
exit (1);
}
if (listen(sockfd, 10) < 0) {
fprintf (stdout, "Listen() failed\n");
perror("listen() failed");
exit (1);
}
// accept the connection
if ((newfd = accept(sockfd, (struct sockaddr *)&clientAddr, &addr_size)) < 0) {
fprintf(stdout, "Error accepting inbound data from client 0\n");
perror(" accept() failed");
exit(EXIT_FAILURE);
}
// initialize the fd set
FD_ZERO(&read_set);
FD_SET(newfd, &read_set); // adding our socket to the set
tv.tv_sec = 0;
tv.tv_usec = TIMEOUT * 1000;
while (1) {
if ( select(newfd+1, &read_set, NULL, NULL, &tv) == -1) {
perror("select failure");
fprintf(stdout, "errno: %d\n", errno);
exit(EXIT_FAILURE);
}
if (FD_ISSET(newfd, &read_set)) {
bzero(buffer, BUFFSIZE);
recv(newfd, &buffer, BUFFSIZE, 0);
fprintf(stdout, "Received message: %s\n", buffer);
}
}
return 0;
}
After each select you need call FD_ZERO(&read_set); FD_SET(newfd, &read_set); again.
So just move those functions into the loop, before select.

socket is set with O_NONBLOCK, but it seems the calling thread still gets into sleep when sending data sometimes

Client
In fact, my client doesn't recv and process data send from server, just connects to my server.
int netif_msg_client_socket_create(char *sockpath)
{
int addrlen, retval;
int sockfd;
struct sockaddr_un serv;
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if(sockfd < 0) {
PR_ERROR(NETIF_MSG_M, " fatal failure, client msg socket, error is %s, %s %u\n", strerror(errno), __FILE__, __LINE__);
return -1;
}
/* Make client socket. */
memset (&serv, 0, sizeof (struct sockaddr_un));
serv.sun_family = AF_UNIX;
strncpy (serv.sun_path, sockpath, strlen(sockpath));
addrlen = sizeof (serv.sun_family) + strlen(serv.sun_path);
retval = connect(sockfd, (struct sockaddr*)&serv, addrlen);
if(retval < 0)
{
PR_ERROR(NETIF_MSG_M, " fatal failure, client msg connect, error is %s, %s %u\n", strerror(errno), __FILE__, __LINE__);
close(sockfd);
return -1;
}
fcntl(sockfd, F_SETFL, O_NONBLOCK);
return sockfd;
}
2.Server
But my server will try to send some data to the client continuously.
int netif_msg_server_socket_create(char *sockpath)
{
int addrlen, retval;
int sockfd;
struct sockaddr_un serv;
/* First of all, unlink existing socket */
unlink (sockpath);
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if(sockfd < 0)
return -1;
fcntl(sockfd, F_SETFL, O_NONBLOCK);
/* Make server socket. */
memset (&serv, 0, sizeof (struct sockaddr_un));
serv.sun_family = AF_UNIX;
strncpy (serv.sun_path, sockpath, sizeof(serv.sun_path)-1);
addrlen = sizeof (serv.sun_family) + strlen(serv.sun_path);
//printf("sizeof(serv) == %d, addrlen == %d.\r\n", sizeof(serv), addrlen);
retval = bind (sockfd, (struct sockaddr *) &serv, addrlen);
if (retval < 0)
{
close (sockfd); /* Avoid sd leak. */
return -1;
}
retval = listen (sockfd, 20);
if (retval < 0)
{
close (sockfd); /* Avoid sd leak. */
return -1;
}
return sockfd;
}
My server uses select and accepts the connection from my client successfully.
After my server sent 412 packets(96 Bytes each), it seems the server sleeps on send.
Key codes:
printf("Try to send packet(%d bytes) to clientfd %d.\n", MSGCB_DLEN(msgcb), client->acpt_fd);
retval = send(client->acpt_fd, msgcb->data_ptr, MSGCB_DLEN(msgcb), 0);
if(retval != MSGCB_DLEN(msgcb))
{
printf("Send netif notify msg failed[%d].\n", retval);
} else {
printf("Send netif notify msg succeeded.\n");
}
After 412 packets sent to my client and "Try to ..." outputed, nothing goes on, neither "...failed" nor "...succeeded" outputs.
I use getsockopt to fetch the SO_RCVBUF and SO_SNDBUF, there are about 100000Bytes for each of them.
I don't know why, need your help, thanks!
If you want the server socket that is connected to the client to be non-blocking, then you must specifically set the new socket that is returned from accept() to be non-blocking. Your code only sets the listening socket to non-blocking.
You can perform non-blocking I/O with send using the MSG_DONTWAIT flag in the last parameter.
retval = send(client->acpt_fd, msgcb->data_ptr, MSGCB_DLEN(msgcb),
MSG_DONTWAIT);
When performing non-blocking I/O, you need to detect when the return value is signalling you to retry the operation.
if (retval < 0) {
if (errno == EAGAIN) {
/* ... handle retry of send laster when it is ready ... */
} else {
/* ... other error value cases */
}
}

TCP client socket, doesn't block on select()

The following code is a test program wriiten to understand the behaviour of select() call in a TCP client program.
What I observe is that the select is not blocking, instead the program is blocking on recv().
The output is as follows:
Wait on select.
Wait on recv.
...
My question is why the select() returns a success? Ideally it should be blocking on the select() instead of recv().
The TCP server is sending a character string of 15 bytes once in 3 seconds.
int clientfd = -1;
int dummyfd = -1;
int maxfd = -1;
struct sockaddr_in server_addr;
char recv_buf[100] = {0};
int msg_len = 0;
int bytes_recv = 0;
fd_set readfd;
int retval = 0;
/* Open the socket and a dummy socket */.
clientfd = socket(AF_INET, SOCK_STREAM, 0);
dummyfd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == clientfd || -1 == dummyfd)
{
perror("socket error: ");
exit(1);
}
printf("Socket opened : %d\n", clientfd);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(10000);
//server_addr.sin_addr.s_addr = INADDR_ANY;
inet_aton("127.0.0.1", &(server_addr.sin_addr));
memset(&(server_addr.sin_zero), 0, 8);
/* Connect to server */
if(connect(clientfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)))
{
perror("connect error: ");
exit(1);
}
printf("Connect Success\n");
maxfd = (clientfd > dummyfd) ? (clientfd + 1) : (dummyfd + 1);
while(1)
{
FD_ZERO(&readfd);
FD_SET(clientfd, &readfd);
FD_SET(dummyfd, &readfd);
printf("Wait on select\n");
retval = select(maxfd , &readfd, NULL, NULL, NULL);
if(retval <= 0)
{
printf("select failed\n");
}
else
{
printf("Wait on recv\n");
/* ... The process waits here ... */
bytes_recv = recv(clientfd, recv_buf, 100, 0);
printf("%d: Bytes recv = %d\t%s\n", retval, bytes_recv, recv_buf);
memset(recv_buf, 0 ,100);
}
}
close(clientfd);
return 0;
}
Edit: Without dummyfd, the program works as intended.
A follow up question:
When the server is closed abruptly, how to detect this using select()?
Can the program be modified so that is blocks on select() when the server side, say, crashes?
Use the following to be sure it's the clientfd that's returning from the select:
else if (FD_ISSET(clientfd, &readfd)) {
Don't have time to test, but I suspect the dummyfd is returning as an EOF from the select, not the clientfd.
After select() returns, you will want to conditionally receive from clientfd. My guess is that there may be data on dummyfd that is triggering the select to complete, but the receive is on the clientfd.
retval = select(maxfd , &readfd, NULL, NULL, NULL);
if(retval <= 0)
{
printf("select failed\n");
}
else
{
if (FD_ISSET(clientfd, &readfd))
{
bytes_recv = recv(clientfd, recv_buf, 100, 0);
...
}
if (FD_ISSET(dummyfd, &readfd))
{
/* "dummyfd" processing */
}

Resources