RFComm- client while loop does not end when server is killed - c

I am using RFComm socket. I have a client loop where it does read and write in a loop. When the server exits I guess , the client should also terminate. But client is not terminating. It is not printing "client loop exited". My code is as follows-
void* clientLoop(void* arg)
{
char* server_address = (char*)arg;
printf("\nserver address in clientLoop = %s\n",server_address);
struct sockaddr_rc addr = { 0 };
int s, status;
char gpsMessage[128];
int flag = true;
struct timeval tv;
// allocate a socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
if(s<0) perror("socket error in client loop");
// set the connection parameters (who to connect to)
addr.rc_family = AF_BLUETOOTH;
addr.rc_channel = (uint8_t) 1;
str2ba( server_address, &addr.rc_bdaddr );
tv.tv_sec = 30; // 30 seconds
tv.tv_usec = 0; // microsecs, set to 0 (or ...)
setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv,sizeof(struct timeval));
// connect to server
status = connect(s, (struct sockaddr *)&addr, sizeof(addr));
if(status<0) perror("socket status error in client loop");
// send a message
if( status == 0 ) {
while(flag)
{
sleep(10);
printf("clientLoop did not exited\n");
prepareMessageToSend(gpsMessage);
status = write(s,gpsMessage , strlen(gpsMessage));
if(status == 0) flag=false;
status = read(s,gpsMessage, 128);
if(strcmp(gpsMessage,"Ring"))
{
printf("RING\n");
system("espeak -ven+f3 -k5 -s150 \"I've just picked up a fault in the AE35 unit\"");
}
if(status == 0) flag=false;
}
}
if( status < 0 ) perror("uh oh");
printf("clientLoop exited\n");
close(s);
//return s;
}

Give the socket a timeout
struct timeval tv;
tv.tv_sec = 30; // 30 seconds
tv.tv_usec = 0; // microsecs, set to 0 (or ...)
setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv,sizeof(struct timeval));
if the read cannot be performed within that time, the timeout is triggered.
Also
status = read(s,gpsMessage, 128);
// check status first, or if there is no ambiguity, check only the 4 first chars
if(strncmp(gpsMessage, "Ring", 4))
(in case the message could not be set correctly)

Related

How to use IO multiplexing technology to improve server concurrency performance?

