select() method not returning and hence blocking - c

I am a beginner to network programming. I have made a simple UDP server and UDP client . The client sends messages to the server and the server prints the message .
As soon as the client stopped sending messages , then the recvfrom method was blocked . Hence , I tried to make a non-blocking socket with fcntl and select but it is not working.
Following is my code of my UDP server .
#include "udpserver.h"
void start_udp_server(int PORT)
{
struct sockaddr_in server_addr ;
sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
FD_ZERO(&master_fds);
FD_SET(sock_fd, &master_fds);
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET ;
server_addr.sin_addr.s_addr = htonl(0);
server_addr.sin_port = htons(PORT);
// bind the address with the socket
if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr))<0)
fprintf(stderr , "error binding the socket to the address\n");
else
{
fprintf(stderr , "bind successful...\n");
fflush(stdout);
}
if (fcntl(sock_fd, F_GETFL) & O_NONBLOCK)
{
printf("\nsocket is non-blocking");
}
int r = fcntl(sock_fd, F_SETFL, fcntl(sock_fd, F_GETFL) | O_NONBLOCK);
printf("r = %d",r);
if (r < 0)
{
printf("error making the socket non-blocking %d",r);
}
if (fcntl(sock_fd, F_GETFL) & O_NONBLOCK)
{
printf("\nsocket is non-blocking");
}
fprintf(stderr , "server listening on port %d %s\n",ntohs(server_addr.sin_port) ,inet_ntoa(server_addr.sin_addr));
fflush(stdout);
}
int receive_udp_msg()
{
socklen_t lengthOfClientAddress = sizeof(client_addr);
int activity = 0 ;
int l = 0 ;
FD_ZERO(&read_fds);
memcpy(&read_fds, &master_fds, sizeof(master_fds));
printf("before select\n");
activity = select(sock_fd + 1 , &read_fds, NULL, NULL, NULL);
printf("after select\n");
if (FD_ISSET(sock_fd, &read_fds))
{
printf("----activity happened on sock_fd\n");
l = (int)recvfrom(sock_fd, buffer, 1000, 0, (struct sockaddr *)&client_addr , &lengthOfClientAddress) ;
printf("received msg\n");
if (l == - 1)
{
fprintf(stderr , "there was error \n");
fflush(stdout);
return -1 ;
}
}
return l ;
}
int main()
{
start_udp_server ;
int l = 0 ;
while(1)
{
l = receive_udp_msg();
if(l > 0 )
print("message received : %s",buffer);
}
}
When the client has stopped sending messages , the program prints before select and after that it does not print anything.

Because you are using a NULL value for your timeout pointer passed to select, the call will block until there is socket activity.
activity = select(sock_fd + 1 , &read_fds, NULL, NULL, NULL);
^
^
This is fully explained in the man pages for select. If you do not want this, provide your call to select with a non-null pointer to a timeval struct populated with the desired timeout value.

Related

c: accept() for non-blocking server

