Here is a Server implementation with select ()`, and a simple client. It is not the main app, but an example, which may not run. What matters is that infinite loop from server.
The problem appears here: the client sends a (correct) message, receives an (correct) answer from server, and then, when he sends another message, it receives Error: write (): Bad file descriptor.
I checked back in server and he didn't close it. I suspect that the problem either in select () or in server architecture.
EDIT: I test my app on 127.0.0.1, if relevant.
Server
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>
#define PORT 2728
extern int errno;
/* converting client address int char* */
char * conv_addr (struct sockaddr_in address)
{
static char str[25];
char port[7];
strcpy (str, inet_ntoa (address.sin_addr));
bzero (port, 7);
sprintf (port, ":%d", ntohs (address.sin_port));
strcat (str, port);
return (str);
}
int main ()
{
struct sockaddr_in server;
struct sockaddr_in from;
fd_set readfds; //clients which are ready to write
fd_set actfds; //active clients
struct timeval tv;
int sd, client;
int optval=1;
int fd;
int nfds; //max number of descriptors
int len;
if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
{
perror ("[server] Error:socket().\n");
return errno;
}
/*SO_REUSEADDR option*/
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR,&optval,sizeof(optval));
bzero (&server, sizeof (server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl (INADDR_ANY);
server.sin_port = htons (PORT);
if (bind (sd, (struct sockaddr *) &server, sizeof (struct sockaddr)) == -1)
{
perror ("[server] Error:bind().\n");
return errno;
}
if (listen (sd, 5) == -1)
{
perror ("[server] Error:listen().\n");
return errno;
}
FD_ZERO (&actfds);
FD_SET (sd, &actfds);
tv.tv_sec = 1;
tv.tv_usec = 0;
nfds = sd;
printf ("[server] Waiting at port %d...\n", PORT);
fflush (stdout);
/* serving clients... */
while (1)
{
bcopy ((char *) &actfds, (char *) &readfds, sizeof (readfds));
if (select (nfds+1, &readfds, NULL, NULL, &tv) < 0)
{
perror ("[server] Error:select().\n");
return errno;
}
if (FD_ISSET (sd, &readfds))
{
/* preparing client structure */
len = sizeof (from);
bzero (&from, sizeof (from));
client = accept (sd, (struct sockaddr *) &from, &len);
if (client < 0)
{
perror ("[server] Error:accept()\n");
continue;
}
if (nfds < client) /* adjusting max value */
nfds = client;
FD_SET (client, &actfds);
printf("[server] Client with %d descriptor and %s address connected.\n",client, conv_addr (from));
fflush (stdout);
}
/* checking if any client is ready so 'speak' */
for (fd = 0; fd <= nfds; fd++)
{
if (fd != sd && FD_ISSET (fd, &readfds))
{
//receive message from client
//do something
//sent back result
}
}
/* for */
} /* while */
} /* main */
Client
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
extern int errno;
int port;
int main (int argc, char *argv[])
{
int sd;
struct sockaddr_in server;
char msg[100];
if (argc != 3)
{
printf ("[client] Sintax: %s <server_address> <port>\n", argv[0]);
return -1;
}
port = atoi (argv[2]);
if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
{
perror ("[client] Error:socket().\n");
return errno;
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(argv[1]);
server.sin_port = htons (port);
if (connect (sd, (struct sockaddr *) &server,sizeof (struct sockaddr)) == -1)
{
perror ("[client]Error: connect().\n");
return errno;
}
while(1)/*meaning untill user doesn't close the client*/)
{
//here are the functions used to communicate with server. Same in server.
if (write (sd, msg, 100) <= 0)
{
perror ("[client]Error:write().\n");
return errno;
}
if (read (sd, msg, 100) < 0)
{
perror ("[client]Error:read().\n");
return errno;
}
}//while
close (sd);
}//main