How can I display the client IP address on the server side? - c

My mini project is on implementing a c socket program where multiple clients send files to two or three servers. i have implemented these. but for handling the client request i need to create a child process is it? how can i do that . like have to handle the request separately.please anybody guide me to do it.
server:
int main()
{
int sockfd, new_sockfd,x1,x2,log,n;
int server_len, client_len,len;
int cont,fh,cont2;
int result1;
struct sockaddr_in serveraddress;
struct sockaddr_in address;
struct sockaddr_in client_address;
FILE *ia_address;
char *fname = "/home/shishira/Desktop/packet_capture/info_agent_report.txt";
int buffsize=1024;
char buffer1[1024];
char buffer[1024];
char clntName[INET_ADDRSTRLEN];
if((sockfd = socket(AF_INET,SOCK_STREAM,0))>0)
printf("\n Socket was created\n");
/* Name the socket. */
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = ntohs(9734);
server_len = sizeof(address);
bind(sockfd, (struct sockaddr *)&address, server_len);
/* Create a connection queue and wait INFO_AGENT_REPORTS */
listen(sockfd, 5);
while(1)
{
char ch;
printf("\n\n Task agent waiting...\n");
/* Accept a connection to collect report from INFO_AGENT */
client_len = sizeof(client_address);
new_sockfd = accept(sockfd,(struct sockaddr *)&client_address, &client_len);
if (new_sockfd==-1) { perror("Connection Not Accepted!!"); return(1);}
else
{
printf("\n Information agent is connected\n");
if(inet_ntop(AF_INET,&client_address.sin_addr.s_addr,clntName,sizeof(clntName))!=NULL)
{
ia_address = fopen("info_agent_report.txt","a+");
fprintf(ia_address,"\nFrom InformationAgent:%s\n",clntName);
fclose(ia_address);
}
printf("\n Task agent received the contents and saved it in 'info_agent_report' file");
log=open("info_agent_report.txt",O_CREAT|O_RDWR|O_APPEND,0777);
if(log==-1)
{
perror("cannot open info_agent_report file\n");
return(1);
}
do
{
x1=read(new_sockfd, buffer1, 1024);
x2=write(log,buffer1,x1);
}
while (x1>0);
close(log);
close(new_sockfd);
}
/*this is to connect to other server */
/* connect socket to the interface server's socket. */
int interface_sockfd = socket(AF_INET,SOCK_STREAM,0);
serveraddress.sin_family = AF_INET;
serveraddress.sin_addr.s_addr = inet_addr("127.0.0.1");
serveraddress.sin_port = 9735;
len = sizeof(serveraddress);
//len=sizeof(address);
if((result1 = connect(interface_sockfd, (struct sockaddr *)&serveraddress, len))==0)
printf("\n Connecting to the Interface server\n");
if(result1 == -1)
{
perror(" Not able to connect to Interface Server!!!!\n");
}
fh = open(fname , O_RDONLY);
if(fh==-1)
{
perror(" INFO_AGENT_REPORT File is Not Opened!!\n");
return(1);
}
do
{
cont=read(fh, buffer, buffsize);
cont2=write(interface_sockfd,buffer,cont);
}
while (cont==1024);
close(fh);
printf("\n Task agent has sent 'info_agent_report' file to the Interface Server\n\n");
close(interface_sockfd);
}
}

getnameinfo() is more new-style.
You use it like
char clntName[INET6_ADDRSTRLEN];
char portName[6]; // I wonder if there is no appropriate constant...
if(getnameinfo(&client_address,sizeof client_address,clntName,sizeof(clntName),NULL,0,NI_NUMERICHOST|NI_NUMERICSERV|NI_NUMERICSCOPE)==0){
printf("Client = %s/%s\n",clntName,portName);
} else {
printf("Unable to get address\n");
}
Once you have done so, you won't have any difficulties mixing IPv4 and IPv6 calls.

Here is how : ( put this after accept ):
char clntName[INET_ADDRSTRLEN];
FILE *output;
if(inet_ntop(AF_INET,&client_address.sin_addr.s_addr,clntName,sizeof(clntName))!=NULL){
output = fopen("output.txt","a+");
fprintf(output,"%s%c%d",clntName,'/',ntohs(client_address.sin_port));
fclose(output);
} else {
printf("Unable to get address\n"); // i just fixed this to printf .. i had it as print before
}

