Why is UDP Multicast Server not responding? - c

I am trying to implement basic UDP multicast client and server on Linux. The server, based on a message sent by the client, is supposed to reply with system parameters (kinda like SNMP). Right now, I am testing with a single server. After running client and server on different terminals, I send a 3 character request to the server, but it appears that server is not able to proceed, and just stays suspended there, waiting for client. The codes are given here:
Client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>
char* createheader(int , int , int , char , int );
#define PORT 15002
#define MAXLINE 10000
char* MULTICAST = "224.0.0.3";
char* myIP = "127.0.0.1";
// Driver code
int main(int argc, char *argv[])
{
char buffer[10000];
char message[10000];
char *msg;
int sockfd, n;
char c = '0';
int req1, req2, req3;
int ctr = 0;
int prev = 0, curr = 0;
char tp = 'Q';
int seq = 0, len;
int yes = 1;
short int resendflag = 0;
struct timeval time1, time2, tv={2,0}; // structures that can take time in seconds and micro seconds.
struct sockaddr_in servaddr;
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_addr.s_addr = inet_addr(MULTICAST);
servaddr.sin_port = htons(PORT);
servaddr.sin_family = AF_INET;
struct in_addr interface_addr;
interface_addr.s_addr = inet_addr(myIP);
// create datagram socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (int*) &yes, sizeof(yes));
if (sockfd < 0) {
perror("Error: socket");
exit(1);
}
/*if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
printf("\n Error : Connect Failed \n");
exit(0);
}*/
setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char *)&tv,sizeof(struct timeval));
//u_char loop;
//setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));
//Create Tx Header
while(1)
{
prev = seq;
seq++;
printf("\nEnter the 3 request characters, each followed by newline\n");
scanf("%d%d%d", &req1, &req2, &req3);
msg = createheader(req1, req2, req3, tp, seq);
while(c!='\0')
{
c = *(msg+ctr);
//puts(&c);
message[ctr] = c;
ctr++;
}
//printf("\nsize of %d",sizeof(c));
c = '0';
ctr = 0;
//msg = NULL;
// connect to server
// request to send datagram
// connect stores the peers IP and port
sendto(sockfd, message, sizeof(message), 0, (struct sockaddr*)&servaddr, sizeof(servaddr));
puts(message);
// waiting for response
n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&servaddr, &len);
Portion after this is specific to my application: may be ignored unless you want to test it out.
curr = buffer[4]-'0' + (buffer[5]-'0')*256 + (buffer[6]-'0')*65536 + (buffer[7]-'0')*65536*256;
if (prev == curr || n == -1)
{
resendflag = 1;
while(resendflag)
{
printf("No Response Recieved. Resending...\n");
sendto(sockfd, message, strlen(message), 0, (struct sockaddr*)&servaddr, sizeof(servaddr));
n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)NULL, NULL);
curr = buffer[4]-'0' + (buffer[5]-'0')*256 + (buffer[6]-'0')*65536 + (buffer[7]-'0')*65536*256;
if (prev == curr || n == -1)
{
resendflag = 1;
}
else
{
resendflag = 0;
puts(buffer+12);
}
sleep(1);
}
}
else
puts(buffer+12);
//tp = 'A';
//msg = createheader(req1, req2, req3, tp, seq);
// close the descriptor
}
close(sockfd);
}
char* createheader(int req1, int req2, int req3, char tp, int seq)
{
static char msg1[1000];
int len;
//char req;
msg1[0] = 'A';
msg1[1] = tp;
msg1[3] = '0';
msg1[4] = seq%256+'0';
msg1[5] = (seq/256)%256+'0';
msg1[6] = (seq/65536)%256+'0';
msg1[7] = (seq/(65536*256))%256+'0';
msg1[8] = req1+'0';
msg1[9] = req2+'0';
msg1[10] = req3+'0';
msg1[12] = '\0';
len = strlen(msg1);
msg1[2] = len +'0';
return msg1;
}
And this is the server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <time.h>
#define PORT 15002
#define MAXLINE 10000
char* MULTICAST = "224.0.0.3";
char* myIP = "127.0.0.2";
char* createheader(int , int , int , char , int , int);
char* sysfunc(int , int , int);
// Driver code
int main(int argc, char *argv[])
{
setbuf(stdout, NULL);
printf("lololol5"); //Just some indicators to see the progress
char buffer[10000];
char *message = "Hello Client";
char msg[10000];
char *msg1;
char tp = 'R';
int yes = 1;
int listenfd, len, l=0, seq = 0, req1, req2, req3, i, curr = 0, exc = 0;
const char* syscl= NULL;
int drop;
srand(time(NULL));
FILE* fp;
struct sockaddr_in servaddr, cliaddr;
bzero(&servaddr, sizeof(servaddr));
printf("lololol4");
// Create a UDP Socket
listenfd = socket(AF_INET, SOCK_DGRAM, 0);
if (listenfd < 0) {
perror("socket");
exit(1);
}
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (int*)&yes, sizeof(yes))<0)
{
perror("socket");
exit(1);
}
printf("lololol3");
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);
servaddr.sin_family = AF_INET;
char *ip = inet_ntoa(servaddr.sin_addr);
printf("\nip is %s\n", ip);
// bind server address to socket descriptor
if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
perror("bind");
exit(1);
}
printf("lololol2");
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST);
mreq.imr_interface.s_addr = inet_addr(myIP);
char *ip1 = inet_ntoa(mreq.imr_multiaddr);
printf("\nmulip is %s\n", ip1);
if (setsockopt(listenfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &mreq, sizeof(mreq)) < 0)
{
perror("setsockopt");
return 1;
}
while(1)
{
//receive the datagram
len = sizeof(cliaddr);
int n = recvfrom(listenfd, (char*) buffer, sizeof(buffer), 0, (struct sockaddr*)&cliaddr, &len); //receive message from client
As before, application specific portion.
printf("\nHi\n");
puts(buffer); //display message
printf("\n");
curr = buffer[4]-'0' + (buffer[5]-'0')*256 + (buffer[6]-'0')*65536 + (buffer[7]-'0')*65536*256;//acquire client seq. no
req1 = buffer[8]; req2 = buffer[9]; req3 = buffer[10];//extract request bytes
syscl = sysfunc(req1-48, req2-48, req3-48); //Function call to get system corresponding system command string
l = 12; //After 12 bytes of header
puts(syscl);
if (strcmp(syscl, "\nInvalid Command...\n\0"))
{
system(syscl); //The system call with the string gotten
fp = fopen("sysstat.txt","r"); //Open the file where system output is written
while(!feof(fp))
{
msg[l] = fgetc(fp); //write file into an array
l++;
}
fclose(fp);
msg[l] = '\0'; //Append string with end of text char
}
else
{
char c1 = '0';
while(c1 != '\0')
{
c1 = *(syscl+l-12); //write file into an array
//printf("\n %c", msg[l]);
msg[l] = c1;
l++;
}
}
msg1 = createheader(req1, req2, req3, tp, curr, l); //Create Header
for (i=0; i<12; i++)
{
msg[i] = *(msg1+i);
}
drop = rand()%10+1; //to simulate dropped packets
if (drop > 2) //Drop with a given prob (i.e (x-1)/10)
{
sendto(listenfd, &msg, MAXLINE, 0,(struct sockaddr*)&cliaddr, sizeof(cliaddr));
puts(msg);
}
l = 0;
}
}
char* createheader(int req1, int req2, int req3, char tp, int seq, int len) //header
{
static char msg1[10000];
//int len;
//char req;
msg1[0] = '$'; //Start Char
msg1[1] = tp; //Type of req.
//msg1[3] = '0';
msg1[4] = seq%256+'0'; //4-7: seq no in little endian
msg1[5] = (seq/256)%256+'0';
msg1[6] = (seq/65536)%256+'0';
msg1[7] = (seq/(65536*256))%256+'0';
msg1[8] = req1;
msg1[9] = req2;
msg1[10] = req3;
msg1[11] = '0';//Reserved Byte, Also for alignment
//len = strlen(msg1);
msg1[2] = (len +'0')%256+'0'; //2-3:Length in lil' endian
msg1[3] = ((len+'0')/256)%256+'0';
return msg1;
}
char* sysfunc(int req1, int req2, int req3)
{
static char syscl[100];
//printf("\ncomm %d\n", req2);
//printf("\ncomm %d\n", req3);
switch (req2)
{
case 1: //Hardware
{
switch (req3)
{
case 1: strcpy(syscl, "lscpu > sysstat.txt\0"); //CPU
break;
case 2: strcpy(syscl, "lsmem > sysstat.txt\0"); //Memoru=y
break;
case 3: strcpy(syscl, "lsblk > sysstat.txt\0"); //HDDs
break;
case 4: strcpy(syscl, "lspci > sysstat.txt\0"); //PCI Add-Ons
break;
default: strcpy(syscl, "\nInvalid Command...\n\0"); //Default
break;
}
}
break;
case 2: //OS
{
switch (req3)
{
case 1: strcpy(syscl, "hostname > sysstat.txt\0");//Hostname
break;
case 2: strcpy(syscl, "hostnamectl > sysstat.txt\0");//OS and Kernel
break;
case 3: strcpy(syscl, "uptime > sysstat.txt\0");//Uptime
break;
default: strcpy(syscl, "\nInvalid Command...\n\0");
break;
}
}
break;
case 3: //Network
{
switch (req3)
{
case 1: strcpy(syscl, "ip link show > sysstat.txt\0");//Ifs
break;
case 2: strcpy(syscl, "ifconfig | grep ether > sysstat.txt\0");//Ethernet
break;
case 3: strcpy(syscl, "ifconfig > sysstat.txt\0");//IP
break;
case 4: strcpy(syscl, "route -n > sysstat.txt\0");//Routing Table
break;
default: strcpy(syscl, "\nInvalid Command...\n\0");
break;
}
}
break;
default: strcpy(syscl, "\nInvalid Command...\n\0");
break;
}
return syscl;
}
Have been at it for 2 days. Unable to figure out where I went wrong. Since the server is showing no reaction, I am assuming there is something wrong in the initial portions (recvfrom on the server side) and therefore have split the code in such a way. Sorry if I have made some obvious noob mistakes.

