Chat Server (Network Programming in C) - c

I have made the following chat server program in c. The Problem is that as soon as I run my client and 'Client Says :-' is displayed on the Client Screen, the server immediately displays 'Client Says :-', 'Server Says :-' without waiting for the Client to give the input and then process it and the program doesnot work after that no matter what I input.
I want my Client to ask for input then send it to server , The server should then display the Client's input and ask for it's own input. This should go on until anyone of them enters 'bye'.
//Chat Server
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<string.h>
#include<errno.h>
int main()
{
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd<0)
{
perror("Error in Creating Socket\n");
exit(-1);
}
struct sockaddr_in server,client;
bzero(&server,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(10000);
server.sin_addr.s_addr = INADDR_ANY;
if(bind(sockfd, (struct sockaddr*)&server, sizeof(server))<0)
{
perror("Error in Socket Binding\n");
exit(-1);
}
if(listen(sockfd,5)<0)
{
perror("Error in Listening\n");
exit(-1);
}
printf("Listening\n");
char clientsent[500];
char bhago[5] = "exit";
bhago[5] = '\0';
char serverinput[500];
while(1)
{
int acceptfd = accept(sockfd, (struct sockaddr*)&client, (socklen_t*)sizeof(client));
pid_t pid = fork();
if(pid == 0)//child process is executing
{
close(sockfd);
while(1)
{
bzero(&serverinput, 500);
bzero(&clientsent, 500);
int n = recv(acceptfd, clientsent,500,0);
printf("Client Says :-\n");
printf("%s",clientsent);
if(strcmp(clientsent,bhago) == 0)
{
close(acceptfd);
exit(0);
}
printf("Server Says :-\n");
int x = 0;
do{
serverinput[x]=getchar();
x++;
}while(x-1 != '\n');
send(acceptfd, serverinput, 500, 0);
if(strcmp(serverinput,bhago) == 0)
{
close(acceptfd);
exit(0);
}
}
}
close(acceptfd);
}
}
//Chat Client
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<string.h>
#include<errno.h>
int main()
{
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd<0)
{
perror("Error in Creating Socket\n");
exit(-1);
}
struct sockaddr_in server;
bzero(&server,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(10000);
server.sin_addr.s_addr = INADDR_ANY;
if(connect(sockfd, (struct sockaddr*)&server, sizeof(server))<0)
{
perror("Error in Connection\n");
exit(-1);
}
printf("Connection Established\n");
char clientinput[500];
char bhago[5] = "exit";
bhago[5] = '\0';
char serversent[500];
while(1)
{
bzero(&clientinput, 500);
bzero(&serversent, 500);
printf("Client Says :-\n");
int x = 0;
do{
clientinput[x]=getchar();
x++;
}while(x-1 != '\n');
send(sockfd, clientinput, 500, 0);
if(strcmp(clientinput, bhago) == 0)
{
close(sockfd);
exit(0);
}
printf("Server Said :-\n");
recv(sockfd, serversent, 500,0);
printf("%s",serversent);
if(strcmp(serversent, bhago) == 0)
{
close(sockfd);
exit(0);
}
}
close(sockfd);
}//main

For starters, the latter of those two lines
char bhago[5] = "exit";
bhago[5] = '\0';
invokes undefined behaviour by writing out of bhago's bounds by accessing the 6th element, with bhago being 5 elements wide. From now on anything can happen.
In C arrays' indexes are 0-based. The 1st element here is bhago[0].
And this
..., (socklen_t*)sizeof(client));
is plain horrible wrong. Do not blindly cast away compilation errors. A pointer is expected and the code passes a compile-time constant, invoking undefined behaviour again here. I'd expect the code to die with execution of this line immediately.
accept() expects a socklen_t * as last parameter, so pass one:
socklen_t socklen = sizeof client;
..., &socklen));

Related

How to run UDP client and server (in C) on two remote hosts?

