I have been trying to do some network programming in Linux but I seem to be stuck again. I don’t seem to get the first argument of the select() function. It should be the last made socket filedescriptor + 1 as far as I know. Mostly the highest filedescriptor contains the number 6. When I add the filedescriptor to the fd_set it suddenly changes to 64–probably because it changes to fd_bytes (correct me if I’m wrong). So, 6+1 does not seem to make it for the select statement because it keeps blocking, but not if I get the fd_bytes from the fd_set. I am very confused about all of this and would like to have some advice on the subject or if someone had it, a good tutorial for sigio that could make things easier.
Server.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <boost/thread/thread.hpp>
#include <sys/time.h>
#include <sys/ioctl.h>
using namespace std;
void error(char *msg,int socket)
{
perror(msg);
close(socket);
exit(1);
}
int main(int argc, char** argv) {
int sockfd, newsockfd, portno, n;
socklen_t clilen;
fd_set readfds;
FD_ZERO(&readfds);
/*
* Sockfd, newsockfd contain values returned by the socket
* portno stores the port number on which the server accepts connections
* clilen stores the size of the address of the client
* n contains the amount of character written of read
*/
char buffer[256];
/* buffer contains the characters read from the socket*/
struct sockaddr_in serv_addr, cli_addr;
/*
* sockaddr_in contains an internet address
* serv_addr contains the servers address
* cli addr contains the clients address
*/
if(argc < 2)
{
fprintf(stderr,"ERROR no port provided");
exit(1);
}
/*
* error if no argument
*/
sockfd = socket(AF_INET,SOCK_STREAM,0);
int opt = 1;
ioctl(sockfd, FIONBIO, &opt);
if(sockfd < 0){
error("ERROR opening socket", sockfd);
}
/*
* socket() creates a new socket
* argument 1 contains the address domain
* argument 2 contains the socket type
* argument 3 contains the protocol should be 0
* socket() returns a reference for itself
*/
bzero((char*) &serv_addr, sizeof(serv_addr));
/* empty the serv_addr variable*/
portno = atoi(argv[1]);
/*converts the port argument from string to int*/
serv_addr.sin_family = AF_INET;
/*set the code for the address family*/
serv_addr.sin_port = htons(portno);
/*htons converts the portno to network bytes and gives it to the server address*/
serv_addr.sin_addr.s_addr = INADDR_ANY;
/*set the server ip to the ip of the running machine*/
if(bind(sockfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR on binding", sockfd);
/*
* bind() binds a socket to an address, in this case the
* addess of the current host
*/
listen(sockfd,5);
/*the listen system call allows the process to listen on the socket for
connections*/
clilen = sizeof(cli_addr);
do{
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
}while(newsockfd < 0);
/*
* accept() lets the system wait until a client connects to the server
*/
FD_SET(newsockfd,&readfds);
int sockcount = pselect(readfds.fds_bits[0] + 1,&readfds,NULL,NULL,NULL,NULL);
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if(n < 0) error("ERROR reading from socket", sockfd);
printf("Here is the message: %s", buffer);
/*
* bzero empties the buffer
* read obviously reads data from the new socket descriptor
*/
n = write(newsockfd,"I got your message",18);
if(n < 0) error("ERROR writing to socket", sockfd);
close(sockfd);
return 0;
}
Some (or all) code might not make sense but that’s mainly because I’m just testing how the code behaves and after that make it multi threaded. The code above works more of less: it can be tested with telnet or with client from the tutorial located here http://www.linuxhowtos.org/C_C++/socket.htm.
I’ve never seed anyone do
readfds.fds_bits[0] + 1before. For your case, you could just usenewsockfd + 1inpselect().