It seems you chose a wrong local IP address of interface in the server (where did you get the "127.0.0.2" from?) - if I change
mreq.imr_interface.s_addr = inet_addr(myIP);
to
mreq.imr_interface.s_addr = INADDR_ANY;
the server starts receiving.
Aren't 127.0.0.0/8 block of local addresses?
These are loopback addresses (see What is the rest of the 127.0.0.0/8 address space used for?). The comment local IP address of interface in the definition of struct ip_mreq may be a bit misleading, since it can remind one of localhost, but it actually means an IP address assigned to an interface of the local host seen from outside.
It is still not working with INADDR_ANY.
As so often, not working is an insufficient problem description. You could gather more information e. g. by running the server with strace -enetwork …. And I recommend to leave aside unnecessary complications like Mininet until the programs work on a pure network.

Related

Socket programming chat application

I made a chat application using sockets in c language. When i run server and client on same device it works fine. But, when i run client and server on different device client shows connect error. is this problem related to ip address.
server side code:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <signal.h>
#define MAX_CLIENTS 100
#define BUFFER_SZ 2048
static _Atomic unsigned int cli_count = 0;
static int uid = 10;
/* Client structure */
typedef struct{
struct sockaddr_in address;
int sockfd;
int uid;
char name[32];
} client_t;
client_t *clients[MAX_CLIENTS];
pthread_mutex_t clients_mutex = PTHREAD_MUTEX_INITIALIZER;
void str_overwrite_stdout() {
printf("\r%s", "> ");
fflush(stdout);
}
void str_trim_lf (char* arr, int length) {
int i;
for (i = 0; i < length; i++) { // trim \n
if (arr[i] == '\n') {
arr[i] = '\0';
break;
}
}
}
void print_client_addr(struct sockaddr_in addr){
printf("%d.%d.%d.%d",
addr.sin_addr.s_addr & 0xff,
(addr.sin_addr.s_addr & 0xff00) >> 8,
(addr.sin_addr.s_addr & 0xff0000) >> 16,
(addr.sin_addr.s_addr & 0xff000000) >> 24);
}
/* Add clients to queue */
void queue_add(client_t *cl){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i < MAX_CLIENTS; ++i){
if(!clients[i]){
clients[i] = cl;
break;
}
}
pthread_mutex_unlock(&clients_mutex);
}
/* Remove clients to queue */
void queue_remove(int uid){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i < MAX_CLIENTS; ++i){
if(clients[i]){
if(clients[i]->uid == uid){
clients[i] = NULL;
break;
}
}
}
pthread_mutex_unlock(&clients_mutex);
}
/* Send message to all clients except sender */
void send_message(char *s, int uid){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i<MAX_CLIENTS; ++i){
if(clients[i]){
if(clients[i]->uid != uid){
if(write(clients[i]->sockfd, s, strlen(s)) < 0){
perror("ERROR: write to descriptor failed");
break;
}
}
}
}
pthread_mutex_unlock(&clients_mutex);
}
/* Handle all communication with the client */
void *handle_client(void *arg){
char buff_out[BUFFER_SZ];
char name[32];
int leave_flag = 0;
cli_count++;
client_t *cli = (client_t *)arg;
// Name
if(recv(cli->sockfd, name, 32, 0) <= 0 || strlen(name) < 2 || strlen(name) >= 32-1){
printf("Didn't enter the name.\n");
leave_flag = 1;
} else{
strcpy(cli->name, name);
sprintf(buff_out, "%s has joined\n", cli->name);
printf("%s", buff_out);
send_message(buff_out, cli->uid);
}
bzero(buff_out, BUFFER_SZ);
while(1){
if (leave_flag) {
break;
}
int receive = recv(cli->sockfd, buff_out, BUFFER_SZ, 0);
if (receive > 0){
if(strlen(buff_out) > 0){
send_message(buff_out, cli->uid);
str_trim_lf(buff_out, strlen(buff_out));
printf("%s -> %s\n", buff_out, cli->name);
}
} else if (receive == 0 || strcmp(buff_out, "exit") == 0){
sprintf(buff_out, "%s has left\n", cli->name);
printf("%s", buff_out);
send_message(buff_out, cli->uid);
leave_flag = 1;
} else {
printf("ERROR: -1\n");
leave_flag = 1;
}
bzero(buff_out, BUFFER_SZ);
}
/* Delete client from queue and yield thread */
close(cli->sockfd);
queue_remove(cli->uid);
free(cli);
cli_count--;
pthread_detach(pthread_self());
return NULL;
}
int main(int argc, char **argv){
if(argc != 2){
printf("Usage: %s <port>\n", argv[0]);
return EXIT_FAILURE;
}
char *ip = "127.0.0.1";
int port = atoi(argv[1]);
int option = 1;
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
pthread_t tid;
/* Socket settings */
listenfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(ip);
serv_addr.sin_port = htons(port);
/* Ignore pipe signals */
signal(SIGPIPE, SIG_IGN);
if(setsockopt(listenfd, SOL_SOCKET,(SO_REUSEPORT | SO_REUSEADDR),(char*)&option,sizeof(option)) < 0){
perror("ERROR: setsockopt failed");
return EXIT_FAILURE;
}
/* Bind */
if(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR: Socket binding failed");
return EXIT_FAILURE;
}
/* Listen */
if (listen(listenfd, 10) < 0) {
perror("ERROR: Socket listening failed");
return EXIT_FAILURE;
}
printf("=== WELCOME TO THE CHATROOM ===\n");
while(1){
socklen_t clilen = sizeof(cli_addr);
connfd = accept(listenfd, (struct sockaddr*)&cli_addr, &clilen);
/* Check if max clients is reached */
if((cli_count + 1) == MAX_CLIENTS){
printf("Max clients reached. Rejected: ");
print_client_addr(cli_addr);
printf(":%d\n", cli_addr.sin_port);
close(connfd);
continue;
}
/* Client settings */
client_t *cli = (client_t *)malloc(sizeof(client_t));
cli->address = cli_addr;
cli->sockfd = connfd;
cli->uid = uid++;
/* Add client to the queue and fork thread */
queue_add(cli);
pthread_create(&tid, NULL, &handle_client, (void*)cli);
/* Reduce CPU usage */
sleep(1);
}
return EXIT_SUCCESS;
}
client side code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define LENGTH 2048
// Global variables
volatile sig_atomic_t flag = 0;
int sockfd = 0;
unsigned char name[32];
void str_overwrite_stdout() {
printf("%s", "> ");
fflush(stdout);
}
void str_trim_lf (char* arr, int length) {
int i;
for (i = 0; i < length; i++) { // trim \n
if (arr[i] == '\n') {
arr[i] = '\0';
break;
}
}
}
void catch_ctrl_c_and_exit(int sig) {
flag = 1;
}
void send_msg_handler() {
unsigned char message[LENGTH] = {};
unsigned char buffer[3000] = {};
while(1) {
str_overwrite_stdout();
fgets(message, LENGTH, stdin);
str_trim_lf(message, LENGTH);
if (strcmp(message, "exit") == 0) {
break;
} else {
sprintf(buffer, "%s: %s\n", name, message);
send(sockfd, buffer, strlen(buffer), 0);
}
bzero(message, LENGTH);
bzero(buffer, LENGTH + 32);
}
catch_ctrl_c_and_exit(2);
}
void recv_msg_handler() {
char message[LENGTH] = {};
while (1) {
int receive = recv(sockfd, message, LENGTH, 0);
if (receive > 0) {
printf("%s", message);
str_overwrite_stdout();
} else if (receive == 0) {
break;
} else {
// -1
}
memset(message, 0, sizeof(message));
}
}
int main(int argc, char **argv){
if(argc != 2){
printf("Usage: %s <port>\n", argv[0]);
return EXIT_FAILURE;
}
char *ip = "152.168.0.100";
int port = atoi(argv[1]);
signal(SIGINT, catch_ctrl_c_and_exit);
printf("Please enter your name: ");
fgets(name, 32, stdin);
str_trim_lf(name, strlen(name));
if (strlen(name) > 32 || strlen(name) < 2){
printf("Name must be less than 30 and more than 2 characters.\n");
return EXIT_FAILURE;
}
struct sockaddr_in server_addr;
/* Socket settings */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(ip);
server_addr.sin_port = htons(port);
// Connect to Server
int err = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (err == -1) {
printf("ERROR: connect\n");
return EXIT_FAILURE;
}
// Send name
send(sockfd, name, 32, 0);
printf("=== WELCOME TO THE CHATROOM ===\n");
pthread_t send_msg_thread;
if(pthread_create(&send_msg_thread, NULL, (void *) send_msg_handler, NULL) != 0){
printf("ERROR: pthread\n");
return EXIT_FAILURE;
}
pthread_t recv_msg_thread;
if(pthread_create(&recv_msg_thread, NULL, (void *) recv_msg_handler, NULL) != 0){
printf("ERROR: pthread\n");
return EXIT_FAILURE;
}
while (1){
if(flag){
printf("\nBye\n");
break;
}
}
close(sockfd);
return EXIT_SUCCESS;
}
it is showing connect error when i run it on different machines.
So as far as I can tell, the codes that you posted are incomplete, but let's assume that, as you say, everything is working fine, it work in the local machine, but when you run the two programs in two different devices, the client fails to connect to the server.
Then I would ask you the question, as I also asked it in the comment: are the two devices in the same subnet? You have a home router, and both devices are connected to this router?
If not, then that will be the problem. I am not sure how deep you understand IP addresses and subnets, but here is a simple summary. When you look at the IP address on your PC, you see your private IP address that was given you by the router. Let's say, that you have two machines connected to the same router, one has the IP address of 192.168.0.101, the other 192.168.0.102. If 192.168.0.101 is the client and wants to connect to the server that runs on 192.168.0.102, it should work without problems.
But let's say that you send the server code to me. I run the server on my computer, which has the IP address of 192.168.0.103, you still run the client at home on 192.168.0.101. In this case, you won't be able to connect to my machine, because the 192.168.0.103 is the private IP address given out by my own router. For that to work, I would have to at least configure my router to open up a port and forward the packets coming to that port to my PC. Then I would have to give you the public IP and the port. And so if the firewall is configured so that it allows your packets into my network, then it might work.
Of course it is a bit more complicated than this, but this is the general idea.
If this is not the case for you, and the devices are on the same subnet, then we would simply need more information and the comlete code.