I am new to socket programming. I wrote codes for UDP Client and Server which work fine on my computer. I want to run these programs on two different hosts, i.e. the Server on my computer and Client on my friend' computer. How do I do it without a router? Please mention if any specific changes are to be made in the code for the purpose.
Here's the code:
Receiver
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<string.h>
#include<unistd.h>
int main() {
int ret = socket(AF_INET, SOCK_DGRAM, 0);
if (ret == -1) {
printf("socket creation fails\n");
exit(0);
} else
printf("socket creation succeeds\n");
struct sockaddr_in sender;
int port;
printf("Enter port:");
scanf("%d", & port);
sender.sin_family = AF_INET;
sender.sin_port = htons(port);
sender.sin_addr.s_addr = INADDR_ANY;
int ret1;
ret1 = bind(ret, (struct sockaddr * ) & sender, sizeof(sender));
if (ret1 == -1) {
printf("socket binding fails\n");
exit(0);
}
printf("socket binding succeeds\n");
struct sockaddr_in receiver;
char str[15], str2[15];
int addrlen = sizeof(receiver);
while (1) {
int rec = recvfrom(ret, str, sizeof(str), 0, (struct sockaddr * ) & receiver, & addrlen);
printf("Received:");
str[rec] = '\0';
if (strcmp(str, "exit") == 0)
break;
if (rec == -1) {
printf("recvfrom fails\n");
exit(0);
}
printf("%s\n", str);
printf("Enter :");
scanf("%s", str2);
int recsend = sendto(ret, str2, strlen(str2), 0, (struct sockaddr * ) & receiver, sizeof(receiver));
if (recsend == -1) {
printf("sendto fails");
exit(0);
}
if (strcmp(str2, "exit") == 0)
break;
}
close(ret);
return 0;
}
Sender
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<string.h>
#include<unistd.h>
int main() {
int ret = socket(AF_INET, SOCK_DGRAM, 0);
if (ret == -1) {
printf("\nsocket creation fails");
exit(0);
} else
printf("\nsocket creation succeeds");
struct sockaddr_in receiver;
int port;
printf("\nEnter port:");
scanf("%d", & port);
receiver.sin_family = AF_INET;
receiver.sin_port = htons(port);
receiver.sin_addr.s_addr = INADDR_ANY;
char str[15], str2[15];
int addrlen1 = sizeof(receiver);
struct sockaddr_in sender;
int addrlen = sizeof(sender);
while (1) {
printf("Enter:");
scanf("%s", str);
int send = sendto(ret, str, strlen(str), 0, (struct sockaddr * ) & receiver, addrlen1);
if (send == -1) {
printf("sendto fails");
exit(0);
}
if (strcmp(str, "exit") == 0)
break;
int senrec = recvfrom(ret, str2, sizeof(str2), 0, (struct sockaddr * ) & sender, & addrlen);
printf("\n");
printf("Received:");
str2[senrec] = '\0';
if (strcmp(str2, "exit") == 0)
break;
if (senrec == -1) {
printf("recvfrom fails\n");
exit(0);
}
printf("%s\n", str2);
}
close(ret);
return 0;
}
Connect both to different networks and get your server's ip address.
Change your client's receiver ip and port to:
receiver.sin_addr.s_addr = inet_addr("8.8.8.8"); // Ip address of your server.
receiver.sin_port=htons(port); // Whatever port your server is listening to

The second connection in two-client socket program is rarely not accepted from the server

