Broadcasting a message to multiple clients from a server using UDP protocol - c

i have two code here for a UDP chat with a broadcasting mechanism where the server can broadcast a message to all clients simultaneously
Server code...
#include<stdio.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
int main(int argc, char *argv[] )
{
struct sockaddr_in client,server;
int s,n;
char b1[100],b2[100];
s=socket(AF_INET,SOCK_DGRAM,0);
server.sin_family=AF_INET;
server.sin_port=htons(2000);
server.sin_addr.s_addr=inet_addr("127.0.0.1");
bind(s,(struct sockaddr *)&server,sizeof(server));
printf("\nServer ready,waiting for client....\n");
n=sizeof(client);
int sock; /* Socket */
struct sockaddr_in broadcastAddr; /* Broadcast address */
char *broadcastIP; /* IP broadcast address */
unsigned short broadcastPort; /* Server port */
char *sendString; /* String to broadcast */
int broadcastPermission; /* Socket opt to set permission to broadcast */
unsigned int sendStringLen; /* Length of string to broadcast */
if (argc < 4) /* Test for correct number of parameters */
{
fprintf(stderr,"Usage: %s <IP Address> <Port> <Send String>\n", argv[0]);
exit(1);
}
broadcastIP = argv[1]; /* First arg: broadcast IP address */
broadcastPort = atoi(argv[2]); /* Second arg: broadcast port */
sendString = argv[3]; /* Third arg: string to broadcast */
/* Create socket for sending/receiving datagrams */
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
broadcastPermission = 1;
while(1)
{
recvfrom(s,b1,sizeof(b1),0,(struct sockaddr *) &client,&n);
if(!(strcmp(b1,"end")))
break;
printf("\nClient:%s",b1);
printf("\nServer:");
gets(b2);
sendto(s,b2,sizeof(b2),0,(struct sockaddr *) &client,n);
broadcastPermission = 1;
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (void *) &broadcastPermission,sizeof(broadcastPermission));
/* Construct local address structure */
//memset(&broadcastAddr, 0, sizeof(broadcastAddr)); /* Zero out structure */
broadcastAddr.sin_family = AF_INET; /* Internet address family */
broadcastAddr.sin_addr.s_addr = inet_addr(broadcastIP);/* Broadcast IP address */
broadcastAddr.sin_port = htons(broadcastPort); /* Broadcast port */
sendStringLen = strlen(sendString);
for (;;) /* Run forever */
{
/* Broadcast sendString in datagram to clients every 3 seconds*/
sendto(sock, sendString, sendStringLen, 0, (struct sockaddr *) &broadcastAddr, sizeof(broadcastAddr));
// DieWithError("sendto() sent a different number of bytes than expected");
//sleep(3); /* Avoids flooding the network */
}
}
}
Client code...
#include<stdio.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#define MAXRECVSTRING 255
int main(int argc , char argv[])
{
struct sockaddr_in client,server;
int s,n;
char b1[100],b2[100];
s=socket(AF_INET,SOCK_DGRAM,0);
server.sin_family=AF_INET;
server.sin_port=htons(2000);
server.sin_addr.s_addr=inet_addr("127.0.0.1");
printf("\nClient ready....\n");
n=sizeof(server);
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);
}
printf("\nClient ready…11111.\n");
broadcastPort = htons(argv[1]); /* First arg: broadcast port */
printf("\nClient ready….1\n");
/* Create a best-effort datagram socket using UDP */
if(sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)<0)
printf("no sock created");
printf("\nClient ready….2\n");
while(1)
{
printf("\nClient:");
gets(b2);
sendto(s,b2,sizeof(b2),0,(struct sockaddr *) &server,n);
if(strcmp(b2,"end")==0)
break;
recvfrom(s,b1,sizeof(b1),0,NULL,NULL);
printf("\nServer:%s",b1);
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 */
bind(sock, (struct sockaddr *) &broadcastAddr, sizeof(broadcastAddr));
/* Receive a single datagram from the server */
recvStringLen = recvfrom(sock, recvString, MAXRECVSTRING, 0, NULL, 0);
recvString[recvStringLen] = '\0';
printf("Received: %s\n", recvString); /* Print the received string */
}
close(sock);
}
These code run without any error but when i send a string from client to the server the server is unable to receive the string and vice versa.
If someone could help me out as to why this is happening.
i am running both the server and client on the same system in different terminal windows..hence the local host address

Some platforms, e.g. Windows, won't receive broadcasts unless the socket is bound to INADDR_ANY, i.e. 0.0.0.0.

To start with:
server.sin_port=2000;
You forget to make this network-order.