I want to make a server software similar to Apache on windows platforms.
. The client sends data to the specified server port and the server responds accordingly. In order to improve the client access speed, I want to use "select" to improve the performance of the server, but there are many problems in the use process.
Here is my code;
Function "create_server"
This function is used to create the server Socket and set it to non-blocking.
int create_server(char*ip_address,int port) {
WORD sockVersion = MAKEWORD(2, 2);
WSADATA wsaData;
if(WSAStartup(sockVersion, &wsaData) != 0)
{
return 0;
}
int server_socket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
int ret = -1;
struct sockaddr_in addr;
if (server_socket == -1) {
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.S_un.S_addr= INADDR_ANY;
ret = bind(server_socket,(LPSOCKADDR)&addr,sizeof(addr));
if (ret == -1) {
perror("bind error!");
return -2;
}
listen(server_socket,5);
SetBlock(server_socket, 0);
return server_socket;}
Function "SetBlock"
This function is used to change the socket blocking mode.
int SetBlock(int sock, int isblock){
int re = 0;
unsigned long ul = 0;
if (!isblock) ul = 1;
re = ioctlsocket(sock, FIONBIO, (unsigned long*)& ul);
if (re != 0) return 0;
return 1;
}
Function "main"
int main() {
int s = create_server("127.0.0.1",6666);
int client_socket = -1;
struct sockaddr_in clientaddr;
int addrlen = sizeof(clientaddr);
char buf[1025];
int buffersize=1,result=0;
int isread = 0;
fd_set server;
struct timeval timeout;
int fd = 0;
timeout.tv_sec = 3;
timeout.tv_usec = 0;
FD_ZERO(&server);
FD_SET(s, &server);
while (1) {
result = select(FD_SETSIZE, &server, NULL, NULL, NULL);
if (result < 1) {
perror("error!");
exit(1);
}
if (FD_ISSET(s, &server)) {
//if server can be readable and written do this
client_socket = accept(s, (struct sockaddr*) & clientaddr, &addrlen);
while (buffersize > 0) {
buffersize = recv(client_socket, buf, 1024, 0);
buf[buffersize] = '\0';
printf("%s", buf);
if (buffersize < 1024) {
break;
}
}
buffersize = 1;
}
}
return 0;}
As you know, TCP takes some time to establish a connection. I want to use the "select" function to reduce the setup time of multi-client connections. I think the function "accept" is the process of establishing connection between client and server, but how to use IO multiplexing in this process, please help me.
the use of select() will delay all client connections to the server.
suggest a sequence similar to:
create a thread pool
create a sockaddr_in
sock_t serverSock = socket()
bind()
listen()
while( 1 )
{
sock_t clientSock = accept( serverSock, ... )
pass clientSock to available thread and mark thread as 'busy'
}
That way, the communication with a client does not 'hang' on a select(), nor a accept()
in each thread:
while(1)
{
wait until thread marked as 'busy'
sock_t mySocket = passedSocket
perform all communication with the specific client
close( mySocket );
mark thread as 'idle'
}

using setsockopt; read returns 0 not -1 when socket closed from other side [duplicate]

This question already has an answer here:
Can read() function on a connected socket return zero bytes?
(1 answer)
Closed 5 years ago.
I am using TCP socket to connect between devices. I close 1 side of connection-the server side. I am using setsockopt and timeout. Aread call on client socket should return -1 in this case as per my understanding. But it is returning 0. Is there anything I need to modify?
Pasting the client code below.
void* socketClientLoop(void* arg)
{
//struct socketArgs* sockArg = (struct socketArgs *)arg;
char server_address[20] , *strtokResult;
strcpy(server_address,"192.168.43.217"/*sockArg->server_address*/);
printf("\nsocket : server address in clientLoop = %s\n",server_address);
struct sockaddr_in addr = { 0 };
int s, status, distance;
int distanceFromSocket = 0;//sockArg->distance;
char gpsMessage[128], dist[16];
int flag = true, writeFlag = false;
struct timeval tv;
while(true)
{
printf("socket : loop started\n");
flag = true;
// allocate a socket
printf("socket : loop started1\n");
s = socket(AF_INET, SOCK_STREAM, 0);
printf("socket : loop started2\n");
if(s<0) perror("socket error in client loop");
// set the connection parameters (who to connect to)
addr.sin_family = AF_INET;
addr.sin_port = htons(5000);
if(inet_pton(AF_INET, server_address, &addr.sin_addr)<=0)
{
printf("\n socket : inet_pton error occured\n");
return 0;
}
tv.tv_sec = 15; // 30 seconds
tv.tv_usec = 0; // microsecs, set to 0 (or ...)
setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv,sizeof(struct timeval));
// connect to server
status = connect(s, (struct sockaddr *)&addr, sizeof(addr));
if(status<0) perror("socket status error in client loop");
// send a message
if( status == 0 ) {
while(flag)
{
sleep(5);
memset(gpsMessage,0,sizeof(gpsMessage));
status = read(s,gpsMessage, 128);
if(!strncmp(gpsMessage,"connected",9)) writeFlag = true;
else writeFlag = false;
strtokResult = strtok(gpsMessage,":");
if(strtokResult)
{
strtokResult = strtok(0,":");
if(strtokResult)
{
strcpy(dist,strtokResult);
sscanf(dist,"%d",&distance);
}
}
printf("dist = %d\n", distance);
printf("socket : clientLoop did not exited\n");
if(distance == 2*distanceFromSocket)
{
/*pthread_mutex_lock(&fill_mutex);
pthread_cond_signal(&cond_var);
pthread_mutex_unlock(&fill_mutex);*/
}
if(writeFlag)
{
socketPrepareMessageToSend(gpsMessage);
status = write(s,gpsMessage , strlen(gpsMessage));
//if(status < 0) flag=false;
}
//strcpy(gpsMessage,"No Ring");
status = read(s,gpsMessage, 128);
printf("bytes_read %d \n",status);
if(status < 0)
{
printf("set loopflag\n");
flag=false;
writeFlag=false;
}
else
{
writeFlag=true;
printf("ring no ring = %s\n",gpsMessage);
if(!strcmp(gpsMessage,"Ring"))
{
printf("SOCKET RING\n");
system("espeak -ven+f3 -k5 -s150 \"I've just picked up a fault in the AE35 unit\"");
}
else printf("wrongoption\n");
}
}
}
if( status < 0 ) perror("uh oh");
printf("socket : clientLoop exited\n");
close(s);
printf("socket : end of loop\n");
}
}
When a socket is closed from other side, it indicates an End-Of-File, and the read call will return 0. That is the correct behavior.
Refer:
https://linux.die.net/man/2/read