I am new to socket programming, so I'm sorry if this is a noob question.
I have a program in C for Linux, which connects two sockets from "server.c" to two "client.c"s with the help of fork(). It works just fine most of the time, but there are times when the second client gets stuck before the first recv() function. On these occasions, the server doesn't accept() the connection and I am confused as to what is truly happening and how I can fix it.
Since I don't know much about socket programming, any explanation could be useful.
Here is the codes for the server and the client:
server.c
int main(){
int server_socket, p1_socket, p2_socket;
int pid;
pid = fork();
if(pid<0)
printf("Fork failed.\n");
else if(pid==0){
//PLAYER 1
socket_creation_and_connection(&server_socket, &p1_socket);
connect_to_player(&p1_socket, 1);
}
else{
//PLAYER 2
socket_creation_and_connection(&server_socket, &p2_socket);
connect_to_player(&p2_socket, 2);
}
printf("Hello message sent from %d\n", pid);
return 0;
}
void connect_to_player(int *socket, int playerNo){
char buffer[256];
while(1){
send(*socket , (int *)&playerNo , sizeof(int) , 0);
recv(*socket, (int *)&buffer, 1024, 0);
printf("PlayerNo %d Message received from client %s\n", playerNo, buffer);
}
}
void socket_creation_and_connection (int *server_socket, int *new_socket){
struct sockaddr_in address;
int addrlen = sizeof(address);
printf("creating sth\n");
if ((*server_socket = socket(AF_INET, SOCK_STREAM, 0)) == 0){
perror("Failed to create socket.");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
if (bind(*server_socket, (struct sockaddr *)&address, sizeof(address))<0){
perror("Failed to bind.");
exit(EXIT_FAILURE);
}
if (listen(*server_socket, 3)<0){
perror("Failed to listen.");
exit(EXIT_FAILURE);
}
if ((*new_socket = accept(*server_socket, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0){
perror("Failed to accept.");
exit(EXIT_FAILURE);
}
printf("finished creating sth\n");
}
client.c
int main(){
int client_socket = 0;
char message[256];
socket_creation_and_connection(&client_socket);
int intbuf;
while(1){
recv(client_socket, (int *)&intbuf, sizeof(int), 0);
if(intbuf == 1)
printf("Received message from Player1\n");
else
printf("Received message from Player2\n");
printf("Type a string\n");
scanf("%s", message);
send(client_socket, message , strlen(message) , 0 );
sleep(1);
}
return 0;
}
void socket_creation_and_connection(int *client_socket){
struct sockaddr_in address;
if ((*client_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_port = htons(PORT);
if (connect(*client_socket, (struct sockaddr *)&address, sizeof(address)) < 0)
{
printf("Connection Failed.\n");
exit(EXIT_FAILURE);
}
}
Edit: PORT is defined along with the libraries like this.
#define PORT 8080

Couldn't receive message from a TCP client in C

I'm trying to create a server that can receive messages from multiple connected clients, but in my code, the recv() function always return -1. How can I make my server receive codes from the client?
This is my server. The recv() function is called in the while loop at the bottom.
I tried to use read(), but I couldn't find a way to make it unblocking. Is there any way to interpret this by using read()? If not, How can I fix this problem with recv() always returning -1, despite I have a new client connected and have a new message sent?
/*------------------Header Files----------------------------------------------------------------------*/
#define _GNU_SOURCE
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<errno.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
#include<sys/stat.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<arpa/inet.h>
/*-------------------Linked List------------------------------------------------------------------------*/
struct client_online{
int client_socket;
char* name;
struct client_online* next;
};
/*-------------------Global Variables-------------------------------------------------------------------*/
struct client_online* first_client = NULL;
/*-------------------Main Function----------------------------------------------------------------------*/
int main(int argc, char* argv[]){
// Cite: get help from office hour code
// Creating the socket
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
if(server_socket < 0){
perror("Error creating server socket");
return -1;
}
// Server address
struct sockaddr_in server_address;
memset(&server_address, 0, sizeof(struct sockaddr_in));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(atoi(argv[2]));
server_address.sin_addr.s_addr = inet_addr(argv[1]);
// Binding the socket
int binder = bind(server_socket, (const struct sockaddr *) &server_address, sizeof(server_address));
if(binder == -1){
perror("Error calling bind");
return -1;
}
// Listen to the socket
int listener = listen(server_socket, 50);
if(listener == -1){
perror("Error calling listen");
return -1;
}
// Client address
struct sockaddr_in client_address;
// Reading and writing
int quit = 0;
while(!quit){
// Check if there is a new connection
int client_address_size = sizeof(client_address);
int each_client_socket = accept4(server_socket,
(struct sockaddr*) &client_address,
&client_address_size,
SOCK_NONBLOCK);
// If there is a new connection, add client to linked list
if(each_client_socket >= 0){
if(first_client == NULL){
first_client = malloc(sizeof(*first_client));
first_client->client_socket = each_client_socket;
first_client->name = (char*)malloc(100);
strcpy(first_client->name,"User");
first_client->next = NULL;
free(first_client->name);
free(first_client);
}
else{
struct client_online* tracker = first_client;
while(tracker->next != NULL){
tracker = tracker->next;
}
struct client_online* new_client;
new_client = malloc(sizeof(*new_client));
new_client->client_socket = each_client_socket;
new_client->name = (char*)malloc(100);
strcpy(new_client->name, "User");
new_client->next = NULL;
tracker->next = new_client;
free(new_client->name);
free(new_client);
}
}
// Check if there are messages recieved
struct client_online* checker = first_client;
while(checker != NULL){
char client_response[256];
char toSend[256];
bzero(client_response, sizeof(client_response));
int receiver = recv(checker->client_socket,
client_response,
sizeof(client_response),
MSG_DONTWAIT);
printf("%d\n", receiver);
if(receiver > 0){
printf("message received\n");
snprintf(toSend, sizeof(toSend), "%s: %s\n", checker->name, client_response);
struct client_online* sender = first_client;
while(sender != NULL){
send(sender->client_socket, toSend, sizeof(toSend), MSG_DONTWAIT);
}
}
checker = checker->next;
}
sleep(1);
}
return 0;
}
Here is my client
/*----------------------------------------------------Header Files----------------------------------------*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
#include<sys/stat.h>
#include<netinet/ip.h>
#include<arpa/inet.h>
#define _GNU_SOURCE
/*----------------------------------------------------Main Function--------------------------------------*/
int main(int argc, char* argv[]){
// Seek help from office hour codes
// Create the client socket
int client_socket = socket(AF_INET, SOCK_STREAM, 0);
if(client_socket < 0){
perror("Error creating client socket");
return -1;
}
// Construct the address of the connection
struct sockaddr_in client_address;
memset(&client_address, 0, sizeof(struct sockaddr_in));
client_address.sin_family = AF_INET;
client_address.sin_port = htons(atoi(argv[2]));
client_address.sin_addr.s_addr = inet_addr(argv[1]);
// Connect the client to the server
int connecter = connect(client_socket,
(const struct sockaddr*) &client_address,
sizeof(struct sockaddr_in));
if(connecter < 0){
perror("Error connecting to server");
}
// Reading and writing
int quit = 0;
while(!quit){
// Read from command line
char client_message[256];
memset(&client_message, 0, sizeof(client_message));
int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
int reader = read(STDIN_FILENO, client_message, sizeof(client_message));
if (reader > 0) {
// Writing normal message
send(client_socket, client_message, 1, MSG_WAITALL);
}
//
sleep(1);
}
return 0;
}
Since you are passing MSG_DONTWAIT to your recv call, if there is nothing to receive from the client yet, the call will return an error to indicate that fact.
If you are using polling mechanism, like epoll, then you would typically wait for a readable notification. Once the notification is received, you can retry the recv call. I don't see any use of a polling mechanism in your code.
Alternatively, you can spawn a thread for each new connection, and use blocking calls to recv (omit the MSG_DONTWAIT flag).

gets not working in TCP/IP chat program

/* Server Code */
#include<stdio.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<pthread.h>
#define MAXSIZE 50
void transmit();
void Recieve();
int sockfd, newsockfd, retval;
socklen_t actuallen;
int recedbytes, sentbytes;
struct sockaddr_in serveraddr, clientaddr;
// char buff[MAXSIZE];
int a = 0, port_no;
main()
{
printf("Enter port number: ");
scanf("%d",&port_no);
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-1) {
printf("\nSocket creation error");
exit(-1);
}
serveraddr.sin_family=AF_INET;
serveraddr.sin_port=htons(port_no);
serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);
retval= bind(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
if(retval == -1) {
printf("Binding error");
close(sockfd);
exit(0);
}
retval = listen(sockfd, 1);
if (retval == -1) {
close(sockfd);
exit(0);
}
actuallen = sizeof(clientaddr);
newsockfd = accept(sockfd, (struct sockaddr*)&clientaddr, &actuallen);
if(newsockfd == -1) {
close(sockfd);
exit(0);
}
int i=1;
pid_t pid = fork();
if(pid == 0)
transmit();
else
Recieve();
close(newsockfd);
close(sockfd);
}
void Recieve()
{
char buff[50]; int f=1;
while(f)
{
recedbytes=recv(newsockfd,buff,sizeof(buff),0);
if(recedbytes == -1) {
close(sockfd);
close(newsockfd);
exit(0);
}
printf("recdbytes: %d\n", recedbytes);
if(strcmp(buff, "Stop") == 0)
{
puts("Closing");
strcpy(buff,"Stop");
sentbytes=send(newsockfd,buff,sizeof(buff),0);
if(sentbytes == -1) {
close(sockfd);
close(newsockfd);
exit(0);
}
f=0;
}
else {
char cl[]="Client: ";
strcat(cl,buff);
puts(cl);
}
}
}
void transmit()
{
char buff[50];
while(1)
{
// printf("%s","You: ");
gets(buff);
sentbytes = send(newsockfd, buff, sizeof(buff), 0);
if(sentbytes == -1) {
close(sockfd);
close(newsockfd);
exit(0);
}
}
}
/* Client Code */
#include<stdio.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<pthread.h>
#define MAXSIZE 50
void transmit();
void Recieve();
int sockfd, retval;
int recedbytes, sentbytes;
struct sockaddr_in serveraddr;
// char buff[MAXSIZE];
main()
{
int port_no;
printf("Enter port number:");
scanf("%d",&port_no);
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd == -1) {
printf("\nSocket creation error");
exit(-1);
}
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(port_no);
serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
retval = connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
if(retval == -1) {
printf("Connection error"); close(sockfd);
exit(0);
}
int i = 1;
pid_t pid = fork();
if(pid == 0)
transmit();
else
Recieve();
printf("\n");
close(sockfd);
}
void Recieve()
{
char buff[50];
int f=1;
while(f)
{
recedbytes = recv(sockfd, buff, sizeof(buff), 0);
if(recedbytes == -1) {
close(sockfd);
exit(0);
}
printf("recdbytes: %d\n",recedbytes);
if(strcmp(buff, "Stop") == 0)
{
puts("Closing");
f = 0;
strcpy(buff, "Stop");
sentbytes = send(sockfd, buff, sizeof(buff), 0);
if(sentbytes == -1) {
close(sockfd);
exit(0);
}
}
else {
char sr[] = "Server :";
strcat(sr, buff);
puts(sr);
}
}
}
void transmit()
{
char buff[50];
while(1)
{
// printf("%s","You: ");
gets(buff);
sentbytes = send(sockfd, buff, sizeof(buff), 0);
if(sentbytes == -1) {
close(sockfd);
exit(0);
}
}
}
I am trying to create a chat server/client program using TCP/IP and process creation in C (linux).
It seems like the gets(buff) in transmit function of both the Client and Server Programs is not functioning as blocking and send(..) function is transmitting an empty buff.
As a result, "Client:" or "Server:" in server program and client program respectively is being printed even if no data has actually been sent from the counterpart program.
recedbytes=recv(newsockfd,buff,sizeof(buff),0);
if(recedbytes == -1) {
close(sockfd);
close(newsockfd);
exit(0);
}
printf("recdbytes: %d\n", recedbytes);
if(strcmp(buff, "Stop") == 0)
How are you expecting strcmp to know the length of the received string? You never did anything with recedbytes.
You also have numerous other bugs. You are expecting recv to somehow receive messages, despite the fact that you've never implemented any message protocol.
If you want to send and receive messages, you have to do three things:
Precisely define what a "message" is.
Write code to send a message.
Write code to receive a message.
There's no evidence in the code you've done any of these things. If your definition of a message is "precisely 50 bytes, always including a zero byte that marks the end of the data the receiver should process", then you may be okay on 1 and 2, but you definitely haven't done 3.

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