In your server code:
The socket is not bound to any IP address. Although it broadcasts the message and the client receives; the vice-versa won't work.
Thus, bind your server and client side sockets to 2 different IP addresses.
When the server broadcasts the message, use appropriate broadcast address (see the subnet of the server-client IP) in the sendto function.

Related

multicast data from specific ip address

For example I am having two different segment IP of same server 172.17.8.90 172.19.8.100. Now, I want my program to send multicast from only 172.19.8.100 this ip. Currently my program is sending multicast from 172.17.8.90 which is not allowed to send multicast because of this, i want multicast data from specific IP
#include <stdio.h> /* for fprintf() */
#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
#include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
#include <stdlib.h> /* for atoi() and exit() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for sleep() */
void DieWithError(char *errorMessage) /* External error handling function */
{
fprintf(stderr,"Dieing baby\n");
}
int main(int argc, char *argv[])
{
int sock; /* Socket */
struct sockaddr_in multicastAddr; /* Multicast address */
char *multicastIP; /* IP Multicast address */
unsigned short multicastPort; /* Server port */
char *sendString; /* String to multicast */
unsigned char multicastTTL; /* TTL of multicast packets */
unsigned int sendStringLen; /* Length of string to multicast */
if ((argc < 4) || (argc > 5)) /* Test for correct number of parameters */
{
fprintf(stderr,"Usage: %s <Multicast Address> <Port> <Send String> [<TTL>]\n",
argv[0]);
exit(1);
}
multicastIP = argv[1]; /* First arg: multicast IP address */
multicastPort = atoi(argv[2]); /* Second arg: multicast port */
sendString = argv[3]; /* Third arg: String to multicast */
if (argc == 5) /* Is TTL specified on command-line? */
multicastTTL = atoi(argv[4]); /* Command-line specified TTL */
else
multicastTTL = 1; /* Default TTL = 1 */
/* Create socket for sending/receiving datagrams */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
DieWithError("socket() failed");
/* Set TTL of multicast packet */
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (void *) &multicastTTL,
sizeof(multicastTTL)) < 0)
DieWithError("setsockopt() failed");
/* Construct local address structure */
memset(&multicastAddr, 0, sizeof(multicastAddr)); /* Zero out structure */
multicastAddr.sin_family = AF_INET; /* Internet address family */
multicastAddr.sin_addr.s_addr = inet_addr(multicastIP);/* Multicast IP address */
multicastAddr.sin_port = htons(multicastPort); /* Multicast port */
sendStringLen = strlen(sendString); /* Find length of sendString */
for (;;) /* Run forever */
{
/* Multicast sendString in datagram to clients every 3 seconds */
if (sendto(sock, sendString, sendStringLen, 0, (struct sockaddr *)
&multicastAddr, sizeof(multicastAddr)) != sendStringLen)
DieWithError("sendto() sent a different number of bytes than expected");
sleep(3);
}
}
When sending out multicast packets, the OS will by default chose one particular interface to send from. To change the outgoing interface, you need to set the IP_MULTICAST_IF option:
struct in_addr multi_out;
multi_out.s_addr = inet_addr("172.19.8.100");
if (setsockopt(sock,IPPROTO_IP,IP_MULTICAST_IF, (char *)&multi_out, sizeof(multi_out)) == -1) {
perror("error setting IP_MULTICAST_IF option");
exit(1);
}
Also be sure to use the perror function as above for error checking to see why a particular library call failed.

Checking return address in recvfrom() (C UDP Sockets)

