LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   single tcp server which connects to client using select() function (https://www.linuxquestions.org/questions/linux-newbie-8/single-tcp-server-which-connects-to-client-using-select-function-4175524533/)

innovator 11-06-2014 04:51 AM

single tcp server which connects to client using select() function
 
Hello,
I want to connect multiple clients to server using select and FD_Set functions .So after the client connects to the server i have save their File descriptor in an array and checked if data is
available on file to read using select function , if yes then read the data else i want to broadcast a message to all the client .. This goes in a loop . After every second i want to broascast a msg to client . 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;
}


(pass ip address while rining the client)


This code does not work . while debugging the server , it wait at select function and nothing is received or sent.I am unable to figure out the problem.
Please help!!

jpollard 11-07-2014 07:44 PM

It won't work..

The problem you have is that once you accept a connection, you never check for another connection.

The usual way this is done is to use threads - the main thread then just accepts (which will cause a wait), then atomically adds the accepted connection to the fdset used by another thread.

Alternatively, you CAN do it single threaded, BUT the loop must start with adding the listening socket to the fdset. Then, whenever input is ready you have to check to see if it is the listening socket rather than a client socket.

It makes the event loop a bit more complex.

Second, if you expect to be able to send a message to the clients every second or so, you have to include a timeout value.

I refer you to "UNIX Network Programming" for examples (there are various editions, personally, I still like the Stevens versions).


All times are GMT -5. The time now is 07:50 AM.