listing multiple interfaces in C program - c

I have a program where i want to forward packet coming from one interface ( VxBridge) & sending it on another interface (ens3:- listing raw sockets ) and vice versa also.
Although my program listens to 3 interfaces
1. VxBridge --> Listing on port 1702
2. ens3 --> listen raw interface
3. tap interface --> tun tap interface
Packet coming from ens3 <--> VxBridge
Problem :-
So program works fine if i have running Wireshark listing on ens3.
If wireshark is stop then Program doesn't listen to packets on ens3. Below is code snippet of program.
Also i believe it is related to somewhat in select() function where waiting of I/O event to occur.
I know i am doing something really wrong here. Any help in redirection would be appreciated.
Below is program :-
main(int argc, char **argv)
{
struct sockaddr_in addr;
struct sockaddr_ll daddr;
fd_set rfds;
fd_set hfds;
int cc,ccd;
struct sockaddr_in from;
size_t fromlen;
int fdmax;
int i;
char* newframe=NULL;
int fdcounter =0;
char *vb = NULL;
int vxSocketfdSet,hwSocketfdSet,tapSocketfdSet;
vxSocketfdSet= hwSocketfdSet=tapSocketfdSet=0;
// Open sockets for L2 device
if (send_to_hw){
if ( ( destsock_fd = socket( PF_PACKET , SOCK_RAW , IPPROTO_RAW) ) < 0){
perror("destsocket creation failed exit");
exit(1);
}
global_fd[fdcounter]=destsock_fd;
fdcounter++;
}
memset(&daddr, 0, sizeof(struct sockaddr_ll));
daddr.sll_family = AF_PACKET;
daddr.sll_protocol = htons(ETH_P_ALL);
daddr.sll_ifindex = if_nametoindex("ens3");
if (bind(destsock_fd, (struct sockaddr*) &daddr, sizeof(daddr)) < 0) {
printf(" ens3 bind failed\n");
close(destsock_fd);
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "ens3");
if (setsockopt(destsock_fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
printf("setsockopt to ens3 failed");
}
/* Open a socket for receiving frames from the Bridge, and forwarding to other l2fwd instances of remote host. */
if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket");
exit(1);
}
global_fd[fdcounter]=sock_fd;
if (vb != NULL)
{
/* create a TAP interface and attach to virtual bridge */
if ((tap_fd = tap_alloc_via_tun_helper(argv[tap_ip_arg], vb)) < 0) {
exit(1);
}
global_fd[fdcounter]=tap_fd;
fdcounter++;
}
memset(&addr, '\0', sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(DE);
if (bind(sock_fd, (void *) &addr, sizeof(addr)) < 0) {
perror("bind");
exit(1);
}
write(1, "> ", 2);
if (pcap)
tv_wait = &pcap_flush_delay;
for (;;) {
FD_ZERO(&rfds);
fdmax = 0;
for ( i =0;i<=fdcounter;i++){
FD_SET(global_fd[i], &rfds);
if (global_fd[i] > fdmax)
fdmax = global_fd[i];
}
if (select(fdmax + 1, &rfds, 0, 0, tv_wait) < 0) {
perror("select");
continue;
}
for (i = 0;i <= fdcounter; i++)
{
if (FD_ISSET(global_fd[i], &rfds)) {
printf ("\nfdset value is %d &&& %d\n",i,global_fd[i]);
if (i==0)
{
printf("hw set ");
hwSocketfdSet = 1;
destsock_fd=global_fd[i];
}
else if (i==1){
printf ("vx Set x");
vxSocketfdSet = 1;
sock_fd=global_fd[i];
}
else if (i ==2){
tapSocketfdSet = 1;
tap_fd=global_fd[i];
}
break;
}
}
if (vxSocketfdSet){
fromlen = sizeof(from);
cc = recvfrom(sock_fd, buf, sizeof(buf), 0, (void *) &from, &fromlen);
if (cc < 0) {
perror("recvfrom");
continue;
}
printf("\nvx frame buf\n");
tempFrom = &from;
forward(buf, cc, &from,0);
}
if (tapSocketfdSet){
printf("tap frame received");
/* Ethernet frame received from local XC. */
if ((cc = read(tap_fd, buf, sizeof(buf))) < 0) {
perror("read");
continue;
}
forward(buf, cc, NULL,0);
}
if (hwSocketfdSet){
printf ("Packet received on ens3 header buffer\n");
if ((ccd = read(destsock_fd, hbuf, sizeof(hbuf))) < 0) {
printf ("error reading");
perror("read");
continue;
}
if (headerbuff != NULL && tempFrom != NULL)
{
printf("headerbuff =%u\n",headerbuff);
printf("headerbuff+ACTUAL_PAYLOAD_OFFSET %u\n",headerbuff+ACTUAL_PAYLOAD_OFFSET);
memcpy(headerbuff+ACTUAL_PAYLOAD_OFFSET,hbuf,ccd+ACTUAL_PAYLOAD_OFFSET);
newframe=headerbuff;
// printing packet with raw buffer
// weird logic is used don't try to understand this one.
// forward(headerbuff, ccd+ACTUAL_PAYLOAD_OFFSET,tempFrom,1);
}
}
vxSocketfdSet=hwSocketfdSet=tapSocketfdSet=0;
}
}

Enabling promiscuous mode on the interface allows it to receive packets for any address. Otherwise the interface ignores packets for foreign addresses. To do this, set the IFF_PROMISC bit in the flags argument to the SIOCSIFFLAGS ioctl call.
Don't forget to turn it off when the program ends.

Related

How to use select and accept to communicate with clients properly?

I have read some example and manual about select and accept but I still can't figure out where I did wrong.
I tried to let server communicate with multiple clients. But when I execute server first, then execute client, server will immediately cause segmentation fault( when i == sockfd in server.c). And I tried to print some strings to check which statement cause wrong, it even no print anything after if (i == sockfd). So I really have no idea how to move on, are there any suggestion?
Server.c
char inputBuffer[140] = {};
char message[] = {"Hi,this is server.\n"};
int sockfd = 0,forClientSockfd = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
printf("Fail to create a socket.");
}
//socket creation
struct sockaddr_in serverInfo,clientInfo;
socklen_t addrlen = sizeof(clientInfo);
serverInfo.sin_family = PF_INET;
serverInfo.sin_addr.s_addr = INADDR_ANY;
serverInfo.sin_port = htons(PORT);
bind(sockfd,(struct sockaddr *)&serverInfo,sizeof(serverInfo));
listen(sockfd,5);
fd_set active_fd_set, read_fd_set;
int i;
struct sockaddr_in clientname;
size_t size;
/* Initialize the set of active sockets. */
FD_ZERO (&active_fd_set);
FD_SET (sockfd, &active_fd_set);
int fd_max = sockfd;
while (1)
{
/* Block until input arrives on one or more active sockets. */
//FD_ZERO (&active_fd_set);
//FD_SET (sockfd, &active_fd_set);
read_fd_set = active_fd_set;
if (select (fd_max+1, &read_fd_set, NULL, NULL, NULL) < 0)
{
printf("select fail\n");
}
/* Service all the sockets with input pending. */
for (i = 0; i <= fd_max; ++i)
{
//printf("%d\n",i);
if (FD_ISSET (i, &read_fd_set))
{
//printf("inner :%d %d\n",i,sockfd);
if (i == sockfd)
{
/* Connection request on original socket. */
//printf("A");
int new;
size = sizeof (clientname);
new = accept (sockfd,(struct sockaddr *) &clientname,&size);
if (new < 0)
{
printf("accept fail\n");
}
else
{
printf (
"Server: connect from host %s, port %hd.\n",
inet_ntoa (clientname.sin_addr),
ntohs (clientname.sin_port));
FD_SET (new, &active_fd_set);
if(new > fd_max)
{
fd_max = new;
}
}
}
else
{
/* Data arriving on an already-connected socket. */
if (read_from_client (i) < 0)
{
close (i);
FD_CLR (i, &active_fd_set);
}
}
}
}
}
return 0;
}
int read_from_client (int filedes)
{
char buffer[140];
int nbytes;
nbytes = recv (filedes, buffer, sizeof(buffer),0);
if (nbytes < 0)
{
/* Read error. */
perror ("read");
exit (EXIT_FAILURE);
}
else if (nbytes == 0)
/* End-of-file. */
return -1;
else
{
/* Data read. */
printf ("Server: got message: `%s'\n", buffer);
return 0;
}
}
client.c
int sockfd = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
printf("Fail to create a socket.");
}
//socket connnection
struct sockaddr_in info;
bzero(&info,sizeof(info));
info.sin_family = PF_INET;
//localhost test
info.sin_addr.s_addr = inet_addr(LOCALHOST);
info.sin_port = htons(PORT);
int err;
char *p;
//Send a message to server
err = connect(sockfd,(struct sockaddr *)&info,sizeof(info));
if(err==-1)
printf("Connection error");
while(1)
{
char message[140];
char receiveMessage[140] = {};
fgets(message,140,stdin);
//scanf("%*[^\n]",message);
//printf("%s",message);
/*if(p=strchr(message,'\n')){
*p = 0;
}else{
scanf("%*[^\n]");
scanf("%c");
}
fgets(message,140,stdin);*/
//scanf("%s",message);
send(sockfd,message,sizeof(message),0);
//printf("RCV");
//recv(sockfd,receiveMessage,sizeof(receiveMessage),0);
//printf("%s\n",receiveMessage);
}
thanks !!