C: How do you read and unpack a message over a socket?

I am trying to receive an updated message over the socket and unpack the
data. I want to use the update_client function to update the server's
internal representation of the client co-ordinates and respond to the
client with the required value.
I think I should use recv to read the full message (of length UPDATE_CMD_LEN) into buffer.
Then unpack data having message in the following format:
U<id><fields of gpscoords>
Character 'U' (meaning update), followed by ID of the client (unsigned char)
and then the gpscoord structure in network format.
This is a rough idea of how to do it but I don't know how:
[1] Unpack ID
[2] Unpack coordinates with int update_client(unsigned char id, gpscoords *pos
which takes ID and pointer to position struct, returns -1 on error and 0 on success
The server should then respond to client using sendto function and reply
NO_RES on error and SUCC_RES on success.
void do_update(int sockfd, struct sockaddr_in *clientaddr) {
char msg[UPDATE_CMD_LEN];
recv(sockfd, msg, UPDATE_CMD_LEN, flags);
fprintf(stderr, "do_update not implemented!\n");
exit(-1);
}
client.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "gps.h"
#define CMD_LEN 10
#define LINE_LEN NAME_LEN + 15
#define FIREFOX "/usr/bin/firefox"
void make_route_url(char *url, gpscoords *pos, gpscoords *target) {
char pos_sign_n;
char pos_sign_e;
char tar_sign_n;
char tar_sign_e;
pos_sign_n = pos->north ? '+' : '-';
pos_sign_e = pos->east ? '+' : '-';
tar_sign_n = target->north ? '+' : '-';
tar_sign_e = target->east ? '+' : '-';
sprintf(url,
"http://map.project-osrm.org/?z=13&loc=%c%u.%u,%c%u.%u&loc=%c%u.%u,%c%u.%u",
pos_sign_n, pos->lat, pos->lat_frac,
pos_sign_e, pos->lon, pos->lon_frac,
tar_sign_n, target->lat, target->lat_frac,
tar_sign_e, target->lon, target->lon_frac);
}
void show_route(gpscoords *pos, gpscoords *target) {
// char url[75];
fprintf(stderr, "show_route not implemented!\n");
exit(-1);
}
int run_client(char *name, char *serverip) {
char *cmdline;
size_t line_len;
char cmd[11];
gpsinfo info;
gpscoords pos, targetpos;
char targetname[NAME_LEN];
bzero(targetname, NAME_LEN);
bzero(&info, sizeof(info));
bzero(&pos, sizeof(pos));
bzero(&targetpos, sizeof(targetpos));
if (register_client(serverip, name, &info) == -1) {
perror("Error registering client.");
return -1;
}
find_self(&pos);
if (update_position(&info, &pos) == -1) {
printf("Failed to send initial position to server.\n");
exit(-1);
}
for (;;) {
printf("Command: ");
line_len = 0;
cmdline = NULL;
getline(&cmdline, &line_len, stdin);
if (strncmp(cmdline, "update", 3) == 0) {
find_self(&pos);
if (update_position(&info, &pos) == -1) {
printf("Failed to update.\n");
}
} else if (strncmp(cmdline, "find", 3) == 0) {
sscanf(cmdline, "%10s %25s", cmd, targetname);
if (get_position(&info, targetname, &targetpos) == -1) {
printf("Couldn't find target.\n");
} else {
show_route(&pos, &targetpos);
}
} else if (strncmp(cmdline, "quit", 4) == 0) {
free(cmdline);
break;
}
free(cmdline);
}
if (unregister_client(&info) == -1) {
perror("Error unregistering client.");
return -1;
}
return 0;
}
int main(int argc, char **argv) {
if (argc < 2) {
printf("Usage: ./client <client name> <server_ip>\n");
return 0;
}
return run_client(argv[1], argv[2]);
}
socket.c
#include <sys/socket.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "sockets.h"
int create_dg_socket(in_port_t port) {
// Create the socket
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
printf("create_dg_socket cannot create socket!");
return -1;
}
// Bind the socket port
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
printf("create_dg_socket cannot bind socket!");
close(sockfd);
return -1;
}
return sockfd;
}
int open_dg_socket(char *ipaddr, in_port_t port, struct sockaddr_in *addr) {
// Create the socket
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
return -1;
}
// Setup
addr->sin_family = AF_INET;
addr->sin_port = htons(port);
addr->sin_addr.s_addr = inet_addr(ipaddr);
return sockfd;
}
int dg_sendrecv(int sockfd,
struct sockaddr_in *addr,
char *message, size_t out_len,
char *response, size_t in_len) {
if (sendto(sockfd, message, out_len, 0, (struct sockaddr *)&addr, sizeof(*addr)) == -1) {
printf("dg_sendrecv cannot send data!");
return -1;
}
int ret = recvfrom(sockfd, response, in_len, 0, NULL, NULL);
if (ret == -1) {
printf("dg_sendrecv cannot read data!");
return -1;
}
return ret;
}
/*
int dg_sendrecv(int sockfd,
struct sockaddr_in *addr,
char *message, size_t out_len,
char *response, size_t in_len) {
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ipaddr);
return dg_sendrecv_addr(sockfd, &addr, message, out_len, response, in_len);
}
*/
server.c
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include "sockets.h"
#include "gps.h"
#include "server.h"
#define NUM_CLIENTS 5
char clients[NUM_CLIENTS][NAME_LEN];
gpscoords coords[NUM_CLIENTS];
void do_register(int sockfd, struct sockaddr_in *clientaddr) {
char msg[REGISTER_CMD_LEN];
char *name;
unsigned char id, i;
if (recv(sockfd, msg, REGISTER_CMD_LEN, 0) == -1) {
perror("Error receiving register command.");
exit(-1);
}
// first byte is server command, rest is name
name = &msg[1];
id = NO_RES;
for (i = 0; i < NUM_CLIENTS; ++i) {
if (clients[i][0] == '\0') {
strncpy(clients[i], name, NAME_LEN);
clients[i][NAME_LEN - 1] = '\0';
bzero(&coords[i], sizeof(coords[i]));
id = i + 1;
break;
}
}
if (sendto(sockfd,
&id, sizeof(id),
0,
(struct sockaddr *)clientaddr, sizeof(*clientaddr)) == -1) {
perror("Error replying to client.");
exit(-1);
}
}
void do_unregister(int sockfd, struct sockaddr_in *clientaddr) {
unsigned char msg[UNREGISTER_CMD_LEN];
unsigned char id;
char res = NO_RES;
if (recv(sockfd, &msg, UNREGISTER_CMD_LEN, 0) == -1) {
perror("Error receiving unregister command.");
exit(-1);
}
id = msg[1] - 1;
if (id < NUM_CLIENTS) {
clients[id][0] = '\0';
res = SUCC_RES;
}
if (sendto(sockfd,
&res, sizeof(res),
0,
(struct sockaddr *)clientaddr, sizeof(*clientaddr)) == -1) {
perror("Error responding to client.");
exit(-1);
}
}
int update_client(unsigned char id, gpscoords *pos) {
id -= 1;
if (id >= NUM_CLIENTS)
return -1;
memcpy(&coords[id], pos, sizeof(coords[id]));
return 0;
}
void do_update(int sockfd, struct sockaddr_in *clientaddr) {
/**
* Receive an update message over the socket and unpack the
* data. Then use the update_client function to update the server's
* internal representation of the client co-ordinates. Then respond to the
* client with the required value.
* Use recv to read the full message (of length UPDATE_CMD_LEN) into buffer.
* Unpack data, message of following format:
* U<id><fields of gpscoords>
* Character 'U' (meaning update), followed by ID of the client (unsigned char)
* and then the gpscoord structure in network format.
*
* 1. Unpack ID
* 2. Unpack coordinates with (int update_client(unsigned char id, gpscoords *pos)
* which takes ID and pointer to position struct, returns -1 on error and 0 on success
* Server should then respond to client using sendto function and reply
* NO_RES on error and SUCC_RES on success.
*/
char msg[UPDATE_CMD_LEN];
recv(sockfd, msg, UPDATE_CMD_LEN, flags);
fprintf(stderr, "do_update not implemented!\n");
exit(-1);
}
static gpscoords *get_client(char *name) {
for (int i = 0; i < NUM_CLIENTS; ++i) {
if (strcmp(name, clients[i]) == 0) {
return &coords[i];
break;
}
}
return NULL;
}
void do_get(int sockfd, struct sockaddr_in *clientaddr) {
char msg[GET_CMD_LEN];
char res[GET_RES_LEN];
char *name;
if (recv(sockfd, msg, GET_CMD_LEN, 0) == -1) {
perror("Error receiving get command.");
exit(-1);
}
name = &msg[1];
name[NAME_LEN - 1] = '\0';
gpscoords *pos = get_client(name);
if (pos == NULL) {
res[0] = NO_RES;
} else {
res[0] = SUCC_RES;
pack_gpscoords(pos, &res[1]);
}
if (sendto(sockfd,
&res, GET_RES_LEN,
0,
(struct sockaddr *)clientaddr, sizeof(*clientaddr)) == -1) {
perror("Error sending result to client.");
exit(-1);
}
}
int serve(int sockfd) {
char cmd;
struct sockaddr_in clientaddr;
socklen_t clientaddrlen = sizeof(clientaddr);
for (;;) {
if (recvfrom(sockfd,
&cmd, sizeof(cmd),
MSG_PEEK,
(struct sockaddr *)&clientaddr, &clientaddrlen) == -1) {
exit(-1);
}
switch (cmd) {
case CMD_REGISTER:
do_register(sockfd, &clientaddr);
break;
case CMD_UNREGISTER:
do_unregister(sockfd, &clientaddr);
break;
case CMD_UPDATE:
do_update(sockfd, &clientaddr);
break;
case CMD_GET:
do_get(sockfd, &clientaddr);
break;
default:
break;
}
}
}
void init_info() {
int i;
for (i = 0; i < NUM_CLIENTS; ++i) {
clients[i][0] = '\0';
}
}
int main(int argc, char **argv) {
int sockfd = create_dg_socket(SERVER_PORT);
if (sockfd == -1) {
fprintf(stderr, "Error creating socket!\n");
return -1;
}
init_info();
printf("Server ready.\n");
serve(sockfd);
// Note: server never terminates, we're relying on the system to clean up
// our open socket file descriptor (and shut it down)
return 0;
}
If you are looking for a way to safe and read data from char arrays that maybe will help you:
char buffer[5+sizeof(gpscoords)];
int *int_pointer;
gpscoords *gps_pointer;
int id=1;
gpscoords gps="some gps contend";
int id_frombuffer;
gpscoords gps_frombuffer;
char c_frombuffer;
buffer[0]='U';
int_pointer=(int*)&buffer;
int_pointer+=1;
*int_pointer=id;
gps_pointer=(gpscoords*)&buffer;
gps_pointer+=5;
*gpspointer=gps;
//send buffer
c_frombuffer=buffer[0];//c_frombuffer now contains 'U'
int_pointer=(int*)&buffer;
int_pointer+=1;
id_frombuffer=*int_pointer;//id_frombuffer now contains 1
gps_pointer=(gpscoords*)&buffer;
gpscoords+=5;
gps_frombuffer=*pointer;//gps_frombuffer now contains "some gps contend"
As an example if your client code looks like that:
void sendupdate(unsigned char id,gpscoords gps)
{
char buffer[2+sizeof(gpscoords)];
gpscoords *gps_pointer;
buffer[0]='U';
buffer[1]=id;
gps_pointer=(gpscoords*)&buffer;
gps_pointer+=2;
*gpspointer=gps;
send(socket, buffer, 2+sizeof(gpscoords), flags);
}
your server function should look like that:
void do_update(int sockfd, struct sockaddr_in *clientaddr)
{
char buffer[2+sizeof(gpscoords)];
recv(sockfd, buffer, 2+sizeof(gpscoords), flags);
unsigned char id_frombuffer=buffer[1];
gpscoords *gpspointer=(gpscoords*)&buffer;
gpspointer+=2;
update_client(id_frombuffer, gpspointer);
}

