Why isn't my C socket server recieving data - c

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.

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 !!

listing multiple interfaces in C program

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.

What can cause `recvfrom()` not to set

So I'm using Unix Domain Socket (datagram) to communicate between two processes on my machine. The client sends queries to the server which is making some calculations and returns the result to the client.
My server receives queries from the client using recvfrom(), and my problem is that on the first time recvfrom() is being called, it does not set struct sockaddr *restrict address which is the address of the sender.
This happens only on the first time recvfrom() is being called, the following queries are working perfectly fine.
What am I doing wrong here?
client.c:
/* relevant code from client.c */
sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);
memset(&client, 0, sizeof(client));
client.sun_family = AF_UNIX;
strcpy(client.sun_path, CLIENT_PATH);
bind(sockfd, (struct sockaddr *)&client, sizeof(struct sockaddr_un);
memset(&server, 0, sizeof(server));
server.sun_family = AF_UNIX;
strcpy(server.sun_path, SERVER_PATH);
while(1) {
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
FD_SET(STDIN, &readfds);
select(sockfd+1, &readfds, NULL, NULL, NULL);
if (FD_ISSET(STDIN, &readfds)) {
nbytes = read(STDIN, buf, sizeof buf);
buf[nbytes] = '\0';
if (sendto(sockfd, buf, strlen(buf), 0,
(struct sockaddr *)&server,
sizeof(struct sockaddr_un)) < strlen(buf)) {
perror("send");
}
}
if (FD_ISSET(sockfd, &readfds)) {
if ((nbytes = recvfrom(sockfd, buf, MAXDATASIZE, 0, NULL, NULL)) < 0) {
perror("recv");
}
buf[nbytes] = '\0';
printf(">> %s", buf);
}
}
server.c:
/* relevant code from server.c */
FD_ZERO(&master);
FD_ZERO(&read_fds);
if ((client = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
perror("client socket");
exit(3);
}
memset(&server, 0, sizeof(struct sockaddr_un));
server.sun_family = AF_UNIX;
strcpy(server.sun_path, SOCK_PATH);
unlink(server.sun_path);
if (bind(client, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
perror("uds bind");
exit(3);
}
FD_SET(client, &master);
// keep track of the biggest file descriptor
fdmax = client; //so far, it's this one
// main loop
for(;;) {
read_fds = master; // copy it
if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
perror("select");
exit(4);
}
// run through the existing connections looking for data to read
for(i = 0; i <= fdmax; i++) {
if (FD_ISSET(i, &read_fds)) { // we got one!!
if (i == client) {
// data is from client console
if ((nbytes = recvfrom(i, &buf, sizeof buf, 0, (struct sockaddr *)&client_addr, &remotelen)) <= 0) {
if (nbytes == 0) {
FD_CLR(i, &master);
close(i);
} else {
perror("client: recv");
}
}
buf[nbytes-1] = '\0';
if (strcmp(buf, "command-1") == 0) {
if ((nbytes = sendto(i, cmd1_str, strlen(cmd1_str), 0, (struct sockaddr *)&client_addr, remotelen)) < 0) {
perror("sendto");
}
buf[0] = '\0';
} else {
sendto(i, unknown_str, strlen(unknown_str), 0, (struct sockaddr *)&client_addr, remotelen);
buf[0] = '\0';
}
}
}
} // END got new incoming connection
} // END looping through file descriptors
} // END for(;;)--and you thought it would never end!
Code was trimmed a to include only what's supposed to be important and relevant. Please, if anything important is missing, let me know and I'll add it.

Why is select() not returning in my code?

I need help debugging some code for a multiplayer game with a single server (acting as a master) and multiple clients. I want to connect those multiple clients to the server using the select and FD_Set functions.
Once the client connects to the server, I save their file descriptor in an array and check if data is available on file to read (using select). If yes, read the data, else I want to broadcast a message to all clients. This is run repeatedly in a loop. Every second, I want to broadcast a message to all clients. At the same time, I want to receive data from client too. So I am checking the availabity of data with the help of select function.
Here is my code:
Server.c:
#include"stdio.h"
#include"stdlib.h"
#include"sys/types.h"
#include"sys/socket.h"
#include"string.h"
#include"netinet/in.h"
#include "sys/select.h"
#include <fcntl.h>
#define PORT 5000
#define BUF_SIZE 2000
#define CLADDR_LEN 100
int arr[4] = { 0 };
char clientAddr[4][CLADDR_LEN];
void main() {
struct sockaddr_in addr, cl_addr;
int sockfd, len, ret, newsockfd;
char buffer[BUF_SIZE];
fd_set fds;
int maxfd = -1;
int i = 0, j = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("Error creating socket!\n");
exit(1);
}
printf("Socket created...\n");
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = PORT;
ret = bind(sockfd, (struct sockaddr *) &addr, sizeof(addr));
if (ret < 0) {
printf("Error binding!\n");
exit(1);
}
printf("Binding done...\n");
printf("Waiting for a connection...\n");
listen(sockfd, 4);
for (j = 0; j < 2; j++) { //infinite loop
len = sizeof(cl_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cl_addr, &len);
if (newsockfd < 0) {
printf("Error accepting connection!\n");
exit(1);
}
printf("Connection accepted...\n");
inet_ntop(AF_INET, &(cl_addr.sin_addr), clientAddr[j], CLADDR_LEN);
arr[j] = newsockfd;
printf("\n%d", newsockfd);
//FD_ZERO(&fds);
//FD_SET(newsockfd, &fds);
}
close(sockfd);
for (j = 0; j < 2; j++) {
if (arr[j] > maxfd)
maxfd = arr[j];
// FD_SET(arr[j], &fds);
// fcntl(arr[i], F_SETFL, O_NONBLOCK); //stop listening for new connections by the main process.
} //the child will continue to listen.
//the main process now handles the connected client.
while (1) {
for (i = 0; i < 2; i++) {
FD_SET(arr[i], &fds);
}
int returned = select(maxfd + 1, &fds, NULL, NULL, NULL);
if (returned) {
for (i = 0; i < 2; i++) {
if (FD_ISSET(arr[2], &fds)) {
ret = recvfrom(arr[i], (void*) &buffer, sizeof(buffer), 0,
NULL, NULL);
if (ret < 0) {
printf("Error receiving data!\n");
exit(1);
}
printf("%s", buffer);
}
}
}
for (j = 0; j < 2; j++) {
ret = sendto(arr[j], "abc", BUF_SIZE, 0,
(struct sockaddr *) &cl_addr, len);
if (ret < 0) {
printf("Error sending data!\n");
exit(1);
}
printf("Sent data to %s: %s\n", clientAddr[j], buffer);
}
}
/*while (1) {
for (j = 0; j < 2; j++) {
memset(buffer, 0, BUF_SIZE);
if (FD_ISSET(arr[j], &fds)) {
ret = recvfrom(arr[j], buffer, BUF_SIZE, 0,
(struct sockaddr *) &cl_addr, &len);
if (ret < 0) {
printf("Error receiving data!\n");
exit(1);
}
printf("Received data from %s: %s\n", clientAddr[j], buffer);
}
}
for (j = 0; j < 2; j++) {
ret = sendto(arr[j], "abc", BUF_SIZE, 0,
(struct sockaddr *) &cl_addr, len);
if (ret < 0) {
printf("Error sending data!\n");
exit(1);
}
printf("Sent data to %s: %s\n", clientAddr[j], buffer);
}
/* close(arr[0]);
close[arr[1]);
close(arr[2]);
close(arr[3]);
}*/
}
client.c:
#include"stdio.h"
#include"stdlib.h"
#include"sys/types.h"
#include"sys/socket.h"
#include"string.h"
#include"netinet/in.h"
#include"netdb.h"
#define PORT 5555
#define BUF_SIZE 2000
int main(int argc, char**argv) {
struct sockaddr_in addr, cl_addr;
int sockfd, ret;
char buffer[BUF_SIZE];
struct hostent * server;
char * serverAddr;
if (argc < 2) {
printf("usage: client < ip address >\n");
exit(1);
}
serverAddr = argv[1];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("Error creating socket!\n");
exit(1);
}
printf("Socket created...\n");
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(serverAddr);
addr.sin_port = PORT;
ret = connect(sockfd, (struct sockaddr *) &addr, sizeof(addr));
if (ret < 0) {
printf("Error connecting to the server!\n");
exit(1);
}
printf("Connected to the server...\n");
memset(buffer, 0, BUF_SIZE);
//printf("Enter your message(s): ");
//while (fgets(buffer, BUF_SIZE, stdin) != NULL) {
sleep(10);
ret = sendto(sockfd, "a", BUF_SIZE, 0, (struct sockaddr *) &addr, sizeof(addr));
if (ret < 0) {
printf("Error sending data!\n\t-%s", buffer);
}
ret = recvfrom(sockfd, buffer, BUF_SIZE, 0, NULL, NULL);
if (ret < 0) {
printf("Error receiving data!\n");
} else {
printf("Received: ");
fputs(buffer, stdout);
printf("\n");
}
return 0;
}
(The client is passed an IP address.)
This does not work. While debugging the server, it waits at select and nothing is received or sent. What might the problem be?
Probably because you aren't listening on the right port. The sockaddr_in members needs to be configured in network byte order:
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(PORT);
above is example how select works, in a while loop you must set timeval structure and socket sd
while (1) {
FD_ZERO(&readfds);
FD_SET(sd, &readfds);
tv.tv_sec = 0;
tv.tv_usec = 0;
rv = select(sd + 1, &readfds, NULL, NULL, &tv);
if (rv == 1) {
/*recvfrom*/
}
}
In security firstly FD_ZERO(&readfds)
and you not have to FDSET your clientfds every while loop. You can set one time before the while.
Id u check the client side and clients send data succesfully check the this line
for (i = 0; i < 2; i++) {
if (FD_ISSET(arr[2], &fds)) {
ret = recvfrom(arr[i], (void*) &buffer, sizeof(buffer), 0,
NULL, NULL);
In your code FD_ISSET(arr[2], &fds) you can change the like this
FD_ISSET(arr[i], &fds) because your for loop do nothing here if you can not change the arr[i]

C, socket programming: Connecting multiple clients to server using select()

I'm trying to make a server that can be connected to by multiple clients. Here's my code so far:
Client:
int main(int argc, char **argv) {
struct sockaddr_in servaddr;
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == -1) perror("Socket");
bzero((void *) &servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(6782);
servaddr.sin_addr.s_addr = inet_addr(<server_ip_address>);
if (-1 == connect(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)))
perror("Connect");
while(1) {
char message[6];
fgets(message, 6, stdin);
message[5] = '\0';
send(sock, message, 6, 0);
}
close(sock);
}
Server:
int main(int argc, char **argv) {
fd_set fds, readfds;
int i, clientaddrlen;
int clientsock[2], rc, numsocks = 0, maxsocks = 2;
int serversock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serversock == -1) perror("Socket");
struct sockaddr_in serveraddr, clientaddr;
bzero(&serveraddr, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(6782);
if (-1 == bind(serversock, (struct sockaddr *)&serveraddr,
sizeof(struct sockaddr_in)))
perror("Bind");
if (-1 == listen(serversock, SOMAXCONN))
perror("Listen");
FD_ZERO(&fds);
FD_SET(serversock, &fds);
while(1) {
readfds = fds;
rc = select(FD_SETSIZE, &readfds, NULL, NULL, NULL);
if (rc == -1) {
perror("Select");
break;
}
for (i = 0; i < FD_SETSIZE; i++) {
if (FD_ISSET(i, &readfds)) {
if (i == serversock) {
if (numsocks < maxsocks) {
clientsock[numsocks] = accept(serversock,
(struct sockaddr *) &clientaddr,
(socklen_t *)&clientaddrlen);
if (clientsock[numsocks] == -1) perror("Accept");
FD_SET(clientsock[numsocks], &fds);
numsocks++;
} else {
printf("Ran out of socket space.\n");
}
} else {
int messageLength = 5;
char message[messageLength+1];
int in, index = 0, limit = messageLength+1;
while ((in = recv(clientsock[i], &message[index], limit, 0)) > 0) {
index += in;
limit -= in;
}
printf("%d\n", index);
printf("%s\n", message);
}
}
}
}
close(serversock);
return 0;
}
As soon as a client connects and sends its first message, the server just runs in an infinite loop, and spits out garbage from the message array. recv doesn't seem to receive anything. Can anyone see where i go wrong?
Two issues in your code:
You should do recv(i, ...) instead of recv(clientsock[i], ...)
After that you do not check if recv() failed, and therefore printf() prints out the uninitialised buffer message, hence the garbage in the output
You need to check for limit <= 0 in your read loop, before you call read.
In the while loop for the server, change the code to do recv(i) instead of recv(clientsocks[i]). I have implemented this code and it works with this change.
I replaced the else with the below and it works
} else {
/* int messageLength = 5;
char message[messageLength+1];
int in, index = 0, limit = messageLength+1;
memset ( &message[index] , 0, sizeof ( message [index] ) );
while ((in = recv(i, &message[index], limit, 0)) > 0) {
index += in;
limit -= in;
}
printf("%d\n", index);
printf("%s\n", message);
*/
bzero(buf, sizeof(buf));
if ((rval = read(i, buf, 1024)) < 0)
perror("reading stream message");
else if (rval == 0)
printf("Ending connection\n");
else
printf("-->%s\n", buf);
}
1) It is a good practice to use PF_INET(protocol family) rather than
AF_INET(address family) during the Socket creation .
2) within the while(1) loop
each time it is advisable to make your readfds empty by using FD_ZERO(&readfds).
in the recv() call you should use i rather than clientsocks[i]
you have to check return value of recv is negative(which indicating error in reading) if that is the case you do not have to print the message.
during printing the message make sure the stdout/server is ready for writing anything to it which you can do it by using writefds (3rd argument of select).

Resources