This pertains to attempting to validate the return address in recvfrom() (the fifth argument to the function) in this UDP echo client:
While I can send data to the server and receive return communications correctly, I'm having trouble validating the return IP address when comparing the fromAddr.sin_addr and echoServAddr.sin_addr.
The goal here is to compare the address in the structure that was used in sendto() and the address in the structure returned from recvfrom() to validate the echo reply from the server indeed came from where the initial transmission from the client was sent (A rudimentary POC that there wasn't a Man In The Middle).
What should I be looking at in order to appropriately validate the return address as it is returned from recvfrom() matches the address transmitted to as referenced in the sendto() call?
#include <stdio.h> /* for printf() and fprintf() */
#include <sys/socket.h> /* for socket(), connect(), sendto(), and recvfrom() */
#include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
#include <stdlib.h> /* for atoi() and exit() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */
#define ECHOMAX 255 /* Longest string to echo */
void DieWithError(char *errorMessage); /* External error handling function */
int main(int argc, char *argv[])
{
int sock; /* Socket descriptor */
struct sockaddr_in echoServAddr; /* Echo server address */
struct sockaddr_in fromAddr; /* Source address of echo */
unsigned short echoServPort; /* Echo server port */
unsigned int fromSize; /* In-out of address size for recvfrom() */
char *servIP; /* IP address of server */
char *echoString; /* String to send to echo server */
char echoBuffer[ECHOMAX+1]; /* Buffer for receiving echoed string */
int echoStringLen; /* Length of string to echo */
int respStringLen; /* Length of received response */
// manage the command line arguments and errors
if ((argc < 3) || (argc > 4)) {
fprintf(stderr, "Usage: %s <Server IP> <Echo Word> [<Echo Port>]\n",
argv[0]);
exit(1);
}
// load servIP
servIP = argv[1];
// load echoString
echoString = argv[2];
// check echoString and error if too long
echoStringLen = strlen(echoString);
if (!(echoStringLen <= 255)) {
DieWithError("BUFFER EXCEEDED ERROR");
}
// load port
if (argc == 4)
echoServPort = atoi(argv[3]);
else
echoServPort = 7;
// create the socket
if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
DieWithError("SOCKET CREATION ERROR");
}
/* Construct the server address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet addr family */
echoServAddr.sin_addr.s_addr = inet_addr(servIP); /* Server IP address */
echoServAddr.sin_port = htons(echoServPort); /* Server port */
// send the string
inet_pton(AF_INET, servIP, &echoServAddr.sin_addr);
if ((sendto(sock, echoString, strlen(echoString), 0, (struct sockaddr *)
&echoServAddr, sizeof(echoServAddr))) < 0) {
DieWithError("SEND ERROR");
}
// recieve a response
respStringLen = recvfrom(sock, echoBuffer, sizeof(echoBuffer), 0,
(struct sockaddr *) &fromAddr, &fromSize);
if (respStringLen < 0) {
DieWithError("RECV ERROR");
}
// print the message sent
printf("SENT FROM CLIENT: '%s'\n", echoString);
// print the message recieved
echoBuffer[respStringLen] = '\0';
printf("RECEIVED FROM SERVER: '%s'\n", echoBuffer);
// check if from the correct server
if ((struct sockaddr *) &echoServAddr.sin_addr != (struct sockaddr *) &fromAddr.sin_addr) {
DieWithError("INVALID RETURN ADDRESS");
}
// close the socket
close(sock);
// exit the program
exit(0);
}
If the source IP/port of the incoming packet is the same as the destation IP/port of the packet you sent, then the sin_addr and sin_port fields of echoServAddr and fromAddr should match.
This line of code however doesn't do that:
if ((struct sockaddr *) &echoServAddr.sin_addr != (struct sockaddr *) &fromAddr.sin_addr) {
This is comparing the address of echoServAddr.sin_addr against the address of fromAddr.sin_addr. Because these are two separate variables, this will always be false. You instead want:
if ((echoServAddr.sin_addr.s_addr != fromAddr.sin_addr.s_addr) ||
(echoServAddr.sin_port != fromAddr.sin_port))

UDP Socket Programming - recvfrom() one Port and sendto() other Port

UDP Socket Programming - Server listening on Port 5000 - Client listening on Port 6000
recvfrom() from one Port - 5000
sendto() to other Port - 6000 to the same client.
Server.c
#include <stdio.h> /* for printf() and fprintf() */
#include <sys/socket.h> /* for socket() and bind() */
#include <arpa/inet.h> /* for sockaddr_in and inet_ntoa() */
#include <stdlib.h> /* for atoi() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */
#define MAXSIZE 255 /* Longest string */
#define SRC_PORT 5000
#define DST_PORT 6000
int main(int argc, char *argv[])
{
int sock; /* Socket */
struct sockaddr_in ServAddr; /* Local address */
struct sockaddr_in ClntAddr; /* Client address */
socklen_t CliAddrLen; /* Length of incoming message */
char recBuffer[MAXSIZE]; /* Buffer for echo string */
int recvMsgSize; /* Size of received message */
int i;
/* Create socket for sending/receiving datagrams */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
DieWithError("socket() failed");
/* Construct local address structure */
memset(&ServAddr, 0, sizeof(ServAddr)); /* Zero out structure */
ServAddr.sin_family = AF_INET; /* Internet address family */
ServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
ServAddr.sin_port = htons(SRC_PORT); /* Local port */
/* Construct address structure */
memset(&ClntAddr, 0, sizeof(ClntAddr)); /* Zero out structure */
ClntAddr.sin_family = AF_INET; /* Internet address family */
ClntAddr.sin_addr.s_addr = inet_addr("192.168.1.*");
ClntAddr.sin_port = htons(DST_PORT);
/* Bind to the local address */
if (bind(sock, (struct sockaddr *) &ServAddr, sizeof(ServAddr)) < 0)
DieWithError("bind() failed");
for (;;) /* Run forever */
{
printf("Listening on UDP:5000 \n");
/* Set the size of the in-out parameter */
cliAddrLen = sizeof(ClntAddr);
/* Block until receive message from a client */
if ((recvMsgSize = recvfrom(sock, recBuffer, MAXSIZE, 0,(struct sockaddr *) &ClntAddr, &cliAddrLen)) < 0)
DieWithError("recvfrom() failed") ;
printf("Handling Client: %s\n", inet_ntoa(ClntAddr.sin_addr));
printf("Received Data: %s",recBuffer);
printf("\n");
/* Send response datagram back to the client */
if (sendto(sock, recBuffer, MAXSIZE, 0, (struct sockaddr *) & ClntAddr, sizeof(ClntAddr)) < 0)
DieWithError("sendto() failed");
}
/* NOT REACHED */
}
It works perfectly. Client and Server programming using different ports for sending and receiving the data.
Thank you
Regards
this is wrong
lntAddr.sin_addr.s_addr = inet_addr("CLIENT_IP");
inet_addr takes a dotted ip address not a host name

C socket programming no port entered

I'm trying to set a default port number for when no port is entered in C socket programming. Does anyone know how I can do this? I keep getting segmentation fault on attempts.
Code:
#define PORT 12345
int main(int argc, char *argv[]) {
/* Thread and thread attributes */
pthread_t client_thread;
pthread_attr_t attr;
int sockfd, new_fd; /* listen on sock_fd, new connection on new_fd */
struct sockaddr_in my_addr; /* my address information */
struct sockaddr_in their_addr; /* connector's address information */
socklen_t sin_size;
int i=0;
/* Get port number for server to listen on */
if (argc != 2) {
fprintf(stderr,"usage: client port_number\n");
exit(1);
}
/* generate the socket */
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
/* generate the end point */
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(atoi(argv[1]));
my_addr.sin_addr.s_addr = INADDR_ANY;
I tried setting the default to 12345 when argc != 2, but I get segmentation fault. Any help would be appreciated!
You can use a conditional expression.
#define DEFAULT_PORT 12345
my_addr.sin_port = htons(argc < 2 ? DEFAULT_PORT : atoi(argv[1]));

bind failed: Cannot assign requested address

I'm trying to write a C program that listens on a port on my machine.
I'm running into a strange error.
Whenever I try to bind the socket to a fixed ip (either 127.0.0.1 or my actual IP) I get a "bind failed: Cannot assign requested address" error.
However when I pass INADDR_ANY to the bind as the address to bind to, it works.
These are the only two IPs I have so it can't be that the 0.0.0.0 works because of some other IP address I have available.
Here is the code:
#include<sys/types.h>
#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<errno.h>
#include<stdlib.h>
#include<string.h>
int main()
{
int port = 1234; /* port number */
int rqst; /* socket accepting the request */
socklen_t alen; /* length of address structure */
struct sockaddr_in my_addr; /* address of this service */
struct sockaddr_in client_addr; /* client's address */
int sockoptval = 1;
int svc;
/* create a TCP/IP socket */
if ((svc = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("cannot create socket");
exit(1);
}
/* allow immediate reuse of the port */
setsockopt(svc, SOL_SOCKET, SO_REUSEADDR, &sockoptval, sizeof(int));
/* bind the socket to our source address */
memset((char*)&my_addr, 0, sizeof(my_addr)); /* 0 out the structure */
my_addr.sin_family = AF_INET; /* address family */
my_addr.sin_port = htons(port);
//my_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* Works! */
my_addr.sin_addr.s_addr = htonl(inet_addr("127.0.0.1")); /* Fails! */
if (bind(svc, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0) {
perror("bind failed");
exit(1);
}
printf("Listening on %d\n", my_addr.sin_addr.s_addr);
/* set the socket for listening (queue backlog of 5) */
if (listen(svc, 5) < 0) {
perror("listen failed");
exit(1);
}
/* loop, accepting connection requests */
for (;;) {
while ((rqst = accept(svc, (struct sockaddr *)&client_addr, &alen)) < 0) {
/* we may break out of accept if the system call */
/* was interrupted. In this case, loop back and */
/* try again */
if ((errno != ECHILD) && (errno != ERESTART) && (errno != EINTR)) {
perror("accept failed");
exit(1);
}
}
/* the socket for this accepted connection is rqst */
}
}
The function inet_addr returns the address already in network order:
The inet_addr() function converts the Internet host address cp from
IPv4 numbers-and-dots notation into binary data in network byte order
So drop the htonl.

Resources