Related

Select system call not scanning more than 2 descriptors

I am writing a Server program serving to Multiple client(max 5). As any client connects to server, server stores the descriptor into an array and checks for any activity in those descriptors via Select system call. But, it is only reading from any 2 clients only and rest client requests are not being served at all. Here is a code for Server
#define NUM_CLIENT 5
void main(int argc,char** argv)
{
int master_sock, newSocket, err;
struct sockaddr_in Server_addr, Client_addr;
char buf[100];
int i=0;
int activity;
//socket descriptors for select
fd_set readfd;
int client_fd[NUM_CLIENT]={-1,-1,-1,-1,-1};
//Socket creation
master_sock= socket(AF_INET,SOCK_STREAM,0);
if(master_sock<0){
perror("socket");
return;
}
//structure filling for listening to the port
Server_addr.sin_family = AF_INET;
Server_addr.sin_port = htons(atoi(argv[1]));
Server_addr.sin_addr.s_addr = INADDR_ANY;
//Binding to the Address and port filled in structure
err = bind(master_sock,(struct sockaddr*)&Server_addr,sizeof(Server_addr));
if(err<0){
perror("socket");
return;
}
printf("\nlistening to port");
err = listen(master_sock,NUM_CLIENT); //to inform, the willlingness to accept connections.
if(err<0){
perror("Listen");
return;
}
printf("\nAccepting connection");
while(1)
{
//Select modifies the objects in structure for any activity,
// So we need to load them again.
FD_ZERO(&readfd); //clearing the readfd list
FD_SET(master_sock,&readfd); //adding the descriptor for select to listen
for(i=0;i<NUM_CLIENT;i++){
if(client_fd[i] != -1){
FD_SET(client_fd[i],&readfd); //Add socket to the list
}
}
//Descriptors loaded..
//start Select operation....
activity = select(NUM_CLIENT+1,&readfd,NULL,NULL,NULL); //wait here until any activiy occurs
if(activity < 0){
perror("Select");break;
}
printf("\nactivity happened in socket...");
//If activity related to master socket i.e. New client is trying to connect.
if( FD_ISSET(master_sock,&readfd) ) {
printf("\nactivity in master socket...");
int len = sizeof(Client_addr);
//Accept the connection
newSocket = accept(master_sock, (struct sockaddr*)&Client_addr ,&len); //blocking call
if(newSocket<0){
perror("accept");return;
}
printf("\nNew connection accepted");
// puts("Receiving data");
if( recv(newSocket,buf,100,0) > 0 ) //blocking call
printf("\n%s",buf);
else
strcpy(buf,"hey");
// puts("Sending data");
if( send(newSocket,buf,strlen(buf),0) < 0 )
perror("send");
//creating client database of descriptors
for(i=0;i<NUM_CLIENT;i++){
printf("\nfd[%d] = %d\n",i,client_fd[i]);
if(client_fd[i] == -1){
client_fd[i]= newSocket;
//FD_SET(newSocket,&readfd); //Add socket to the list
//printf("\nfd[%d] = %d\n",i,client_fd[i]);
break;
}
}
}
//If activity(read or write) in other sockets, check it out
printf("\nChecking Activity in Other File Descriptors\n");
for(i=0;i<NUM_CLIENT;i++){
if(FD_ISSET(client_fd[i],&readfd)){
printf("\nactivity in client %d ...",i);
// puts("Receiving data");
if( recv(client_fd[i],buf,100,0) > 0 ) //blocking call
puts(buf);
else
strcpy(buf,"hello");
// puts("Sending data");
if( send(client_fd[i],buf,strlen(buf)+1,0) == -1 )
perror("send");
//printf("\n%s",buf);
}
}
}
}
And every client sends and receive data after sleeping for given time(provided via command line). Example: client1 5sec ,client2 4sec and so on...
The code for client is :
void main(int argc, char** argv)
{
int fd, err;
char buf[100],buf2[100];
struct sockaddr_in server;
fd = socket(AF_INET,SOCK_STREAM,0);
if(fd<0){
perror("socket");return;
}
I2A(buf,getpid()); //Integer to array conversion, returns array
strcat(buf,"Hello");
printf("%s\n",buf);
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[1])); //Host to network
server.sin_addr.s_addr = inet_addr("127.0.0.1");
printf("Connecting with server\n");
if( connect(fd, (struct sockaddr*)&server,sizeof(server) ) < 0) {
perror("connect");return;
}
printf("Connected with server\n");
while(1){
// printf("Sending data\n");
if( send(fd,buf,20,0) < 0)
perror("send");
// printf("Receiving data\n");
if( recv(fd,buf2,sizeof(buf2),0) >0 )
printf("%s\n",buf2);
sleep(atoi(argv[2]));
}
Thanks in advance.
This line is wrong:
activity = select(NUM_CLIENT+1,&readfd,NULL,NULL,NULL); //wait here until any activiy occurs
The first argument to select() should not be NUM_CLIENT+1, but rather the maximum file descriptor value (across all of the file descriptor values that you called FD_SET() on)), plus one.