Connection Refused even after adding a new Firewall rule

I am trying to connect to my local UNIX server i made from another remote device. the Server is up and listening to the port i specified. i also added a new firewall rule to open that port but still my client cannot connect. it shows ERROR CONNECTION REFUSED
here is my server code
int main() {
int fd, i,svclient,rval,msg;
int clients[10], num_clients;
fd_set read_set,write_set;
char buf[100];
struct sockaddr_in addr;
if ( (fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket error");
exit(-1);
}
bzero((char *) &addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(4001);
//strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);
//strcpy(addr.sun_path, NAME);
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
perror("bind error");
exit(-1);
}
printf("Bind complet...\n");
if (listen(fd, 20) == -1) {
perror("listen error");
exit(-1);
}
num_clients = 0;
int size = sizeof(fd);
while (1) {
int clientfd;
struct sockaddr_in client_addr;
int addrlen=sizeof(client_addr);
FD_ZERO(&read_set);
FD_SET(fd, &read_set);
for (i = 0; i < num_clients; i++) { //at first this part will not excute
FD_SET(clients[i], &read_set);
}
select(fd + num_clients + 1, &read_set, NULL, NULL, NULL);
if (FD_ISSET(fd, &read_set)) {
if ( (clients[num_clients++] = accept(fd,(struct sockaddr*)&client_addr,&addrlen)) == -1) {
perror("accept error");
continue;
}
/*printf("incoming message..................... !\n \n");*/
printf("%s:%d connected\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
}
for (i = 0; i < num_clients; i++) {
if (FD_ISSET(clients[i], &read_set)) {
msg = read(clients[i], buf, sizeof(buf));
if(msg > 0){
buf[msg] = 0;
int savedclnt = clients[i];
printf("%s \n \n", buf);
/*for(int p=0;p<num_clients;p++)
{
if( clients[p]!= savedclnt){
write(clients[p],buf,msg);
}
}*/
}
}
}
}
}
and my client
int main( )
{
struct uci_context *uci;
uci = uci_init();
int sockfd;
int ret;
struct sockaddr_in dest;
struct addrinfo hint, *res = NULL;
struct hostent *host;
char *hostip;
char *string;
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
{
puts("Unble to create socket");
exit(1);
}
hostip = ucix_get_option(uci, "pack_mon", "pack_monitoring", "address");
string = ucix_get_option(uci, "pack_mon", "pack_monitoring", "port");
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(atoi(string));
memset(&hint, '\0', sizeof hint);
hint.ai_family = PF_UNSPEC;
hint.ai_flags = AI_NUMERICHOST;
printf(" %s- %s\n", hostip, string );
if(isdigit(hostip[0])){
ret = getaddrinfo(hostip, NULL, &hint, &res);// this is more efficient than inet_addr
if (ret) {
exit(1);
}
}else if( (host = gethostbyname(hostip)) != 0){
memcpy((char*)&dest.sin_addr , (char*)host->h_addr , (sizeof dest.sin_addr)+1);
}else{
exit(1);
printf("cannot resolve ip address");
}
if ( connect(sockfd, (struct sockaddr *)&dest, sizeof(dest)) < 0 )
{
perror("ERROR Connecting" );
exit(1);
}else{
printf("Port number %s is open.....\n",string);
}
char *message;
message = "help";
write(sockfd,message,strlen(message));
close(sockfd);
freeaddrinfo(res);
return 0;
}
FIREWALL RULE
sudo iptables -I INPUT -p tcp --dport 4001 -j ACCEPT
Error is :
192.168.10.155- 4001
ERROR Connecting: Connection refused
and this logs are coming from this codes :
printf(" %s- %s\n", hostip, string );
perror("ERROR Connecting");
exit(1);
Your client has no code to specify the IP address it wants to connect to. All the code that could do that has been commented out.
Update: Now your bug is here:
strncpy((char*)&dest.sin_addr , (char*)host->h_addr , sizeof dest.sin_addr);
The strncpy function is only suitable for C-style strings. You need to use memcpy or something similar. This will only copy part of the IP address if any octet other than its last one (in network byte order) is zero.
Update: Now your bug is here:
printf("%d\n", connect(sockfd, (struct sockaddr *)&dest, sizeof(dest)) < 0);
perror("hmmmm" );
exit(1);
This calls connect, then calls printf and then calls perror. The problem is, the call to printf can modify errno even if it succeeds. Thus your call to perror can print a totally irrelevant error message.

server can't send message to Client over Socket in C

Hi I'm writing 2 Programs (Server, Client) which should communicate with each other over sockets. The Client is able to send its first message to the server with no problem, but when the server tries to answer, the client receives just an empty msg: recv(...) is 0.
The server suddenly stops after the send(...) function is called.
Here is my Code:
Server:
/* Create a new TCP/IP socket `sockfd`, and set the SO_REUSEADDR
option for this socket. Then bind the socket to localhost:portno,
listen, and wait for new connections, which should be assigned to
`connfd`. Terminate the program in case of an error.
*/
struct sockaddr_in sin,
peer_addr;
//-----gen socket-----//
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
bail_out(EXIT_PARITY_ERROR, "could not create Socket");
//-----bind-----//
memset(&sin, 0, sizeof (sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(options.portno);
sin.sin_addr.s_addr = INADDR_ANY;
if (bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0)
bail_out(EXIT_PARITY_ERROR, "Failed to bind to Port");
//-----listen-----//
if (listen(sockfd, 5) < 0)
bail_out(EXIT_PARITY_ERROR, "Server can't accepted connection");
//-----accept-----//
int sock_len = sizeof peer_addr;
if ((connfd = accept(sockfd, (struct sockaddr*)&peer_addr, (socklen_t *)&sock_len)) < 0) //fragen
bail_out(EXIT_PARITY_ERROR, "Can't accept connection to Client");
/* accepted the connection */
//Some other Code which has nothing to do with my Error!
/* read from client (WORKS FINE!!)*/
if (read_from_client(connfd, &buffer[0], READ_BYTES) == NULL) {
if (quit) break; /* caught signal */
bail_out(EXIT_FAILURE, "read_from_client");
}
request = (buffer[1] << 8) | buffer[0];
DEBUG("Round %d: Received 0x%x\n", round, request);
/* compute answer */
correct_guesses = compute_answer(request, buffer, options.secret);
if (round == MAX_TRIES && correct_guesses != SLOTS) {
buffer[0] |= 1 << GAME_LOST_ERR_BIT;
}
DEBUG("Sending byte 0x%x\n", buffer[0]);
/* send message to client */
if (send_to_client(sockfd, &buffer[0], WRITE_BYTES) == NULL) { //Error in this Method!
if (quit) break; /* caught signal */
bail_out(EXIT_FAILURE, "can't send message!");
}
Methods:
static uint8_t *send_to_client(int fd, uint8_t *buffer, size_t n)
{
/* loop, as packet can arrive in several partial reads */
size_t bytes_send = 0;
do {
ssize_t r = send(fd, buffer + bytes_send, n - bytes_send, 0); //Program stops HERE!
printf("%d\n", (int)r); //This and the following lines will not be executed!
if (r <= 0) {
return NULL;
}
bytes_send += r;
} while (bytes_send < n);
if (bytes_send < n) {
return NULL;
}
return buffer;
}
Client: (Might be usefull)
sockfd = cnt_to_server(argv[1], argv[2]);
uint8_t buffer;
uint16_t msg_buffer;
do
{
msg_buffer = generate_msg(&msg);
printf("Sending byte 0x%x\n", msg_buffer);
if (send_to_server(sockfd, &msg_buffer, WRITE_BYTES) == NULL) //works
error_exit(EXIT_FAILURE, "can't send message!");
if (read_from_server(sockfd, &buffer, READ_BYTES) == NULL) //NULL
error_exit(EXIT_FAILURE, "can't read message!");
printf("received byte 0x%x\n", buffer);
} while (game_continue(buffer, &msg));
(void)close(sockfd);
Methods:
uint8_t* read_from_server(int fd, uint8_t *buffer, int n)
{
/* loop, as packet can arrive in several partial reads */
size_t bytes_recv = 0;
do {
ssize_t r;
r = recv(fd, buffer + bytes_recv, n - bytes_recv, 0); //0
printf("%d\n", (int)r);
if (r <= 0) {
return NULL;
}
bytes_recv += r;
} while (bytes_recv < n);
if (bytes_recv < n) {
return NULL;
}
return buffer;
}
int cnt_to_server(const char *par_server, const char *par_port)
{
struct sockaddr_in server;
struct hostent *hp;
int sockfd;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
error_exit(EXIT_FAILURE, "could not create Socket");
server.sin_family = AF_INET;
if ((hp = gethostbyname(par_server)) == 0)
error_exit(EXIT_FAILURE, "host error!");
memcpy(&server.sin_addr, hp->h_addr, hp->h_length);
server.sin_port = htons(parse_port(par_port));
if (connect(sockfd, (struct sockaddr*) &server, sizeof server) < 0)
error_exit(EXIT_FAILURE, "could not connect!");
return sockfd;
}
Thx for helping me out with this!
Change
if (send_to_client(sockfd, &buffer[0], WRITE_BYTES) == NULL)
to
if (send_to_client(connfd, &buffer[0], WRITE_BYTES) == NULL)
The solution is to use connfd (File descriptor for connection socket) instead of sockfd:
/* read from client */
if (read_from_client(connfd, &buffer[0], READ_BYTES) == NULL) {
if (quit) break; /* caught signal */
bail_out(EXIT_FAILURE, "read_from_client");
}

Why isn't my C socket server recieving data

I've set up a very simple C socket server, there are two files.
main.c:
#include "socket_server.h"
#include "main.h"
int main (int argc, char* argv[])
{
start_socket_server(SOCKET_SERVER_PORT);
while (1)
{
update_clients();
}
return 0;
}
socket_server.c:
#include "socket_server.h"
int listen_fd, fdmax, newfd, nbytes, i, j, k;
char buf[256];
fd_set master;
fd_set read_fds;
struct timeval tv;
void start_socket_server(int port)
{
struct sockaddr_in servaddr;
FD_ZERO(&master);
FD_ZERO(&read_fds);
bzero( &servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port = htons(port);
tv.tv_sec = 0;
tv.tv_usec = 100;
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
listen(listen_fd, 10);
FD_SET(listen_fd, &master);
fdmax = listen_fd;
}
void update_clients()
{
read_fds = master;
select(fdmax+1, &read_fds, NULL, NULL, &tv);
for(i = 0; i<= fdmax; i++)
{
if (FD_ISSET(i, &read_fds))
{
if (i == listen_fd) //new connection
{
newfd = accept(listen_fd, (struct sockaddr *) NULL, NULL);
if (newfd != -1)
{
fprintf(stderr, "New connection!");
FD_SET(newfd, &master);
if (newfd > fdmax) {
fdmax = newfd;
}
}
} else {
nbytes = recv(i, buf, sizeof buf, 0);
if(nbytes <= 0)
{
fprintf(stderr, "Dead");
close(i);
FD_CLR(i, &master);
} else {
for(j = 0; j <= fdmax; j++)
{
if(FD_ISSET(j, &master))
{
if(j != listen_fd && j != i)
{
fprintf(stderr, "%s", buf);
}
}
}
}
}
}
}
}
Then I have a simple flash file to connect to it with the following actionscript:
var socket = new XMLSocket;
socket.connect("12.34.56.78", 8080);
socket.onConnect = function(status) {
if(status) {
trace("connected");
socket.writeUTF("Hello!");
socket.flush();
} else {
trace("couldn't connect");
}
};
If I run the server, then my actionscript, I would expect the following:
Server sits and waits
Flash file starts
Server says "New connection!" and flash file says "connected"
Server says "Hello!".
Only 1-3 happen. "Hello!" is never output to my terminal. In fact as best I can tell this block:
nbytes = recv(i, buf, sizeof buf, 0);
if(nbytes <= 0)
{
fprintf(stderr, "Dead");
close(i);
FD_CLR(i, &master);
} else {
for(j = 0; j <= fdmax; j++)
{
if(FD_ISSET(j, &master))
{
if(j != listen_fd && j != i)
{
fprintf(stderr, "%s", buf);
}
}
}
}
Is never executed at all (except for when I close my flash file and the server prints "Dead".
What's going on? Why can't I see the data sent from flash? I've managed to send data TO flash, but I haven't been able to receive any FROM it. Also this is being run from within flash, so there is no need to worry about policy files at this stage.
You need to set all your sockets to be non-blocking. For example,
void start_socket_server(int port)
{
struct sockaddr_in servaddr;
int val;
FD_ZERO(&master);
FD_ZERO(&read_fds);
bzero( &servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port = htons(port);
tv.tv_sec = 0;
tv.tv_usec = 100;
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == ioctl(listen_fd, FIONBIO, (val = 1, &val)))
{
perror("ioctl failed!\n");
goto ERROR; /* TODO: or however else you want to deal with errors */
}
bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
listen(listen_fd, 10);
FD_SET(listen_fd, &master);
fdmax = listen_fd;
}
...
if (i == listen_fd) //new connection
{
newfd = accept(listen_fd, (struct sockaddr *) NULL, NULL);
if (newfd != -1)
{
int val;
fprintf(stderr, "New connection!");
if (-1 == ioctl(newfd, FIONBIO, (val = 1, &val)))
{
perror("ioctl failed!\n");
goto ERROR; /* TODO: or however else you want to deal with errors */
}
FD_SET(newfd, &master);
if (newfd > fdmax) {
fdmax = newfd;
}
}
} else {
nbytes = recv(i, buf, sizeof buf, 0);
if(nbytes <= 0)
{
fprintf(stderr, "Dead");
close(i);
FD_CLR(i, &master);
} else {
fprintf(stdout, "Received %d bytes: '%s'\n", nbytes, buf);
}
}
You should also do this on your main listening socket too after you create it initially so that you can't get stuck in a call to accept() somehow.
Also, the way you are outputting read-in data doesn't make much sense. As initially posted, the code would only print out if it had multiple client connections established. Then, when data was read in, it would print it N - 1 times, where N was the number of current client connections.

error in select(): invalid argument

Here is my server code, dont know how i got
failed to select : Invalid argument
its work fine on my mac, but not on linux.
can someone tell me where i did wrong ?
Im just new begynniner in c programming.
server.c
int server(int port){
int request_sd, newfd;
socklen_t clientaddrlen;
fd_set masterList;
fd_set readFd;
int bind_adress = 0, listen_connect = 0;
int fd_max;
int select_client, i;
struct sockaddr_in server_adr;
struct sockaddr_in client_adr;
if (!getcwd(root_path, PATH_LEN))
{
perror("set path");
}
request_sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (request_sd < 0)
{
perror("failed: ");
return -1;
}else printf("create new socket i complete: %d\n", request_sd);
memset(&server_adr, 0 , sizeof (struct sockaddr_in));
server_adr.sin_family = AF_INET;
server_adr.sin_addr.s_addr = INADDR_ANY;
server_adr.sin_port = htons(port);
int activate = 1;
if (setsockopt(request_sd, SOL_SOCKET, SO_REUSEADDR, &activate, sizeof(int)) == -1)
{
perror("setsockopt: ");
return -1;
}
bind_adress = bind(request_sd, (struct sockaddr*) &server_adr, sizeof(struct sockaddr_in));
if (bind_adress < 0 )
{
perror("failed to bind : ");
return -1;
}
listen_connect = listen(request_sd, 10);
if (listen_connect <0)
{
perror("failed to listen : ");
return -1;
}
printf("\nListening for connections on port: %d\n\n", port);
fflush(stdout);
FD_ZERO(&masterList);
FD_ZERO(&readFd);
FD_SET(request_sd, &masterList);
fd_max = request_sd;
while(1){
readFd = masterList;
if((select_client = select(fd_max+1, &readFd, NULL, NULL, NULL)) < 0){
perror("FAILED TO SELECT");
}
for ( i = 0; i <= fd_max; i++)
{
if(FD_ISSET(i,&readFd))
{
if(i == request_sd)
{
newfd = accept(request_sd, (struct sockaddr*) &client_adr,
(socklen_t *) &clientaddrlen);
if (newfd == -1 )
{
perror("failed to accept :");
return -1;
}
FD_SET(newfd, &masterList);
if (newfd > fd_max)
{
fd_max = newfd;
}
Since select() is complaining about a bad parameter, and you are passing only two parameters to it, that means either fd_max is invalid or readFd is invalid. The documentation states:
EINVAL
nfds is negative or the value contained within timeout is invalid.
Since you are not using the timeout parameter, look at your fd_max variable, make sure you are not overflowing it.
Aside from that, you should use fd_copy() instead of readFd = masterList on platforms that support it.
FD_COPY(&masterList, &readFd);
A better option is to use poll() or epoll() instead of select(). It is easier to manage, and it tells you the exact socket(s) that satisfied the wait so you don't have to hunt for them.

Resources