executing commands via sockets with popen()

Can anybody give me a hand trying to implement the following server and client?:
The server:
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
int main(void) {
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serv_addr = { 0 };
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(1234);
bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
listen(sock, 128);
struct sockaddr_in cli_addr = { 0 };
socklen_t cli_addrlen = sizeof(cli_addr);
int acc_sock = accept(sock, (struct sockaddr *)&cli_addr, &cli_addrlen);
printf("[+] Connected \n");
char buf[1024];
ssize_t nread;
memset(buf, 0, sizeof(buf));
int a;
while (1) {
nread = read(0, buf, 1024);
write(acc_sock, buf, nread);
memset(buf, 0, sizeof(buf));
while ((read(acc_sock, buf, 1024)) != 0) {
printf("%s", buf);
memset(buf, 0, sizeof(buf));
}
}
}
All the servers does is scanning a command from stdin and send it to the client via sockets. Then scans the client response and prints it out to stdout.
The client:
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
int main(int argc, const char *argv[]) {
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serv = { 0 };
char buf[1024];
char command[1024];
memset(buf, 0, sizeof(buf));
memset(command, 0, sizeof(command));
int nread;
FILE *in;
extern FILE *popen();
serv.sin_family = AF_INET;
serv.sin_port = htons(atoi(argv[1]));
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
int a;
connect(sock, (struct sockaddr*)&serv, sizeof(serv));
while (1) {
nread = read(sock, buf, 1024);
in = popen(buf, "r");
while ((fgets(command, sizeof(command), in)) != NULL) {;
write(sock, command, sizeof(command));
}
memset(buf, 0, sizeof(buf));
}
return 0;
}
Essentially the client receives the command scanned by the server, executes it using popen(), and sends the contents of the command line by line until NULL.
The problem is that the code suddenly stops working just after the first command. the transmission of the command and the command's output is satisfactory, however after printing the output of the first command the program just stops working. I think is a problem with fgets(), however I could be wrong. Is there any solutions for this problem?
Caveat: This may [or may not] fit your needs because I reversed the sense of the client and server loops in the corrected code below. As I had mentioned in my comment above:
The normal orientation for an app like this is that a client connects to a server and the client feeds the commands [read from stdin] to the server [which does popen] and feeds back the results. That's how ssh works. Your orientation is reversed. What you've got is you fire sshd and wait for ssh to connect and then sshd sends commands to ssh. In other words, the loops in the respective sides should be switched.
Reversing this was the only way things made sense to me. If the reversal doesn't work [well] for your desired use case, the code below may still give you some ideas.
I solved the hang problem by introducing the concept of a flag character to denote end-of-output. I borrowed this concept from the PPP [point-to-point] protocol over RS-232.
The flag character is just a given value (e.g. 0x10) that is not likely to be part of normal data. Since your data is most likely ascii or utf-8, any [unused] chars in the range 0x00-0x1F may be used (i.e. don't use tab, cr, newline, etc).
If you need to transmit the flag character (i.e. your data has to be the full binary range 0x00-0xFF), I've included some packet encode/decode routines that implement the escape codes used in PPP above. I've coded them, but did not actually hook them in. In this case, the flag [and escape] chars can be any binary value [usually 0xFF and 0xFE respectively].
For simplicity, I combined both sides into a single .c file. Invoke the server with -s [first].
Anyway, here's the tested code [please pardon the gratuitous style cleanup]:
// inetpair/inetpair -- server/client communication
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
typedef unsigned char byte;
#define BUFMAX 1024
int port = 1234;
int opt_svr;
int opt_debug;
#define FLAG 0x10
#define ESC 0x11
#define ESC_FLAG 0x01
#define ESC_ESC 0x02
#define dbgprt(_fmt...) \
do { \
if (opt_debug) \
printf(_fmt); \
} while (0)
// client
int
client(void)
{
int sock;
struct sockaddr_in serv = { 0 };
char *cp;
char buf[BUFMAX + 1];
int nread;
int flag;
int exitflg;
sock = socket(AF_INET, SOCK_STREAM, 0);
serv.sin_family = AF_INET;
serv.sin_port = htons(port);
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sock, (struct sockaddr *) &serv, sizeof(serv));
while (1) {
cp = fgets(buf,BUFMAX,stdin);
if (cp == NULL)
break;
exitflg = (strcmp(buf,"exit\n") == 0);
// send the command
nread = strlen(buf);
write(sock, buf, nread);
if (exitflg)
break;
while (1) {
dbgprt("client: PREREAD\n");
nread = read(sock, buf, 1024);
dbgprt("client: POSTREAD nread=%d\n",nread);
if (nread <= 0)
break;
cp = memchr(buf,FLAG,nread);
flag = (cp != NULL);
if (flag)
nread = cp - buf;
write(1,buf,nread);
if (flag)
break;
}
}
close(sock);
return 0;
}
// server
int
server(void)
{
struct sockaddr_in serv_addr = { 0 };
int sock;
int acc_sock;
char buf[BUFMAX + 1];
char command[BUFMAX + 1];
ssize_t nread;
FILE *pin;
FILE *xfin;
char *cp;
struct sockaddr_in cli_addr = { 0 };
opt_debug = ! opt_debug;
dbgprt("[+] Starting\n");
sock = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(port);
bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
listen(sock, 128);
while (1) {
socklen_t cli_addrlen = sizeof(cli_addr);
dbgprt("[+] Waiting for connection\n");
acc_sock = accept(sock,(struct sockaddr *)&cli_addr,&cli_addrlen);
dbgprt("[+] Connected\n");
xfin = fdopen(acc_sock,"r");
while (1) {
dbgprt("[+] Waiting for command\n");
cp = fgets(buf,BUFMAX,xfin);
if (cp == NULL)
break;
cp = strchr(buf,'\n');
if (cp != NULL)
*cp = 0;
dbgprt("[+] Command '%s'\n",buf);
if (strcmp(buf,"exit") == 0)
break;
pin = popen(buf, "r");
while (1) {
cp = fgets(command, BUFMAX, pin);
if (cp == NULL)
break;
nread = strlen(command);
write(acc_sock, command, nread);
}
pclose(pin);
command[0] = FLAG;
write(acc_sock,command,1);
}
fclose(xfin);
close(acc_sock);
dbgprt("[+] Disconnect\n");
}
}
// packet_encode -- encode packet
// RETURNS: (outlen << 1)
int
packet_encode(void *dst,const void *src,int srclen)
{
const byte *sp = src;
byte *dp = dst;
const byte *ep;
byte chr;
int dstlen;
// encode packet in manner similar to PPP (point-to-point) protocol does
// over RS-232 line
ep = sp + srclen;
for (; sp < ep; ++sp) {
chr = *sp;
switch (chr) {
case FLAG:
*dp++ = ESC;
*dp++ = ESC_FLAG;
break;
case ESC:
*dp++ = ESC;
*dp++ = ESC_ESC;
break;
default:
*dp++ = chr;
break;
}
}
dstlen = dp - (byte *) dst;
dstlen <<= 1;
return dstlen;
}
// packet_decode -- decode packet
// RETURNS: (outlen << 1) | flag
int
packet_decode(void *dst,const void *src,int srclen)
{
const byte *sp = src;
byte *dp = dst;
const byte *ep;
byte chr;
int flag;
int dstlen;
// decode packet in manner similar to PPP (point-to-point) protocol does
// over RS-232 line
ep = sp + srclen;
flag = 0;
while (sp < ep) {
chr = *sp++;
flag = (chr == FLAG);
if (flag)
break;
switch (chr) {
case ESC:
chr = *sp++;
switch (chr) {
case ESC_FLAG:
*dp++ = FLAG;
break;
case ESC_ESC:
*dp++ = ESC;
break;
}
break;
default:
*dp++ = chr;
break;
}
}
dstlen = dp - (byte *) dst;
dstlen <<= 1;
if (flag)
dstlen |= 0x01;
return dstlen;
}
int
main(int argc, char **argv)
{
char *cp;
--argc;
++argv;
for (; argc > 0; --argc, ++argv) {
cp = *argv;
if (*cp != '-')
break;
switch (cp[1]) {
case 'd':
opt_debug = 1;
break;
case 'P':
port = atoi(cp + 2);
break;
case 's':
opt_svr = 1;
break;
}
}
if (opt_svr)
server();
else
client();
return 0;
}
The client never closes sock. Therefore the server's loop
while ((read(acc_sock, buf, 1024)) != 0) {
printf("%s", buf);
memset(buf, 0, sizeof(buf));
}
never terminates. You need some mechanism to inform server that all the command's output has been sent. Maybe something similar to HTTP chunked transfer encoding.