TCP Keep-alive does not detect a dead client

I have added Keep-alive message in server in order to know about client. In my program server is keep on running and sending data to client. My problem is if client disconnect server never come to know that client get disconnected.
Below is the code snippet where i added keepalive
if ((newConnSD = ::accept(sockDesc, NULL, 0)) < 0) {
throw SocketException("Accept failed (accept())", true);
//TIMEOUT SETTING
int buffersize = 4096;
setsockopt(sockDesc, SOL_SOCKET, SO_SNDBUF, (char *)&buffersize, 4);
// KEEP ALIVE IMPLEMENTATION
struct tcp_keepalive alive;
DWORD dwBytesRet = 0;
alive.onoff = TRUE;
alive.keepaliveinterval = 1000;
alive.keepalivetime = 60000;
if (WSAIoctl(sockDesc, SIO_KEEPALIVE_VALS, &alive, sizeof(alive), NULL, 0,
&dwBytesRet, NULL, NULL) == SOCKET_ERROR)
{
printf("WSAIotcl(SIO_KEEPALIVE_VALS) failed; ");
LOG4CXX_INFO(loggerToFile,"WSAIotcl(SIO_KEEPALIVE_VALS) failed ");
cout<<WSAGetLastError()<<endl;
}
else
{
LOG4CXX_INFO(loggerToFile,"WSAIotcl(SIO_KEEPALIVE_VALS) Success ");
cout<<"WSAIotcl(SIO_KEEPALIVE_VALS) Success " <<endl;
}
int optval;
socklen_t optlen = sizeof(optval);
/* Set the option active */
optval = 1;
optlen = sizeof(optval);
if(setsockopt(sockDesc, SOL_SOCKET, SO_KEEPALIVE,(char*)&optval, optlen) < 0) {
cout<<"Error while setting KEEP_ALIVE Message"<<endl;
LOG4CXX_INFO(loggerToFile,"Error while setting KEEP_ALIVE Message");
}
else
{
LOG4CXX_INFO(loggerToFile,"SO_KEEPALIVE set on socket");
cout<<"SO_KEEPALIVE set on socket"<<endl;
}
printf("SIO_KEEPALIVE_VALS set:\n");

How to reduce message dropping in UDP socket communication, using only single port?

I have writter code snippet for UDP Client and server. I am using same port for sending and receiving. My problem is that there are many messages drops at client side, so can someone help me to optimize my code, here is my code for UDP client:
#define SERVERIP "192.168.170.155"
#define SERVERPORT 5000
#define DEVICE_SEND_PORT 5000
#define DEVICE_RECEIVE_PORT 5000
#define BUFFERSIZE 2048
/**For socket file descriptor identification*/
#define S1READY 0x01
int m_SendSocketId;
int m_ReceiveSocketId;
int msgcount;
int socketbuffsize = 1*1024*1024;
/**
* FUNCTION NAME : waitToRead
* Implementation of select and non-blocking socket mechanism
* #param socket Socket that needs to be in select and non blocking mode
* #return Returnd the file descriptors which, returned by select function
*/
int waitToRead(int socket)
{
fd_set fds;
struct timeval timeout;
int rc; // number of file descriptor returned
int result; // result
int fd; // file descriptor
fd=fcntl(socket,F_GETFL,0);
fcntl(socket,F_SETFL,fd | O_NONBLOCK);
// Set time limit.
timeout.tv_sec = 1;
timeout.tv_usec = 0;
// Create a descriptor containing our sockets.
FD_ZERO(&fds);
FD_SET(socket, &fds);
rc = select(sizeof(fds)*8, &fds, NULL, NULL, &timeout);
if (rc==-1)
{
printf("[%s:%d#%s] Select Failed\n",__FILE__, __LINE__,__func__);
return -1;
}
result = 0;
if (rc > 0)
{
if (FD_ISSET(socket, &fds))
result |= S1READY;
}
return result;
}
/**
* FUNCTION NAME : receiveMessage
* This function opens particular port that is defined in the
* Configuration file, and listens on that port.
* #return if there'll be any issue in listening, then it will return
* false otherwise it will return true.
*/
bool receiveMessage()
{
struct sockaddr_in serverAddr; //Information about the Device UDP Server
struct sockaddr_in client_addr; // Information about Qgate Server
char buffer[BUFFERSIZE]; // Buffer to store incoming message
int addr_len; // to store client address length
int serverlen; // to store server address length
int sockResult; // to store result given by waitToRead
int optval = 1;
int receivedByte = 0;
//Open a datagram Socket
if((m_ReceiveSocketId = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
printf("[%s:%d#%s] UDP Client - socket() error\n",__FILE__, __LINE__,__func__);
return false;
}
//Configure Server Address.
//set family and port
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(DEVICE_RECEIVE_PORT);
setsockopt(m_ReceiveSocketId, SOL_SOCKET,SO_REUSEADDR, &optval, sizeof(optval));
/*if (setsockopt(m_ReceiveSocketId, SOL_SOCKET, SO_RCVBUF, &socketbuffsize, sizeof(socketbuffsize)) == -1)
{
printf("Recieve Socket memory Allocation fail\n");
}*/
if((serverAddr.sin_addr.s_addr = INADDR_ANY) == (unsigned long)INADDR_NONE)
{
printf("[%s:%d#%s] Host Not found(%d)\n",__FILE__, __LINE__,__func__,h_errno);
close(m_ReceiveSocketId); // close the socket
return false;
}
if (bind(m_ReceiveSocketId, (struct sockaddr *) &serverAddr,sizeof(struct sockaddr_in)) < 0 )
{
printf("[%s:%d#%s] UDP Client- Socket Bind error=%s\n",__FILE__, __LINE__,__func__,strerror(errno));
close(m_ReceiveSocketId); // close the socket
return false;
}
serverlen = (int )sizeof(serverAddr);
addr_len = sizeof(struct sockaddr);
// Loop and listen for incoming message
while(1)
{
//wait at select to, read
sockResult = waitToRead(m_ReceiveSocketId);
if(sockResult == S1READY)
{
receivedByte = read(m_ReceiveSocketId,buffer,BUFFERSIZE);
buffer[receivedByte] = '\0';
if(receivedByte == -1)
{
printf("[%s:%d#%s] UDP Client - receive error", __FILE__,__LINE__,__func__);
close(m_ReceiveSocketId);
return false;
}
else if(receivedByte > 0)
{
//printf("[%s:%d#%s] received message = %d bytes\n",__FILE__,__LINE__,__func__,(int)strlen(buffer));
printf("count: %d, buffer %s \n", msgcount++, buffer);
}
}
memset(buffer, 0, BUFFERSIZE);
fflush(stdout);
}
close(m_ReceiveSocketId); // close the socket
printf("[%s:%d#%s] Recieve socket closed:%s\n",
__FILE__, __LINE__,__func__, strerror(errno));
return true;
}
bool sendMessage(char *message)
{
struct sockaddr_in serverAddr; //Information about the server
struct sockaddr_in deviceAddr; //Device UDP Client Address for sending message
int optval = 1;
//Open a datagram Socket
if((m_SendSocketId = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
printf("[%s:%d#%s] UDP Client - socket() error\n",__FILE__, __LINE__,__func__);
return false;
}
// Clear out the device struct
memset(&deviceAddr, 0x00, sizeof(struct sockaddr_in));
deviceAddr.sin_family = AF_INET;
deviceAddr.sin_port = htons(DEVICE_SEND_PORT);
setsockopt(m_SendSocketId, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
/*if (setsockopt(m_SendSocketId, SOL_SOCKET, SO_SNDBUF, &socketbuffsize, sizeof(socketbuffsize)) == -1)
{
printf("send Socket memory Allocation fail\n");
}*/
if((deviceAddr.sin_addr.s_addr = INADDR_ANY) == (unsigned long)INADDR_NONE)
{
// in netdb.h
printf("[%s:%d#%s] Host Not found(%d)\n",__FILE__, __LINE__,__func__, h_errno);
close(m_SendSocketId); // close the socket
return false;
}
if (bind(m_SendSocketId, (struct sockaddr *) &deviceAddr,sizeof(struct sockaddr_in)) < 0 )
{
printf("[%s:%d#%s] UDP Client- Socket Bind error=%s\n",__FILE__, __LINE__,__func__,strerror(errno));
close(m_SendSocketId); // close the socket
return false;
}
// Clear out the server struct
memset(&serverAddr, 0x00, sizeof(struct sockaddr_in));
//Configure Server Address.
//set family and port
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(SERVERPORT);
//serverAddr.sin_addr.s_addr = htonl(39898);
if((serverAddr.sin_addr.s_addr = inet_addr(SERVERIP)) == (unsigned long)INADDR_NONE)
{
printf("[%s:%d#%s] Host Not found %d\n",__FILE__, __LINE__,__func__,h_errno);
close(m_SendSocketId);
return false;
}
// Send data to the server.
if( sendto(m_SendSocketId, message,strlen(message) ,0, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0 )
{
printf("[%s:%d#%s] UDP Client - sendto() error=%s \n",__FILE__, __LINE__,__func__,strerror(errno));
close(m_SendSocketId);
return false;
}
close(m_SendSocketId);
return true;
}
int main ()
{
int loop;
char str[10];
msgcount = 1;
pthread_t receiveThread;
if(pthread_create(&receiveThread, NULL,(void *)&receiveMessage, NULL) != 0)
{
printf("[%s:%d#%s] thread create Failed(%s)\n",
__FILE__, __LINE__,__func__, strerror(errno));
return false;
}
for(loop =0; loop < 1000; loop++)
{
sprintf(str,"%4d",loop);
sendMessage(str);
}
pthread_join(receiveThread, NULL);
return 0;
}
Here is the temporary UDP server code, it receives almost above 90% messages and also sends the same, but udpclient is not able to receive the messages.
int main()
{
int sock;
int addr_len, bytes_read, bytes_send;
char recv_data[1024];
int i;
int count=0;
struct sockaddr_in server_addr , client_addr;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(5000);
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero),8);
//client_addr.sin_family = AF_INET;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
if (bind(sock,(struct sockaddr *)&server_addr,sizeof(struct sockaddr)) == -1)
{
perror("Bind");
exit(1);
}
addr_len = sizeof(struct sockaddr);
printf("\nUDPServer Waiting for client on port 5000");
fflush(stdout);
while (1)
{
bytes_read = recvfrom(sock,recv_data,1024,0,(struct sockaddr *)&client_addr, (socklen_t *)&addr_len);
recv_data[bytes_read] = '\0';
if(recv_data[0]!=0x07)
{
recv_data[0] = 0x09;
//client_addr.sin_port = htons(51254);
bytes_send = sendto(sock, recv_data, bytes_read, 0, (struct sockaddr *)&client_addr, (socklen_t)sizeof(client_addr));
if(bytes_send < 0 )
{
perror("send to ");
}
printf("\nNumber %d", ++count);
memset(&recv_data, 0x00, 1024);
}
else
{
printf("Received Keep ALive\n");
}
memset(&client_addr, 0x00, sizeof(struct sockaddr_in));
fflush(stdout);
}
return 0;
}
Any help would be highly appreciated.
Thanks Yuvi
Your code has nothing to do with UDP dropping packets, except possibly that you are sending packets too fast for the network or the receiver. UDP isn't reliable. It drops packets. If your application protocol requires no dropped packets, you have to build in reliability at that level, via an ACK-based or NACK-based protocol with retries.
Or use TCP like everybody else does in this situation.
The problem was in sendMessage Function, here I was recreating socket every time when I need to send message, and I think that takes time. I don't know yet which is calls are blocking but making sending socket resolves my problem. Now the dropping of message is upto 20 to 30 % only.

Enable non-blocking socket

I have a server written in C/C++.
I set the wrapper for the connection as follow:
//START WRAPPER
void Server::init_address(int port)
{
memset(&(this->serv_addr), 0, sizeof(this->serv_addr));
this->serv_addr.sin_family = AF_INET;
this->serv_addr.sin_port = htons(port);
this->serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
}
int Server::w_socket()
{
int retv;
retv = socket(PF_INET, SOCK_STREAM, 0);
//FIXME
//fcntl(retv, F_SETFL, O_NONBLOCK);
if(retv == -1)
{
std::string err_msg(strerror(errno));
err_msg = "[socket] " + err_msg;
throw err_msg;
}
else
{
int reuse_opt = 1;
if(setsockopt(retv, SOL_SOCKET, SO_REUSEADDR, &reuse_opt, sizeof(int))==-1)
{
perror("setsockopt error");
exit(1);
}
return retv;
}
}
void Server::w_bind()
{
int retv;
retv = bind(this->sock_fd,
(struct sockaddr*) &(this->serv_addr),
sizeof(this->serv_addr));
if(retv == -1)
{
std::string err_msg(strerror(errno));
err_msg = "[bind] " + err_msg;
throw err_msg;
}
}
void Server::w_listen()
{
int retv;
retv = listen(this->sock_fd, 3);
if (retv == -1)
{
std::string err_msg(strerror(errno));
err_msg = "[listen] " + err_msg;
throw err_msg;
}
}
int Server::w_accept(struct sockaddr_in* client_addr)
{
int retv;
int socklen = sizeof(sockaddr_in);
retv = accept(this->sock_fd, (struct sockaddr*)client_addr, (socklen_t*)&socklen);
if(retv == -1)
{
std::string err_msg(strerror(errno));
err_msg = "[accept] " + err_msg;
throw err_msg;
}
else
{
return retv;
}
}
int Server::recvtimeout(int s, char *buf, int len, int timeout)
{
fd_set fds;
int n;
struct timeval tv;
// set up the file descriptor set
FD_ZERO(&fds);
FD_SET(s, &fds);
// set up the struct timeval for the timeout
tv.tv_sec = timeout;
tv.tv_usec = 0;
// wait until timeout or data received
n = select(s+1, &fds, NULL, NULL, &tv);
if (n == 0){
return -2; // timeout!
}
if (n == -1){
return -1; // error
}
// data must be here, so do a normal recv()
return recv(s, buf, len, 0);
}
// END WRAPPER
My goal is to enable the non-blocking socket mode.
I've tried to do fcntl(retv, F_SETFL, O_NONBLOCK); like Beej manual said, but I receive the error: [accept] Resource temporarily unavailable
A solution to this problem is using the select function, but I already use it in the recvtimeout function, always like Beej guide said.
So, I don't know how to solve this problem to enable the non-blocking socket mode.
You get the error because the socket is non-blocking.
Either you do a busy loop while you get that error (check errno when accept returns -1 for either EWOULDBLOCK or EAGAIN). The other and recommended solution is to use select to see when the socket is readable, then you can call accept.
Edit: How to do it with select
You need to have an event-loop at a higher level, that checks if the listening socket, or the connected socket(s), can be read from. If the listening socket is readable then you can accept a new connection, and if the connected sockets are readable then you can read from them.
Something like:
for (;;)
{
fd_set readset;
FD_ZERO(&readset);
FD_SET(listening_socket, &readset);
int maxfd = listening_socket;
if (connected_socket >= 0)
{
FD_SET(connected_socket, &readset);
maxfd = max(maxfd, connected_socket);
}
// NULL timeout (5-th argument) means wait until event
select(maxfd + 1, &readset, NULL, NULL, NULL);
if (FD_ISSET(listening_socket, &readset))
{
accept_new_connection(listening_socket);
}
if (connected_socket >= 0 && FD_ISSET(connected_socket, &readset))
{
if (!read_from_socket(connected_socket))
{
close(connected_socket);
connected_socket = -1;
}
}
}
If you have multiple connected sockets, put them in a simple linked list and add/check them in a loop. Remove from list when they are closed.
In your solution, you are using select call for the connection socket, but you are not using the same for listen socket.
If you have changed the listen socket also to non-blocking, then you must use select for listen socket before calling accept.

Resources