I am writing a tcp server interface in C. In this interface, I would require to listen for command and send periodic outputs through the same sockets. I would think in this case I would need to program my sockets to be non-blocking. Here is my code
#define ERROR -1
#define MAX_CLIENTS 2
#define MAX_DATA 1024
int setNonblocking(int fd)
{
int flags;
#if defined(O_NONBLOCK)
if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
flags = 0;
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
#else
flags = 1;
return ioctl(fd, FIOBIO, &flags);
#endif
}
int main()
{
int lsock;
struct sockaddr_in saddr;
short int port;
char buffer[MAX_DATA];
int socketOption=1;
int LISTENQ =1;
/// creating sockets
if ( (lsock = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
{
printf(" Error: sockets creation \n");
return -1;
}
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
saddr.sin_port = htons(2222);
setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &socketOption, sizeof(socketOption));
setNonblocking(lsock);
if ( bind(lsock, (struct sockaddr *) &saddr, sizeof(struct sockaddr_in)) < 0 )
{
fprintf(stderr, "ECHOSERV: Error calling bind()\n");
return -1;
}
if ( listen(lsock, LISTENQ) < 0 )
{
fprintf(stderr, "ECHOSERV: Error calling listen()\n");
return -1;
}
bool running = true;
bool bConnected = true;
while ( running )
{
int csock;
time_t start = time(NULL);
time_t now;
if ( (csock = accept(lsock, NULL, NULL) ) < 0 )
{
int errno_s = errno;
printf("The error is %d \n", errno_s);
fprintf(stderr, "ECHOSERV: Error calling accept()\n");
return -1;
}
else
{
bConnected =true;
}
while(bConnected)
{
int n;
if((n=recv(lsock, buffer, MAX_DATA, 0)) > 0)
{
printf("Command Handling \n");
}
if(now - start == 100)
{
printf("Data Sending \n");
}
}
return 0;
}
The program always run into error whenever accept() is being called, I wonder why csock always return -1? I then tried to print out the errno. The errno read 11, which seems to be EAGAIN ( telling to try again ). So should I ignore this error?
I did think about other method to achieve what I want eg using select() and a set of file sockets... but somehow i think it might run into problem
Need your opinion and help on this
REgards
See the accept man page:
If no pending connections are present on the queue, and the socket is not marked as nonblocking, accept() blocks the caller until a connection is present. If the socket is marked nonblocking and no pending connections are present on the queue,
accept() fails with the error EAGAIN or EWOULDBLOCK.
You can use select() to test for data on a listening socket, and then call accept() only when it actually has data, ie a pending connection.

Connection refused in socket programming in c linux

I have wrote simple socket programming in c in for Handle multiple socket connections client and sever.
But when I run it, client showed that connection refused error.
Server side
/**
Handle multiple socket connections with select and fd_set on Linux
*/
#include <stdio.h>
#include <string.h> //strlen
#include <stdlib.h>
#include <errno.h>
#include <unistd.h> //close
#include <arpa/inet.h> //close
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h> //FD_SET, FD_ISSET, FD_ZERO macros
#define TRUE 1
#define FALSE 0
#define PORT 8889
int main(int argc , char *argv[])
{
int opt = TRUE;
int master_socket , addrlen , new_socket , client_socket[30] , max_clients = 30 , activity, i , valread , sd;
int max_sd;
struct sockaddr_in address;
char buffer[1025]; //data buffer of 1K
//set of socket descriptors
fd_set readfds;
//a message
char *message = "ECHO Daemon v1.0 \r\n";
//initialise all client_socket[] to 0 so not checked
for (i = 0; i < max_clients; i++)
{
client_socket[i] = 0;
}
//create a master socket
if( (master_socket = socket(AF_INET , SOCK_STREAM , 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
//set master socket to allow multiple connections , this is just a good habit, it will work without this
if( setsockopt(master_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 )
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
//type of socket created
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
//bind the socket to localhost port 8888
if (bind(master_socket, (struct sockaddr *)&address, sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
printf("Listener on port %d \n", PORT);
//try to specify maximum of 3 pending connections for the master socket
if (listen(master_socket, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
//accept the incoming connection
addrlen = sizeof(address);
puts("Waiting for connections ...");
while(TRUE)
{
//clear the socket set
FD_ZERO(&readfds);
//add master socket to set
FD_SET(master_socket, &readfds);
max_sd = master_socket;
//add child sockets to set
for ( i = 0 ; i < max_clients ; i++)
{
//socket descriptor
sd = client_socket[i];
//if valid socket descriptor then add to read list
if(sd > 0)
FD_SET( sd , &readfds);
//highest file descriptor number, need it for the select function
if(sd > max_sd)
max_sd = sd;
}
//wait for an activity on one of the sockets , timeout is NULL , so wait indefinitely
activity = select( max_sd + 1 , &readfds , NULL , NULL , NULL);
if ((activity < 0) && (errno!=EINTR))
{
printf("select error");
}
//If something happened on the master socket , then its an incoming connection
if (FD_ISSET(master_socket, &readfds))
{
if ((new_socket = accept(master_socket, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
//inform user of socket number - used in send and receive commands
printf("New connection , socket fd is %d , ip is : %s , port : %d \n" , new_socket , inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
//send new connection greeting message
if( send(new_socket, message, strlen(message), 0) != strlen(message) )
{
perror("send");
}
puts("Welcome message sent successfully");
//add new socket to array of sockets
for (i = 0; i < max_clients; i++)
{
//if position is empty
if( client_socket[i] == 0 )
{
client_socket[i] = new_socket;
printf("Adding to list of sockets as %d\n" , i);
break;
}
}
}
//else its some IO operation on some other socket :)
for (i = 0; i < max_clients; i++)
{
sd = client_socket[i];
if (FD_ISSET( sd , &readfds))
{
//Check if it was for closing , and also read the incoming message
if ((valread = read( sd , buffer, 1024)) == 0)
{
//Somebody disconnected , get his details and print
getpeername(sd , (struct sockaddr*)&address , (socklen_t*)&addrlen);
printf("Host disconnected , ip %s , port %d \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
//Close the socket and mark as 0 in list for reuse
close( sd );
client_socket[i] = 0;
}
//Echo back the message that came in
else
{
//set the string terminating NULL byte on the end of the data read
buffer[valread] = '\0';
send(sd , buffer , strlen(buffer) , 0 );
}
}
}
}
return 0;
}
Client side
// Client side C/C++ program to demonstrate Socket programming
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#define PORT 8889
int main(int argc, char const *argv[])
{
int sock = 0, valread;
struct sockaddr_in serv_addr;
char *hello = "Hello from client";
char buffer[1024] = {0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
send(sock , hello , strlen(hello) , 0 );
printf("Hello message sent\n");
valread = read( sock , buffer, 1024);
printf("%s\n",buffer );
return 0;
}
When I compile and run the code getting Connection refused
Compile
gcc server1.c -o server1
gcc client2.c -o client2
Run
./client2 127.0.0.1
Client Error: Connection Failed.: Connection refused
binded successfully

TCP Server Crash

I am just wondering why this crashes when a client connects?? Its supposed to be a simple TCP server that when the client connects and sends a string, the server responds with the number of A's in the string. The server crashes as soon as the client types a letter in.
#include<io.h>
#include<stdio.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
int main(int argc , char *argv[])
{
WSADATA wsa;
SOCKET s , new_socket, master;
struct sockaddr_in server , address;
int c, valread;
char *message = "Welcome to Marshall's TCP Server!!";
int MAXRECV = 1024;
char *buffer;
char AmmtA = 'a';
char AmmtB = 'A';
int count = 0, x;
fd_set readfds;
buffer = (char*) malloc((MAXRECV + 1) * sizeof(char));
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.\n");
//Create a socket
if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 9000 );
//Bind
if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done");
//Listen to incoming connections
listen(s , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
while( (new_socket = accept(s , (struct sockaddr *)&address, &c)) != INVALID_SOCKET )
{
puts("Connection accepted");
send(new_socket , message , strlen(message) , 0);
valread = recv( new_socket , buffer, MAXRECV, 0);
if( valread == SOCKET_ERROR)
{
int error_code = WSAGetLastError();
if(error_code == WSAECONNRESET)
{
//Somebody disconnected , get his details and print
printf("Host disconnected unexpectedly , ip %s , port %d \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
//Close the socket and mark as 0 in list for reuse
closesocket( s );
}
else
{
printf("recv failed with error code : %d" , error_code);
}
}
if ( valread == 0)
{
//Somebody disconnected , get his details and print
printf("Host disconnected , ip %s , port %d \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
//Close the socket and mark as 0 in list for reuse
closesocket( s );
}
else
{
for (x = 0; buffer[x] != '\0'; x++) {
if (buffer[x] == AmmtA || buffer[x] == AmmtB)
count++;
}
char feedback[150];
sprintf(feedback, "There is %d A's in your string", count);
feedback[MAXRECV] = '\0';
printf("%s:%d - %s \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port), buffer);
send( s , feedback , MAXRECV , 0 );
}
free(buffer);
}
if (new_socket == INVALID_SOCKET)
{
printf("accept failed with error code : %d" , WSAGetLastError());
return 1;
}
closesocket(s);
WSACleanup();
return 0;
}
10057 - WSAENOTCONN - Socket is not connected.
The send call is correct and it uses new_socket. But the recv call uses socket/sd "s". The recv call should also use new_socket.
The error 10057 is returned because s is only bound to the local end point and not connected with the remote end whereas the new socket returned by the accept connected to the remote end.
for (x = 0; buffer[x] != '\0'; x++) {
if (buffer[x] == AmmtA || buffer[x] == AmmtB)
count++;
}
Why are you comparing buffer[x] to 0. There's no special reason any particular entry in the buffer should be zero, and this can easily read off the end of the buffer. Perhaps you think buffer contains a string. But it doesn't. It contains whatever you read from the socket, and it has no special format or terminator.
Fortunately, you do know the number of bytes you read. You stored that in valread, so you want:
for (x = 0; x < valread; x++) {

client makes multiple connections to server

I have updated my code to this based on research:
while (number_of_connections--) {
client_sock = socket(AF_INET , SOCK_STREAM , 0);
if (connect(client_sock , (struct sockaddr *)&server , sizeof(server)) < 0)
{
perror("connect failed. Error");
}
printf("socket %d created\n", client_sock);
pthread_t sniffer_thread;
new_sock = malloc(1);
*new_sock = client_sock;
if( pthread_create( &sniffer_thread , NULL , connection_handler , (void*) new_sock) < 0)
{
perror("could not create thread");
return 1;
}
}
Then I'm handling it with this function:
void *connection_handler(void *socket_desc)
{
//Get the socket descriptor
int sock = *(int*)socket_desc;
int read_size, cursor;
char *message , client_message[2000];
//Send some messages to the client
char handshakeBuf[sizeof(handshake)];
memcpy(handshakeBuf, &handshake, sizeof(handshake));
handshake.a++;
handshake.c = 0xac;
handshake.d = 0x0d;
//Send some data
if( send(sock , handshakeBuf , sizeof(handshakeBuf) , 0) < 0)
{
puts("Send failed");
}
//keep communicating with server
while(1)
{
//Receive a reply from the server
if( recv(sock , client_message , 2000 , 0) < 0)
{
puts("recv failed");
break;
}
puts(client_message);
}
close(sock);
return 0;
}
Now my problem is why does it suddenly stop when it reaches the 4th connection?
Original Question
I am trying to write my first C client. I needed to create 4 connections to the server from one client to simulate 4 clients connected where each connection of course has its own handler.
Here is what I have so far:
void connect_to_server(struct sockaddr_in server);
int main(int argc , char *argv[])
{
int number_of_connections, x;
struct sockaddr_in server;
server.sin_addr.s_addr = inet_addr("ipaddress");
server.sin_family = AF_INET;
server.sin_port = htons( port );
number_of_connections = 4;
for ( x = 0; x < number_of_connections; x++ ) {
connect_to_server(server);
}
return 0;
}
void connect_to_server(struct sockaddr_in server) {
int sock;
char message[1000] , server_reply[2000];
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1)
{
printf("Could not create socket");
}
puts("Socket created");
if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0)
{
perror("connect failed. Error");
}
while(1)
{
scanf("%s" , message);
if( send(sock , message , strlen(message) , 0) < 0)
{
puts("Send failed");
}
if( recv(sock , server_reply , 2000 , 0) < 0)
{
puts("recv failed");
break;
}
puts(server_reply);
}
close(sock);
}
Well I'm obviously also new to C. So what is wrong? Should I declare more sockets like: int sockA, sockB, sockC, sockD or I guess its the while loop inside the connect_to_server?
It seems the new version of the implementation uses multithreading: pthread_create(...) function call. But is there an implementation of waiting after the threads are created?
For example, the waiting can be implemented:
by using pthread_join(...) function call;
by waiting for specific key press event using getchar() function call.
Notes
Please be careful with these statements:
if (send(sock, handshakeBuf, sizeof(handshakeBuf), 0) < 0)
if (recv(sock, client_message, 2000 , 0) < 0)
The send() and recv() functions do not guarantee that the entire buffer will be sent/received after one function call. The functions return the actual number of sent/received bytes.
Please introduce analysis of the returned value for send() and recv() function calls: continue sending if not all bytes are sent, continue receiving if "not enough" bytes are received. Also, there is an article related to the some basics of the network programming: TCP/IP client-server application: exchange with string messages.

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