Initializing IP and PORT with variables in program

I am reading IPS and PORTS of few Sockets through this text file IP_CONFIG.txt
"192.168.128.3" IP_CSR
"192.168.128.2" IP_HMIR
"192.168.128.1" IP_OBCUR
"192.168.128.4" IP_ASRR
"127.0.0.1" IP_RSOR
"127.0.0.1" IP_RSO_DR
1901 PORT_CSR
1901 PORT_HMIR
1901 PORT_OBCUR
3567 PORT_ASRR
4444 PORT_RSOR
7777 PORT_RSO_DR
I implemented the code with the following way..
1) I saved all different IP addresses in different char strings and Ports with integers.
2) I call these variables when defining socket addresses.
Problem: Although it is giving correct values while calling these variables with printf , but i cann't load these variables while definining IP adrreses and PORTS of different systems
The complete CODE is here.
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#define MAX_DATE 100
# define BUFLEN 1024
#define ROW 11
#define COL 2
#define MAXWORDS 24
int main(int argc, char **argv)
{
//Declared variables
int sock, sock_RST; // socket name
int bytes_read; // variable for recvfrom
int addrlen; // length of address
int i = 0, j = 0, k = 0, z = 0; // counters
unsigned char ca[BUFLEN], last_OBCU_msg[BUFLEN], last_HMI_msg[BUFLEN],
rcvd_ASR_msg[BUFLEN]; // Data buffers
struct sockaddr_in server_addr, HMI_addr, OBCU_addr, ASR_addr, RSO_addr,
test_addr; //addresses IP PORT
struct sockaddr_in RSO_addr_d;
const char yes = 1;
int TAG_ASR = 0;
// Create a lof file
time_t now;
char the_date[MAX_DATE];
the_date[0] = '\0';
now = time(NULL );
strftime(the_date, MAX_DATE, "CS_LOG_%H_%M_%d_%m_%Y" ".txt", gmtime(&now));
chdir("/home/bsnayak/CS_LOG/");
FILE *file = fopen(the_date, "a");
//Read IPS and PORTS from a text file
//char* file="C:\\Documents and Settings\\Supernovah\\Desktop\\Supernovah.bin";
//FILE* pFile = fopen( file, "rb" );
char* file_text = "/home/bsnayak/IP_CONFIG.txt";
FILE *fp = fopen(file_text, "r");
int ii = 0, jj;
char *words = NULL, *word = NULL, c;
char *allwords[MAXWORDS];
while ((c = fgetc(fp)) != EOF)
{
ii++;
if (c == '\n')
{
c = ' ';
}
words = (char *) realloc(words, (ii + 1) * sizeof(char));
words[ii - 1] = c;
}
words[ii] = '\0';
word = strtok(words, " ");
ii = 0;
while (word != NULL && ii < MAXWORDS)
{
//printf("%s\n",word);
allwords[ii] = malloc(strlen(word) + 1);
strcpy(allwords[ii], word);
word = strtok(NULL, " ");
//allwords[ii][strlen(word)] = '\0';
ii++;
}
if (error_name)
printf("\nNow printing each saved string:\n");
/*for (jj=0; jj<ii; jj++){
printf("String %d: %s\n", jj, allwords[jj]);
//free(allwords[jj]);
}*/
char *IP_CS = allwords[0];
char *IP_HMI = allwords[2];
char *IP_OBCU = allwords[4];
char *IP_ASR = allwords[6];
char *IP_RSO = allwords[8];
char *IP_RSO_D = allwords[10];
int PORT_CS = atoi(allwords[12]);
int PORT_HMI = atoi(allwords[14]);
int PORT_OBCU = atoi(allwords[16]);
int PORT_ASR = atoi(allwords[18]);
int PORT_RSO = atoi(allwords[20]);
int PORT_RSO_D = atoi(allwords[22]);
//printf("The IPs are \n %s\n %s\n %s\n %s\n %s\n %s\n",IP_CS,IP_HMI,IP_OBCU,IP_ASR,IP_RSO,IP_RSO_D);
//printf("The PORTSs are \n %d\n %d\n %d\n %d\n %d\n %d\n",PORT_CS,PORT_HMI,PORT_OBCU,PORT_ASR,PORT_RSO,PORT_RSO_D);
//free(allwords[MAXWORDS]);
setbuf(stdout, NULL );
addrlen = sizeof(struct sockaddr_in);
// Create the Socket for all connections except RST
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("Socket Creation Error");
exit(1);
}
// Create the Socket for RST section
if ((sock_RST = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("Socket Creation Error");
exit(1);
}
// make CS socket non blocking and reusable
fcntl(sock, F_SETFL, O_NONBLOCK);
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &yes, sizeof(int)) < 0)
{
perror("Reuse option\n");
close(sock);
exit(1);
}
// make RST socket non blocking and reusable
fcntl(sock_RST, F_SETFL, O_NONBLOCK);
if (setsockopt(sock_RST, SOL_SOCKET, SO_REUSEADDR, (char*) &yes, sizeof(int))
< 0)
{
perror("Reuse option\n");
close(sock_RST);
exit(1);
}
printf("\nchecked1\n");
// Control server properties
bzero(&(server_addr.sin_zero), sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT_CS);
server_addr.sin_addr.s_addr = inet_addr(IP_CS); //inet_addr("192.168.128.3"); //
// HMI server properties
bzero(&(HMI_addr.sin_zero), sizeof(HMI_addr));
HMI_addr.sin_family = AF_INET;
HMI_addr.sin_port = htons(PORT_HMI);
HMI_addr.sin_addr.s_addr = inet_addr(IP_HMI);
// OBCU server properties
bzero(&(OBCU_addr.sin_zero), sizeof(OBCU_addr));
OBCU_addr.sin_family = AF_INET;
OBCU_addr.sin_port = htons(PORT_OBCU);
OBCU_addr.sin_addr.s_addr = inet_addr(IP_OBCU);
// ASR Server properties
bzero(&(ASR_addr.sin_zero), sizeof(ASR_addr));
ASR_addr.sin_family = AF_INET;
ASR_addr.sin_port = htons(PORT_ASR);
ASR_addr.sin_addr.s_addr = inet_addr(IP_ASR);
// RSO server properties
bzero(&(RSO_addr.sin_zero), sizeof(RSO_addr));
RSO_addr.sin_family = AF_INET;
RSO_addr.sin_port = htons(PORT_RSO);
RSO_addr.sin_addr.s_addr = inet_addr(IP_RSO);
// RSO destination properties (To which you send string content)
bzero(&(RSO_addr_d.sin_zero), sizeof(RSO_addr_d));
RSO_addr_d.sin_family = AF_INET;
RSO_addr_d.sin_port = htons(PORT_RSO_D);
RSO_addr_d.sin_addr.s_addr = inet_addr(IP_RSO_D);
// BIND Controlserver to the main socket
if (bind(sock, (struct sockaddr *) &server_addr, sizeof(struct sockaddr))
!= 0)
{
perror("Bind Error");
close(sock);
exit(1);
}
printf("checked2\n");
// Bind RSO for second socket
if (bind(sock_RST, (struct sockaddr *) &RSO_addr, sizeof(struct sockaddr))
!= 0)
{
perror("Bind Error");
close(sock_RST);
exit(1);
}
printf("checked3\n");
while (1)
{
addrlen = sizeof(test_addr);
bytes_read = recvfrom(sock, ca, BUFLEN, 0, (struct sockaddr *) &test_addr,
&addrlen);
//printf("checked4\n");
if (test_addr.sin_addr.s_addr == OBCU_addr.sin_addr.s_addr)
{
sendto(sock, ca, bytes_read, 0, (struct sockaddr *) &HMI_addr,
sizeof(HMI_addr));
memcpy(last_OBCU_msg, ca, sizeof(ca));
memset(ca, 0, BUFLEN);
printf("OHS Received\n");
}
}
fclose(file);
return 0;
}
But if i remove the varoable names and assign IP and Ports manually it works perfectly but why cann't use them as variables. Kindly suggest necessary modifications, suggestions..
The IP addresses as read from the file are enclosed by "-signs.
That is you do not pass "1.2.3.4" to inet_addr() but "\"1.2.3.4\"". And as "1.2.3.4" isn't a valid IP address (as 1.2.3.4 would be) the function fails.
Just printing them out or inspecting them using a debugger would have shown you this.