client server socket programming c-linux

I'm writing a chat room program that communicates over network using TCP. If user provide ip address as a command line argument, the program would attempt to connect to that address. If not, server will wait for others to connect.
The server has no problem receiving whatever text message the client send. However, the client side only receives text messages from server only when it sends its own message. How do I fix that so that client side receives messages right away? This is my code
Server code:
#define MAX_CLIENTS 100
static unsigned int cli_count = 0;
static int uid = 10;
typedef struct {
struct sockaddr_in addr;
int connfd;
int uid;
char name[32];
} client_t;
client_t *clients[MAX_CLIENTS];
void queue_add(client_t *cl)
{
int i;
for(i=0;i<MAX_CLIENTS;i++)
{
if(!clients[i])
{
clients[i] = cl;
return;
}
}
}
void queue_delete(int uid)
{
int i;
for(i=0;i<MAX_CLIENTS;i++)
{
if(clients[i])
{
if(clients[i]->uid == uid)
{
clients[i] = NULL;
return;
}
}
}
}
void send_message_all(char *s)
{
int i;
for(i=0;i<MAX_CLIENTS;i++)
{
if(clients[i])
{
write(clients[i]->connfd, s, strlen(s));
}
}
}
void *hanle_client(void *arg)
{
char buff_in[256];
char buff_out[256];
int rlen;
cli_count++;
client_t *cli = (client_t *)arg;
sprintf(buff_out, "<<JOIN, HELLO %s\r\n", cli->name);
send_message_all(buff_out);
bzero(buff_in,sizeof(buff_in));
while((rlen = read( cli->connfd,buff_in,sizeof(buff_in)-1))>0)
{
sprintf(buff_out, "[%s] %s\r\n", cli->name, buff_in);
send_message_all(buff_out);
}
close(cli->connfd);
/* Delete client from queue and yeild thread */
queue_delete(cli->uid);
free(cli);
cli_count--;
pthread_detach(pthread_self());
return NULL;
}
int main(int argc, char *argv[])
{
int listenfd = 0, connfd = 0, portno;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
pthread_t tid;
if (argc < 2) {
printf("ERROR, no port provided\n");
exit(1);
}
//Create socket
listenfd= socket(AF_INET , SOCK_STREAM , 0);
if (listenfd == -1)
{
printf("Could not create socket");
}
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portno);
/* Bind */
if(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
{
perror("Socket binding failed");
return 1;
}
/* Listen */
if(listen(listenfd, 10) < 0)
{
perror("Socket listening failed");
return 1;
}
printf("<[SERVER STARTED]>\n");
socklen_t clilen = sizeof(cli_addr);
/* Accept clients */
while( (connfd = accept(listenfd, (struct sockaddr *)&cli_addr, (socklen_t*)&clilen)))
{
/* Client settings */
client_t *cli = (client_t *)malloc(sizeof(client_t));
cli->addr = cli_addr;
cli->connfd = connfd;
cli->uid = uid++;
sprintf(cli->name, "%d", cli->uid);
/* Add client to the queue and fork thread */
queue_add(cli);
pthread_create(&tid, NULL, &hanle_client, (void*)cli);
}
}
Client code:
int main(int argc , char *argv[])
{
int sockfd, portno ;
struct sockaddr_in serv_addr;
struct hostent *server;
char message[2000],server_reply[2000];
if (argc <3)
{
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(1);
}
portno = atoi(argv[2]);
//Create socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("ERROR opening socket");
exit(1);
}
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno);
//Connect to remote server
if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
{
perror("ERROR connecting");
exit(1);
}
puts("Connected\n");
//keep communicating with server
while(1)
{
//Receive a reply from the server
bzero(server_reply,2000);
if( recv(sockfd , server_reply , 2000,0) < 0)
{
puts("recv failed");
break;
}
printf("%s", server_reply);
server_reply[0]='\0';
//Send Message to server
printf("Enter Message:");
bzero(message,2000);
fgets(message, sizeof(message),stdin);
if(send(sockfd , message , strlen(message),0) < 0)
{
puts("Send failed");
return 0;
}
}
close(sockfd);
return 0;
}
I am not sure if I understood your problem correctly. But at a high level, I noticed that your hanleClient method calls close(cli->connfd) on the clients socket after calling sendall. After calling close, you are deleting the client details from the queue. This way, the client being deleted will never receive any future messages. Are you sure this is what you want?
Try removing these lines and check if that is what you want -
close(cli->connfd);
/* Delete client from queue and yeild thread */
queue_delete(cli->uid);
free(cli);
cli_count--;
This way, whenever the server receives a message, it will try to send it to all clients that are connected to the server.
Note: Your code is not thread safe and will result in unexpected behaviour since you are accessing global data from within threads without using mutexes.

how can i display client address using c socket program?

My project is : Client receives the raw packet from the Ethernet saves it in a file called 'sniff_data.bin' and sends it to the server. Server receives the contents processes the packet( distinguishes between tcp,icmp,udp etc) and saves in a text file called 'info_agent_ report. txt' file. i think there is some mistake in my code. can anybody please guide me , help me out.
int main()
{
int sockfd, new_sockfd,log,n,x1,x2;
int server_len, client_len,len;
int cont,fh,cont2,x;
int result1;
struct sockaddr_in serveraddress;
struct sockaddr_in address;
struct sockaddr_in client_address;
FILE *ia_address;
char *fname = "/home/shishira/Desktop/packet_capture/info_agent_report.txt";
int buffsize=1024;
char buffer1[1024];
char buffer[1024];
char clntName[INET_ADDRSTRLEN];
if((sockfd = socket(AF_INET,SOCK_STREAM,0))>0)
printf("\n ---------------------------Task Agent---------------------------\n");
printf("\n Socket was created\n");
/* Name the socket. */
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = htons(9734);
server_len = sizeof(address);
bind(sockfd, (struct sockaddr *)&address, server_len);
/* Create a connection queue and wait INFO_AGENT_REPORTS */
listen(sockfd, 5);
while(1)
{
char ch;
printf("\n\n Task agent waiting...\n");
/* Accept a connection to collect report from INFO_AGENT */
client_len = sizeof(client_address);
new_sockfd = accept(sockfd,(struct sockaddr *)&client_address, &client_len);
if (new_sockfd==-1) { perror("Connection Not Accepted!!"); return(1);}
else
{
// x=fork();
// if (x==0) // child process starts
// {
printf("\n Information agent is connected\n");
//for displaying the client address
if(inet_ntop(AF_INET,&client_address.sin_addr.s_addr,clntName,sizeof(clntName))!=NULL)
{
ia_address = fopen("info_agent_report.txt","a+");
fprintf(ia_address,"\nFrom InformationAgent:%s\n",clntName);
fclose(ia_address);
}
printf("\n Task agent processed the contents and saved it in 'info_agent_report'
file\n\n");
log=open("info_agent_report.txt",O_CREAT|O_RDWR|O_APPEND,0777);
if(log==-1)
{
perror("cannot open info_agent_report file\n");
return(1);
}
do
{
x1=read(new_sockfd, buffer1, 1024);
x2=write(log,buffer1,x1);
}
while (x1>0);
data_process();//for processing the packet
close(log);
// } child process ends
close(new_sockfd);
}
}
I have written the code for displaying the client address in info_agent_report.txt. but is not getting dispalyed :(
To display client name: ( put this after accept )
char clntName[INET_ADDRSTRLEN]; // String to contain client address
if (inet_ntop(AF_INET, &clntAddr.sin_addr.s_addr, clntName,sizeof(clntName)) != NULL){
printf("Handling client %s/%d\n", clntName, ntohs(clntAddr.sin_port));
}
Or this:
char clntName[INET6_ADDRSTRLEN];
char portName[6];
if(getnameinfo(&client_address,sizeof client_address,clntName,sizeof(clntName),NULL,0,NI_NUMERICHOST|NI_NUMERICSERV|NI_NUMERICSCOPE)==0){
printf("Client = %s/%s\n",clntName,portName);
} else {
printf("Unable to get address\n");
}

C - Server broadcasts IP for client

I need my server to broadcast a message (not that it matters but it contains its IP/port info). What I have currently is the working server broadcast, code below. I'm not sure about setting up the client because usually I would use the IP/port of the server which the client doesn't have until it receives the broadcast. The client never receives anything. Can someone tell me what is wrong.
Server:
struct sockaddr_in server, bcast;
int sockfd;
int blen = sizeof(bcast);
int svrlen = sizeof(server);
char buf[BUFLEN];
if((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
printf("Socket error.\n");
exit(1);
}
int broadcastPermission = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (void *)&broadcastPermission,sizeof(broadcastPermission)) < 0){
printf("Error setting socket options.");
}
memset(&bcast, 0, sizeof(bcast));
bcast.sin_family = AF_INET;
bcast.sin_port = htons(PORT);
bcast.sin_addr.s_addr = htonl(INADDR_ANY);
string bcastIP = BCASTIP;
if(inet_aton("255.255.255.255", &bcast.sin_addr) == 0){
printf("Broadcast Address error.");
exit(1);
}
if (bind(sockfd, (struct sockaddr*)&server, sizeof(server)) == -1){
printf("Port error.\n");
exit(1);
}
fflush(stdout);
if(int bytes = sendto(sockfd, ipinfo, sizeof(ipinfo), 0, (struct sockaddr*)&bcast, blen) == -1){
printf("Broadcast send error.");
}
else{
printf("Sent"):
}
Client:
struct sockaddr_in server;
int sockfd;
int bytes;
int svrlen = sizeof(server);
char buf[BUFLEN]
if((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
printf("Socket error.\n");
exit(1);
}
memset((char *)&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(BPORT);
server.sin_addr.s_addr = htonl(INADDR_ANY);
while(1){
printf("Waiting for broadcast...\n\n");
fflush(stdout);
memset(buf,0,BUFLEN);
bytes = recvfrom(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&server, (socklen_t*)&svrlen);
printf("Received");
}
Your client is not calling bind() on the socket before trying to receive data.
http://cs.baylor.edu/~donahoo/practical/CSockets/code/BroadcastReceiver.c shows the following example which you may find helpful:
void DieWithError(char *errorMessage); /* External error handling function */
int main(int argc, char *argv[])
{
int sock; /* Socket */
struct sockaddr_in broadcastAddr; /* Broadcast Address */
unsigned short broadcastPort; /* Port */
char recvString[MAXRECVSTRING+1]; /* Buffer for received string */
int recvStringLen; /* Length of received string */
if (argc != 2) /* Test for correct number of arguments */
{
fprintf(stderr,"Usage: %s <Broadcast Port>\n", argv[0]);
exit(1);
}
broadcastPort = atoi(argv[1]); /* First arg: broadcast port */
/* Create a best-effort datagram socket using UDP */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
DieWithError("socket() failed");
/* Construct bind structure */
memset(&broadcastAddr, 0, sizeof(broadcastAddr)); /* Zero out structure */
broadcastAddr.sin_family = AF_INET; /* Internet address family */
broadcastAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
broadcastAddr.sin_port = htons(broadcastPort); /* Broadcast port */
/* Bind to the broadcast port */
if (bind(sock, (struct sockaddr *) &broadcastAddr, sizeof(broadcastAddr)) < 0)
DieWithError("bind() failed");
/* Receive a single datagram from the server */
if ((recvStringLen = recvfrom(sock, recvString, MAXRECVSTRING, 0, NULL, 0)) < 0)
DieWithError("recvfrom() failed");
recvString[recvStringLen] = '\0';
printf("Received: %s\n", recvString); /* Print the received string */
close(sock);
exit(0);
}
I need my server to broadcast a message (not that it matters but it contains its IP/port info).
That sounds a lot like service discovery. You should really use the standard mDNS/Zeroconf protocol for that. You can use the Avahi library for that (or use the Avahi service on Linux or Zeroconf on MacOS X).

UDP multi-client chat server

I have a multi-client chat server and for some reason only the first client is being added. I used a tutorial to help get me started. I have included my code below. When I try and add another client it doesnt appear to be added. If I add one client I get a response from the server like I want but only the first message I enter then after that it stops sending correctly.
Server Code:
int main(void)
{
struct sockaddr_in my_addr, cli_addr[10],cli_temp;
int sockfd;
socklen_t slen[10],slen_temp;
slen_temp = sizeof(cli_temp);
char buf[BUFLEN];
int clients = 0;
int client_port[10];
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
{
printf("test\n");
err("socket");
}else{
printf("Server : Socket() successful\n");
}
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(PORT);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sockfd, (struct sockaddr* ) &my_addr, sizeof(my_addr))==-1)
{
err("bind");
}else{
printf("Server : bind() successful\n");
}
int num_clients = 0;
while(1)
{
//receive
printf("Receiving...\n");
if (recvfrom(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_temp, &slen_temp)==-1)
err("recvfrom()");
if (clients <= 10) {
cli_addr[clients] = cli_temp;
client_port[clients] = ntohs(cli_addr[clients].sin_port);
clients++;
printf("Client added\n");
//printf("%d",clients);
int i;
for(i=0;sizeof(clients);i++) {
sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr[i], sizeof(cli_addr[i]));
}
}
}
close(sockfd);
return 0;
}
I have included the client code as well in case it helps.
void err(char *s)
{
perror(s);
exit(1);
}
sig_atomic_t child_exit_status;
void clean_up_child_process (int signal_number)
{
/* Clean up the child process. */
int status;
wait (&status);
/* Store its exit status in a global variable. */
child_exit_status = status;
}
int main(int argc, char** argv)
{
struct sockaddr_in serv_addr;
int sockfd, slen=sizeof(serv_addr);
char buf[BUFLEN];
struct sigaction sigchld_action;
memset (&sigchld_action, 0, sizeof (sigchld_action));
sigchld_action.sa_handler = &clean_up_child_process;
sigaction (SIGCHLD, &sigchld_action, NULL);
int pid,ppid;
if(argc != 2)
{
printf("Usage : %s <Server-IP>\n",argv[0]);
exit(0);
}
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
err("socket");
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
if (inet_aton(argv[1], &serv_addr.sin_addr)==0)
{
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
pid = fork();
if (pid<0) {
err("Fork Error");
}else if (pid==0) {
//child process will receive from server
while (1) {
bzero(buf,BUFLEN);
//printf("Attempting to READ to socket %d: ",sockfd);
fflush(stdout);
//recvfrom here
if (recvfrom(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&serv_addr, &slen)==-1)
err("recvfrom()");
printf("The message from the server is: %s \n",buf);
if (strcmp(buf,"bye\n") == 0) {
ppid = getppid();
kill(ppid, SIGUSR2);
break;
}
}
}else {
//parent will send to server
while(1){
printf("Please enter the message to send: ");
bzero(buf,BUFLEN);
fgets(buf,BUFLEN,stdin);
printf("Attempting to write to socket %d: ",sockfd);
fflush(stdout);
//send to here
if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&serv_addr, slen)==-1)
{
err("sendto()");
}
}
}
close(sockfd);
return 0;
}
Several problems jump out at me. First, every time you receive a message it will consider that to be a new client. Instead of just incrementing the clients variable for a message, you'll need to scan through the array to see if the source address is already present. Second, sizeof(clients) will return a static value (probably 4) depending on how many bytes an int occupies on your machine. That loop should be for( int i = 0; i < clients; i++ ).
You also have a variable named num_clients which is not used. Is that supposed to be there for something and maybe is causing some confusion?
Finally, instead of using the magic value 10 all over the place, use #define MAX_CONNECTIONS 10 and then replace all those numbers with MAX_CONNECTIONS. It's a lot easier to read and change later.

Resources