Select function behavior - Multi Client Quiz

I have to build a quiz application.
Details about the application:
1. Each client has to register to server before participating in Quiz. The server will ask
username from each user and generate temporary id for each user.
2. After Registration process clients, who are successfully connected to server will get
Question from server.
3. The client will reply with answer.
4. Server will receive answer from different clients with time stamps, and it will calculate
time difference of each client which is called ∆t.
Define such as:
∆t = (Time Question sent - Time answer received) - RTT
Where RTT is Round Trip Time
Server will select client, whose ∆t is minimum to all and reply with whatever score client will gain remains will not gain any score.
After sending Question server will wait Answer for a particular time periods called (T). If client did not reply within ‘T’ time period Server will skip that Question and goes to next Question.
Pseudocode of main loop in my server code
A. A main while loop which runs once for each question.
B. Inside this first I am accepting login for 10 seconds.
Here I am assigning user Id and all other initialization stuff.
C. Then using `select` to check which are available for writing.
To available connections I am checking `RTT` and then sending question to each user.
D. Then I am waiting for some time to get answers.
Here I am using `select` to determine where the answer is available to read.
E. Then I am repeating steps C. and D.
Problem:
When I connect only to a single client my code works fine for any number of question.
But when I test this code on multiple client with the same client code:
Login for everyone is OK.
Sending First Question to everyone works fine.
Then while waiting for the answer I only received answer from one client. Each client shows that answer is been sent. For second client the second select function doesn't return with readable data availability.
Why for multi-client my code is not working. (According to me the error is somewhere in getting answer).
My Code:
The structure of the packets send can be understand easily from the variable names.
Server.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <error.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>
#define PORT "3490" //the port user will be connecting to
#define BACKLOG 10 //how many pending connection queue will hold
#define maxUser 10
#define LOGIN_OK "OK"
#define LOGIN_WrongPassword "NP"
#define LOGIN_WrongUsername "NU"
#define MAX_USERS 10
#define MAX_ANSWER_TIME 10
#define LOGIN_WAIT 10
#define TOTAL_QUES "3"
int users[MAX_USERS][3] = {}; //index is userID, 0 is no user
void sigchld_handler(int s)
{
while(waitpid(-1, NULL, WNOHANG) > 0);
}
//get sockaddr, IPv4 or IPv6
int timer;
void alarm_handler(int s) {
timer = 0;
}
wrongRecv(ssize_t recvd, ssize_t expctd)
{
if(recvd != expctd)
{
printf("Recvd(%zd) bytes not equal to expected(%zd) bytes\n",recvd,expctd);
//getchar();
}
}
//void nextQues(char* quesMsg, char* ques, char* optA, char* optB, char* optC, char* optD)
int nextQues(char* quesMsg, int QID)
{
char ques[40], optA[10], optB[10], optC[10], optD[10], quesId[5];
sprintf(quesId,"%d",QID);
strncpy(ques, "This is the question?",22);
strncpy(optA, "OptionA", 7); strncpy(optB, "OptionB", 7); strncpy(optC, "OptionC", 7); strncpy(optD, "OptionD", 7);
strncpy(quesMsg,quesId,5);
strncpy(quesMsg + 05,ques,40);
strncpy(quesMsg + 45,optA,10);
strncpy(quesMsg + 55,optB,10);
strncpy(quesMsg + 65,optC,10);
strncpy(quesMsg + 75,optD,10);
return 0;
}
//void answerCheck(char* ques, char* optA, char* optB, char* optC, char* optD, char* usrResponse, int rtt, int timeTaken)
void answerCheck(int fd, char usrResponse[6], int rtt, int timeTaken)
{
int responseTime, i;
char actualAnswer[1];
char quesId[5];
printf("fd(%d) quesid(%s) response(%c) rtt(%d) timeTaken(%d)\n", fd, usrResponse, usrResponse[5], rtt, timeTaken );
strncpy(quesId, usrResponse, 5);
actualAnswer[0] = 'B';//we have quesId we can find actual answer on basis of it
if(actualAnswer[0] == usrResponse[5])
{
//printf("%s\n","+++++" );
responseTime = timeTaken - rtt;
//printf("Response Time(%d)\n",responseTime);
//save it with user id
//finding userid
for(i = 0; i < MAX_USERS; i++) {
if(users[i][1] == fd) {
users[i][2] = responseTime;//saving it
//printf("%d\n",i );
}
}
}
}
int compareAnswer() {
int i, min = 2 * MAX_ANSWER_TIME, userIndex;
for(i = 0; i < MAX_USERS; i++) {
if(users[i][2] < min) {
min = users[i][2];
userIndex = i;
}
}
//Increasing Score
users[userIndex][0]++;
//returning fd
return users[userIndex][1];
}
void users_deleteFd(int fd) {
int i;
for (i = 0; i < MAX_USERS; ++i)
{
if(users[i][1] == fd) {
users[i][1] =0;
return;
}
}
}
int rtt_check(int new_fd)
{
ssize_t send_ret, recv_ret;
char rtt_check[1];
time_t rtt1, rtt2;
rtt1 = time(NULL);
send_ret = send(new_fd, "r", 1, 0);
if(send_ret == 0)
{
return -2;
}
wrongRecv(send_ret, 1);
//printf("%s\n","Between two phase of rttCheck" );
recv_ret = recv(new_fd, rtt_check, 1,0);
rtt2 = time(NULL);
if(recv_ret == 0)
{
return -2;
}
wrongRecv(recv_ret,1);
//printf("diff(%d)\n",(int) difftime(rtt2,rtt1));
return (int) difftime(rtt2,rtt1);
}
int login(char user[], char pass[])
{
//for user
static int Id = 0; //when have function getUserID, make it not static and also remove Id++;
if(!strcmp(user,"abhishek") && !strcmp(pass,"abhishek")) {
//Id = getUserID(user);
return ++Id;
}else if(!strcmp(user,"abhishek")){
return 0; //wrong password
}
return -1; //wrong username
}
int totalQues;
int login_setup(int new_fd)
{
//login inititalizations
char login_det[16];
char username[9],password[9], login_statMsg[7], totalQuesMsg[5] = TOTAL_QUES;
totalQues = atoi(totalQuesMsg);
//for user
int userId;
//for wrongRecv
ssize_t send_ret,recv_ret;
//getting username and password
recv_ret = recv(new_fd,login_det,16,0);
if(recv_ret == 0)
{
return -2;
}
wrongRecv(recv_ret,16);
//extracting username nad password
strncpy(username,login_det,8);
strncpy(password,login_det+8,8);
username[8]='\0'; password[8]='\0';
//printf("username(%s) and password(%s)\n",username,password);
if( (userId = login(username,password)) > 0) {
//printf("%d\n",userId);
//sending status
strncpy(login_statMsg, LOGIN_OK, 2);
strncpy(login_statMsg + 2, totalQuesMsg , 5);
send_ret = send(new_fd, login_statMsg,7,0);
if(send_ret == 0)
{
return -2;
}
wrongRecv(send_ret,7);
//TODO error checking then handling if error
//users[userId][0] = 0; //score
users[userId][1] = new_fd; //file descriptor associated with this user
//users[userId][2] = 0; //answer time
return 1;
}
else if(userId == -1) { //wrong username
strncpy(login_statMsg, LOGIN_WrongUsername, 2);
strncpy(login_statMsg + 2, totalQuesMsg , 5);
send_ret = send(new_fd, login_statMsg,7,0);
if(send_ret == 0)
{
return -2;
}
wrongRecv(send_ret,7);
return 0;
}
else{
strncpy(login_statMsg, LOGIN_WrongPassword, 2);
strncpy(login_statMsg + 2, totalQuesMsg , 5);
send_ret = send(new_fd, login_statMsg,7,0);
if(send_ret == 0)
{
return -2;
}
wrongRecv(send_ret,7);
return 0;
}
//TODO erorr handling of above two case
//TODO make login a loop
}
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(void)
{
int listen_fd, new_fd; // listen on sock_fd, new connection on new_fd
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr;//connection's address info
socklen_t sin_size;
int yes=1;
char s[INET6_ADDRSTRLEN];
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;//IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if((rv = getaddrinfo(NULL,PORT, &hints, &servinfo)) != 0){ //getting which IPv server supports
fprintf(stderr, "getaddrinfo: %s\n",gai_strerror(rv));
return 1;
}
//loop through all the result and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next){
if((listen_fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){
perror("server : socket");
continue;
}
if(setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){
perror("set sockopt");
exit(1);
}
if(bind(listen_fd, p->ai_addr, p->ai_addrlen) == -1){
close(listen_fd);
perror("server: bind");
continue;
}
break;
}
if(p == NULL) {
fprintf(stderr, "server:failed to bind\n");
return 2;
}
freeaddrinfo(servinfo);//all done with this structure
if(listen(listen_fd, BACKLOG) == -1){
perror("listen");
exit(1);
}
//printf("listen_fd(%d)\n",listen_fd );
// sa.sa_handler = sigchld_handler; // reap all dead processes
// sigemptyset(&sa.sa_mask);
// sa.sa_flags = SA_RESTART;
// if(sigaction(SIGCHLD, &sa, NULL) == -1){
// perror("sigaction");
// exit(1);
// }
printf("server waiting for connections.....\n");
fd_set master; //master file descriptor list
fd_set read_fds; //temp file descriptor list for select()
int fdmax;
FD_ZERO(&master); //clear the master and temp sets
FD_ZERO(&read_fds);
FD_SET(listen_fd, &master);
//keep track of the bigge file descriptor
fdmax = listen_fd; // so far it is this one
ssize_t recv_ret, send_ret;
//for login
int loginStatus;
struct sigaction sa;
sa.sa_handler = alarm_handler;
sigemptyset(&sa.sa_mask);
//sa.sa_flags = SA_RESTART;
if(sigaction(SIGALRM, &sa, NULL) == -1){
perror("sigaction");
exit(1);
}
//login while
alarm(LOGIN_WAIT);//accepting login only for 10 seconds
timer = 1;
printf("\n-----------------------------Waiting for users to login for %d seconds.-----------------------------\n",LOGIN_WAIT);
while(timer) {
sin_size = sizeof their_addr;
new_fd = accept(listen_fd, (struct sockaddr *)&their_addr, &sin_size);
if(new_fd == -1){
//perror("accept");
break;// this break is very important , as we are using alarm(Signals) and accept is a blocking function
//If accept is in blocked sate and our signal comes then accept will exit returning error. So
//if error then we have to break else next satements will run on falsy values.
//In reality we dont need this as I alredy set the SA_RESTART flag in sigaction which means
//after returning from the signal handler restart the activity on which you are previously
//instead of starting execution from next line.
}else {
inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s);
printf("server : got connection from %s\n", s);
//LOGIN //need to call login function via thread because this
//may stop the function if user doesnot respond
loginStatus = login_setup(new_fd);
//adding to select checkup
if(loginStatus) {
printf("User Loginned Succesfully\n");
}
}
}
printf("-----------------------------Login Closed. Now starting the QUIZ.-----------------------------\n");
//for randome seek
srand(time(NULL));
//for main loop counter
int i, win_fd;
//for questions
int QID = 0;
int maxQues_Len = 40, maxOpt_len = 10, maxQuesId_len = 5;//including '\0' this time
char quesMsg[80], answer[6];//score doesnot include \0
//char ques[40], optA[10], optB[10], optC[10], optD[10];
//for time calculation of each answer
ssize_t time_ques, time_ans;
//getting all avialable participants
fdmax = 0;
FD_ZERO(&master);
for(i = 0; i < MAX_USERS; i++) {
if( (new_fd = users[i][1]) != 0){
FD_SET(new_fd, &master);
if(new_fd > fdmax)
fdmax = new_fd;
//printf("%d\n",new_fd);
}
}
int current_rtt;
//while for main quiz
while(totalQues--) {
//checking who are ready for witing
if(select(fdmax+1, NULL, &master, NULL, NULL) == -1){//here select will return withh all the descriptors which are
//ready to write , all others have to miss this question
perror("select");
exit(1);
}
//setting which question to send
QID++;
//for sending questions to all
for(i = 0; i <= fdmax; i++) {
if(FD_ISSET(i, &master)) {
//rtt check
current_rtt = rtt_check(i);
if(current_rtt == -2) {//connection closed
FD_CLR(i, &master);
users_deleteFd(i);
continue;
}
//setting question
//nextQues(quesMsg, ques, optA, optB, optC, optD);
nextQues(quesMsg, QID);
printf("Sending Question QID(%s) fd(%d)\n",quesMsg,i);
//send a question
time_ques = time(NULL);
send_ret = send(i, quesMsg, maxQues_Len + 4 * maxOpt_len + maxQuesId_len, 0);
if(send_ret == 0) {//connection closed
FD_CLR(i, &master);
users_deleteFd(i);
continue;
}
wrongRecv(send_ret, maxQues_Len + 4 * maxOpt_len + maxQuesId_len);
}
}
//ASSUMING Question is send ot all the users at same time
//receiving and waiting for answers
alarm(MAX_ANSWER_TIME);
timer = 1;
FD_ZERO(&read_fds);
read_fds = master;
// unsigned int qq = read_fds.fd_count;
// for (int ii = 0; ii < qq; ++ii)
// {
// printf("%d\n",read_fds.fd_array[i] );
// }
while(timer) {
//printf("HURRAY\n");
if(select(fdmax+1, &read_fds, NULL, NULL, NULL) <=0){
perror("select");
//exit(4);
break;//break is important. Explained above
}
for(i = 0; i <= fdmax; i++) {
//printf("Recving answer I(%d)\n",i);
if(FD_ISSET(i, &read_fds)) {
//receiving answer
//TODO if we get answer to wrong ques
printf("Recving answer I(%d) fdmax (%d)\n",i,fdmax);
recv_ret = recv(i,answer,6,0);
time_ans = time(NULL);
wrongRecv(recv_ret,6);
printf("%s\n",answer );
if(recv_ret == 0)//connection closed
{
FD_CLR(i, &read_fds);
FD_CLR(i, &master);
users_deleteFd(i);
continue;
}else if(recv_ret > 0){
if(QID == atoi(answer)) { //we have received the answer to this question so remove the user from wait answer loop
FD_CLR(i, &read_fds);
//printf("%s i(%d)\n","#######",i );
answerCheck(i ,answer, current_rtt, (int) difftime(time_ans,time_ques));
//printf("Answer(%c)\n",answer[0]);
}
else{//we have recvd something unexpectable so ignore for NOW
}
}
//time_t cccc = time(NULL);
//printf("%s I(%d)\n",ctime(&cccc),i);
}
}
}
//comparing answers
win_fd = compareAnswer();
//sending score
}
return 0;
}
Client.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define PORT "3490" //the port client will be connecting to
#define MAXDATASIZE 100 // max number of bytes we can get at once
//get sockaddr ,IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if(sa->sa_family ==AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
wrongRecv(ssize_t recvd, ssize_t expctd)
{
if(recvd != expctd)
{
printf("Recvd(%zd) bytes not equal to expected(%zd) bytes\n",recvd,expctd);
getchar();
}
}
void rtt_check(int sockfd)
{
ssize_t send_ret, recv_ret;
char rtt_check[1];
recv_ret = recv(sockfd, rtt_check, 1,0);
wrongRecv(recv_ret,1);
sleep(1);//to check
send_ret = send(sockfd, "r", 1, 0);
wrongRecv(send_ret, 1);
return;
}
int main(int argc, char *argv[])
{
int sockfd, numbytes;
char buf[MAXDATASIZE];
struct addrinfo hints, *servinfo, *p;
int rv;
char s[INET6_ADDRSTRLEN];
if(argc != 2) {
fprintf(stderr,"usage: client hostname\n");
exit(1);
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) {
fprintf(stderr,"getaddrinfo: %s\n",gai_strerror(rv));
return 1;
}
//lopp through all the results and connect to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){
perror("client: socket");
continue;
}
if(connect(sockfd, p->ai_addr, p->ai_addrlen) == -1){
close(sockfd);
perror("client: connect");
continue;
}
break;
}
if(p ==NULL) {
fprintf(stderr,"client: failed to connect\n");
return 2;
}
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), s, sizeof s);
printf("client : connecting to %s\n", s);
freeaddrinfo(servinfo); // all done with this structure
char login_det[17] = "abhishekabhishek";
char login_retMsg[7], login_stat[3], totalQuesMsg[5];
int totalQues;
//sending login details
ssize_t send_ret,recv_ret;
send_ret = send(sockfd, login_det,16,0);
wrongRecv(send_ret,16);
//receiving login status
recv_ret = recv(sockfd,login_retMsg,7,0);
wrongRecv(recv_ret,7);
strncpy(login_stat, login_retMsg, 2);
login_stat[2] = '\0';
printf("Login Status(%s)\n",login_stat);
strncpy(totalQuesMsg, login_retMsg + 2, 5);
totalQues = atoi(totalQuesMsg);
printf("totalQues(%d)\n",totalQues);
if(!strcmp(login_stat,"OK")) { //login ok
char quesId[5];
int maxQues_Len = 40, maxOpt_len = 10, maxQuesId_len = 5;//including '\0' this time
char quesMsg[80], scoreMsg[1];//score doesnot include \0
char ques[40], optA[10], optB[10], optC[10], optD[10];
char answer[6];
while(totalQues--) {
//checking rtt
rtt_check(sockfd);
//receving question
recv_ret = recv(sockfd, quesMsg, maxQues_Len + 4 * maxOpt_len + maxQuesId_len ,0);
wrongRecv(recv_ret, maxQues_Len + 4 * maxOpt_len + maxQuesId_len);
strncpy(quesId,quesMsg,5);
strncpy(ques, quesMsg + 05, 40);
strncpy(optA, quesMsg + 45, 10);
strncpy(optB, quesMsg + 55, 10);
strncpy(optC, quesMsg + 65, 10);
strncpy(optD, quesMsg + 75, 10);
printf("QUESID(%s) Question(%s), A(%s) , B(%s) , C(%s) , D(%s)\n", quesId, ques, optA, optB, optC, optD);
//choose answer
scoreMsg[0] = 'B';
strncpy(answer,quesId, 5);
answer[5] = scoreMsg[0];
sleep(5);
//sending answer
send_ret = send(sockfd, answer,6,0);
wrongRecv(send_ret,6);
printf("%s\n","Answer Message Sent" );
// if((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
// perror("recv");
// exit(1);
// }
// buf[numbytes] = '\0';
// printf("client: received '%s'\n",buf);
}
}
//TODO wrong login
close(sockfd);
return 0;
}
The problem is that the call to select in the answer getting loop is modifying read_fds to hold just the file descriptor of the first client(s) to respond. Since you don't reset read_fds before calling select again, it will not recognize the other clients' response.

Resources