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.
Related
Hello I am working on a school lab in which I have to ask a server to send me a file. Here is my code so far. for some reason, when I run this code, in which I have fixed the arguments for debug purposes, it is as if I get in an infinite loop and get nothing. The problem is surely in gettftp function in the "send" function i think.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <arpa/tftp.h>
#include <sys/socket.h>
#include <netinet/in.h>
int gettftp(const char *fileName, const char *serverIp)
{
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(69);
server_address.sin_addr.s_addr = inet_addr(serverIp);
//sending read request
struct tftphdr *read_request = (struct tftphdr *) malloc(sizeof(struct tftphdr) + strlen(fileName) + 1);
read_request->th_opcode = htons(RRQ);
strcpy(read_request->th_stuff, fileName);
send(sock, read_request, sizeof(struct tftphdr) + strlen(fileName) + 1, 0);
// Receive and save the file
FILE *fp = fopen(fileName, "wb");
while (1) {
char buffer[512];
int bytes_received = recv(sock, buffer, sizeof(buffer), 0);
if (bytes_received < 0) {
break;
}
fwrite(buffer, 1, bytes_received, fp);
}
fclose(fp);
close(sock);
return 0;
}
/**
* Send back the ip address of the requested server
* #param server name inputed right after file to be executed.
* #output none
*/
int main(int argc, char* argv[])
{
char* server, file;
char buffile[100],bufsN[100];
unsigned char ip[50] ="";
struct addrinfo hints, *results, *rp;
int sfd;
argv[1] = "10.10.32.11";
argv[2] = "alt256";
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_flags = 0;
hints.ai_protocol = 0; /* Any protocol */
if(argc<3)
{
printf("You have requested file :\033[0;31m%s\033[0m", argv[2]); //print file name. the part that has 31 changes color to red
printf(" from server : \033[0;31m%s\033[0m \n", argv[1]); //print server name
}
int status = getaddrinfo(argv[1], "69", &hints, &results);
if (status != 0) {
printf("Error: getaddrinfo: %s\n", gai_strerror(status)); //describes what the error does
return 1;
}
else
{
inet_ntop(AF_INET, &results->ai_addr->sa_data[2], ip, sizeof(ip)); //convert ip adress which is part of a struct to string
printf("L'adresse du serveur est: \033[0;31m%s\033[0m \n", ip); //print server ip address
}
for (rp = results; rp != NULL; rp = rp->ai_next) { //socket creation using address family (rp->ai_family), the socket type (ai_socktype)
sfd = socket(rp->ai_family, rp->ai_socktype, //and protocol(ai_protocol)
rp->ai_protocol);
if (sfd == -1) //in case sfd = -1 move on to the next iteration because there is some error somewhere
continue;
if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1){ //if connection is successful print message and break out of the oop
printf("Connected to server: \033[0;31m%s\033[0m \n", argv[1] );
break; /* Success */
}
close(sfd);
}
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not connect\n");
exit(EXIT_FAILURE);
}
//const char* filen = "alt256";
const char* filen = argv[2];
//const char* serverName = "srvtpinfo1.ensea.fr";
strcpy(buffile, filen);
strcpy(bufsN, ip);
gettftp(buffile, bufsN);
//gettftp("alt256", "10.10.32.11");
return 0;
}
}
I have tries debugging to see if the parameters are right when they get in the function and that was the case
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.
I've run into a problem with UDP sockets.
For this particular program, a single .c file needs to be both a client to another server (via TCP) and a server/client to itself (executed twice, running on separate servers). It will be running twice at the same time and since it needs to be able to do both the TCP connection (for one type of data) and the UDP connection (for a different type of data) at the same time it needed to be done with threads or forks, but I used threads.
The issue I'm having is the UDP sockets aren't receiving any datagrams from each other. There are no compilation errors and it runs fine, but there's no output other than general debugging print statements. It's getting stuck at the recvfrom commands.
The code below is separated into two parts (again, within the same .c file). The top portion is the server section, and the lower portion is the client section. This is all done WITHIN a thread. I tried creating the socket THEN calling the thread with the client code (the idea was the thread would communicate with the parent but it didn't matter), but it gets the same result. So, for now, the thread just handles the UDP connection and the parent deals with the TCP.
If you need any more explanation, please feel free to ask. This is for a school assignment so I can't give TOO much, but I'll say what I can.
Thank you!
QUICK EDIT: All this code below is doing is just sending hello to the server and back to the client. Further details are not needed.
Assume that argv->stuff is the struct that I passed to the thread and that the user provides the server, IP address, and port when executing.
//----- Server portion of code is below
int cli2_sockfd;
char buffer_cli2[MAXLINE];
char *hello2 = "Hello from client 2";
struct sockaddr_in cli2_addr, client1_addr;
int clis_portno = atoi(argv->port);
clis_portno = clis_portno + 1;
// Creating socket file descriptor
if ( (cli2_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&cli2_addr, 0, sizeof(cli2_addr));
memset(&client1_addr, 0, sizeof(client1_addr));
// Filling server information
cli2_addr.sin_family = AF_INET; // IPv4
cli2_addr.sin_addr.s_addr = INADDR_ANY;
cli2_addr.sin_port = htons(clis_portno);
// Bind the socket with the server address
if ( bind(cli2_sockfd, (const struct sockaddr *)&cli2_addr,
sizeof(cli2_addr)) < 0 )
{
perror("bind failed");
exit(EXIT_FAILURE);
}
while(1)
{
int n2;
socklen_t len2;
if((n2 = recvfrom(cli2_sockfd, (char *)buffer_cli2, MAXLINE,
0, ( struct sockaddr *) &client1_addr,
&len2)) < 0)
{
perror("svr recvfrom");
exit(EXIT_FAILURE);
}
buffer_cli2[n2] = '\0';
printf("Client 1: %s\n", buffer_cli2);
if(sendto(cli2_sockfd, (const char *)hello2, strlen(hello2),
MSG_CONFIRM, (const struct sockaddr *) &client1_addr,
len2) < 0)
{
perror("svr sendto");
exit(EXIT_FAILURE);
}
printf("Hello message sent.\n");
}
//----- The client portion of the code is below
int client1_sockfd;
char buffer[MAXLINE];
char *hello1 = "Hello from client 1";
struct sockaddr_in client2_addr;
struct hostent *client_2;
clis_portno = atoi(argv->port);
clis_portno = clis_portno + 1;
// Creating socket file descriptor
if ( (client1_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&client2_addr, 0, sizeof(client2_addr));
if((client_2 = gethostbyname(argv->name)) == NULL)
{
perror("cli gethostbyname");
exit(EXIT_FAILURE);
}
bzero((char *) &client2_addr, sizeof(client2_addr));
// Filling Client 2 information
client2_addr.sin_family = AF_INET;
bcopy((char *)client_2->h_addr, (char *)&client2_addr.sin_addr.s_addr, client_2->h_length);
client2_addr.sin_port = htons(clis_portno);
while(1)
{
int n1;
socklen_t len1;
if( sendto(client1_sockfd, (const char *)hello1, strlen(hello1),
0, (const struct sockaddr *) &client2_addr,
sizeof(client2_addr)) < 0)
{
perror("cli sendto");
exit(EXIT_FAILURE);
}
printf("IN THREAD: Hello1 = %s\n", hello1);
if((n1 = recvfrom(client1_sockfd, (char *)buffer, MAXLINE,
MSG_WAITALL, (struct sockaddr *) &client2_addr,
&len1)) < 0)
{
perror("cli recvfrom");
exit(EXIT_FAILURE);
}
buffer[n1] = '\0';
printf("IN THREAD: Client 2 : %s\n", buffer);
}
You are forgetting to initialize len2:
socklen_t len2;
if((n2 = recvfrom(cli2_sockfd, (char *)buffer_cli2, MAXLINE,
0, ( struct sockaddr *) &client1_addr,
&len2)) < 0)
Better:
socklen_t len2 = sizeof(client1_addr);
n2 = recvfrom(cli2_sockfd, (char *)buffer_cli2, MAXLINE,
0, ( struct sockaddr *) &client1_addr,
&len2));
if (n2 < 0)
{
….
Not sure if that's your only issue that's preventing packets from being received.
I cleaned up your code a little and got it to work using port 9999 for server. And having the client connect to localhost. I cleaned up some of those memcpy statements around gethostbyname, some of your struct initialization calls, removed some of the exit calls that could occur for benign errors (including recvfrom errors when the server is offline). That MSG_WAITALL flag looked weird, so I removed that as well.
I got it working Cygwin without any special hacks. I have no doubt it would work in Linux (or any Unix).
You can see it working here in server mode:
And the corresponding window in client mode:
Code here:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <stdlib.h>
#include <memory.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <stdarg.h>
#define MAXLINE 260
#define MSG_CONFIRM "Confirm"
void server(unsigned short port)
{
int cli2_sockfd = -1;
char buffer_cli2[MAXLINE] = { 0 };
char *hello2 = "Hello from client 2";
struct sockaddr_in cli2_addr = { 0 }, client1_addr = { 0 };
unsigned short clis_portno = port;
// Creating socket file descriptor
if ((cli2_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
// Filling server information
cli2_addr.sin_family = AF_INET; // IPv4
cli2_addr.sin_addr.s_addr = INADDR_ANY;
cli2_addr.sin_port = htons(clis_portno);
// Bind the socket with the server address
if (bind(cli2_sockfd, (const struct sockaddr *)&cli2_addr,
sizeof(cli2_addr)) < 0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
while (1)
{
int n2;
socklen_t len2 = sizeof(client1_addr);
if ((n2 = recvfrom(cli2_sockfd, (char *)buffer_cli2, MAXLINE,
0, (struct sockaddr *) &client1_addr,
&len2)) < 0)
{
perror("svr recvfrom");
exit(EXIT_FAILURE);
}
buffer_cli2[n2] = '\0';
printf("Client 1: %s\n", buffer_cli2);
if (sendto(cli2_sockfd, (const char *)hello2, strlen(hello2),
0, (const struct sockaddr *) &client1_addr,
len2) < 0)
{
perror("svr sendto");
}
printf("Hello message sent.\n");
}
}
void client(const char* hostname, unsigned short port)
{
int client1_sockfd;
char buffer[MAXLINE];
char *hello1 = "Hello from client 1";
struct sockaddr_in client2_addr = { 0 };
struct hostent *client_2 = NULL;
unsigned short clis_portno = port;
// Creating socket file descriptor
if ((client1_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
if ((client_2 = gethostbyname(hostname)) == NULL)
{
perror("cli gethostbyname");
exit(EXIT_FAILURE);
}
// Filling Client 2 information
client2_addr.sin_family = AF_INET;
client2_addr.sin_port = htons(clis_portno);
memcpy(&client2_addr.sin_addr, client_2->h_addr, 4);
while (1)
{
int n1;
if (sendto(client1_sockfd, (const char *)hello1, strlen(hello1),
0, (const struct sockaddr *) &client2_addr,
sizeof(client2_addr)) < 0)
{
perror("cli sendto");
exit(EXIT_FAILURE);
}
printf("IN THREAD: Hello1 = %s\n", hello1);
socklen_t len1 = sizeof(client2_addr);
if ((n1 = recvfrom(client1_sockfd, (char *)buffer, MAXLINE,
0, (struct sockaddr *) &client2_addr,
&len1)) < 0)
{
perror("cli recvfrom");
}
else
{
buffer[n1] = '\0';
printf("IN THREAD: Client 2 : %s\n", buffer);
}
sleep(1);
}
}
int main(int argc, char** argv)
{
if ((argc > 1) && (strcmp(argv[1], "s") == 0))
{
printf("Running in server mode\n");
server(9999);
}
else
{
printf("Running in client mode\n");
client("localhost", 9999);
}
return 0;
}
So I have one UDP server that returns the hour or the date to the client with the following code:
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include <time.h>
void main(int argc, char *argv[]) {
struct addrinfo hints;
struct addrinfo *res;
struct sockaddr_storage cli;
time_t rawtime;
struct tm* timeinfo;
char tbuffer[9];
char buf[81], host[NI_MAXHOST], serv[NI_MAXSERV];
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
hints.ai_protocol = 0; /* Any protocol */
getaddrinfo(argv[1], argv[2], &hints, &res);
int sd = socket(res->ai_family, res->ai_socktype, 0);
bind(sd, (struct sockaddr *)res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
while(1) {
socklen_t clen = sizeof(cli);
int c = recvfrom(sd, buf, 80, 0, (struct sockaddr*) &cli, &clen);
buf[c] = '\0';
getnameinfo((struct sockaddr*) &cli, clen, host, NI_MAXHOST, serv, NI_MAXSERV, NI_NUMERICHOST);
time(&rawtime);
timeinfo = localtime(&rawtime);
if(buf[0] == 't') {
printf("%ld bytes de %s:%s\n", c, host, serv);
ssize_t chars = strftime(tbuffer, sizeof(tbuffer), "%T", timeinfo);
sendto(sd, tbuffer, chars, 0, (struct sockaddr *)&cli, clen);
} else if(buf[0] == 'd') {
printf("%ld bytes de %s:%s\n", c, host, serv);
ssize_t chars = strftime(tbuffer, sizeof(tbuffer), "%D", timeinfo);
sendto(sd, tbuffer, chars, 0, (struct sockaddr *)&cli, clen);
} else if(buf[0] == 'q') {
printf("Saliendo...\n");
exit(EXIT_SUCCESS);
} else {
printf("Comando no soportado %s", buf);
}
}
}
To test the code I was using ./server <IPServerAddres> <PortAddress> on the server side and nc -u <IpServerAddress> <PortServer> on the client side (another machine).
Now I want to create the UDP client UDP and do the same without using nc, just writing ./client <IPServerAddres> <PortAddress> <command> where command can be t for time d for date and q for quit, just like in the server.
Here is the code of the client program:
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include <time.h>
int main(int argc, char *argv[]) {
struct addrinfo hints;
struct addrinfo *res, *resp;
int sd, j, s;
size_t len;
ssize_t nread, nwrite;
char buf[500];
if (argc < 3) {
fprintf(stderr, "Usage: %s host port command...\n", argv[0]);
exit(EXIT_FAILURE);
}
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_flags = 0;
hints.ai_protocol = 0; /* Any protocol */
getaddrinfo(argv[1], argv[2], &hints, &res);
for(resp = res; resp != NULL; resp = resp->ai_next) {
sd = socket(resp->ai_family, resp->ai_socktype, resp->ai_protocol);
if(sd == -1) {
perror("socket()");
continue;
}
if(connect(sd, resp->ai_addr, resp->ai_addrlen) == -1) {
perror("socket()");
} else {
break;
}
close(sd);
}
freeaddrinfo(res);
for(j = 3; j < argc; j++) {
len = strlen(argv[j]) + 1;
nwrite = write(sd, argv[j], len);
if(nwrite == -1) perror("write()");
nread = read(sd, buf, 500);
buf[nread] = 0;
if(nread == -1) perror("read()");
printf("Recibidos %ld bytes: %s\n", (long) nread, buf);
}
exit(EXIT_SUCCESS);
}
The problem is that when I try to run my client program I got no response, so I guess is in a infinite loop or something like that.
Any help will be apreciated, I'm learning C so I'm sorry for the mistakes, thank you.
EDITED: Corrected the break in the for loop in case connect() returns something different than -1.
The problem is in your calculation of the length of the message to send:
len = strlen(argv[j] + 1);
This gets the length of the string starting from the second character. You want:
len = strlen(argv[j]) + 1;
This gives you the string length plus 1 for the null terminator.
Also, after reading the response, you'll need to null-terminate what you got back:
buf[nread] = 0;
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm trying to communicate through a connected-udp-socket between two peer's. The address information between the peers is transmitted via a server using tcp.
First each peer set's up an udp-socket, binds an address and then transmit the address information via tcp to a server. The server sends the connection information to the other peer.
When the peer receives the information it tries to 'connect' the udp-socket to the other peer. The connect call succeed, but send gives me the following error: 'errno: 89, Destination address required'.
peer.c:
#include "Socket.h"
#include "function.h"
int main (int argc, char** argv) {
if(argc != 4) {
printf("3 Parameter must be given.\nclient-ip server-ip server-port\n");
exit(-1);
}
struct sockaddr_in my_addr, server_addr, other_peer_addr;
address_info* msg_address_info;
header *msg;
int recv_done = 0;
int optval = 1;
int fd_udp, fd_server;
ssize_t len;
socklen_t my_addr_len;
fd_set rfds;
FD_ZERO(&rfds);
fd_udp = Socket(AF_INET, SOCK_DGRAM, 0);
memset((void *) &my_addr, 0, sizeof(my_addr));
my_addr.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
my_addr.sin_len = sizeof(struct sockaddr_in);
#endif
my_addr.sin_port = 0; // any port
if ((my_addr.sin_addr.s_addr = (in_addr_t)inet_addr(argv[1])) == INADDR_NONE) {
fprintf(stderr, "Invalid address\n");
}
Bind(fd_udp, (const struct sockaddr *) &my_addr, sizeof(my_addr));
Setsockopt(fd_udp, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int));
Setsockopt(fd_udp, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(int));
memset((void *) &my_addr, 0, sizeof(my_addr));
my_addr_len = sizeof(my_addr);
//get the current address for server registration
Getsockname(fd_udp, (struct sockaddr *) &my_addr, &my_addr_len);
/* TCP Communication */
/* i use 127.0.0.1:55555 for the server */
fd_server = Socket(AF_INET, SOCK_STREAM, 0);
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
server_addr.sin_len = sizeof(struct sockaddr_in);
#endif
server_addr.sin_port = htons(atoi(argv[3]));
if ((server_addr.sin_addr.s_addr = (in_addr_t) inet_addr(argv[2]))
== INADDR_NONE) {
fprintf(stderr, "Invalid address\n");
}
Connect(fd_server, (const struct sockaddr *) &server_addr, sizeof(server_addr));
len = sizeof(address_info);
msg_address_info = malloc(len + get_padding(len));
memset((void*)msg_address_info, 0, len + get_padding(len));
msg_address_info->head.type = htons(30);
msg_address_info->head.length = htons(sizeof(address_info));
msg_address_info->ip = my_addr.sin_addr.s_addr;
msg_address_info->port = my_addr.sin_port;
Send(fd_server, msg_address_info, len + get_padding(len), 0);
free(msg_address_info);
while(!recv_done) {
FD_ZERO(&rfds);
FD_SET(fd_server, &rfds);
//data is ready for recv
if(FD_ISSET(fd_server, &rfds)) {
msg = recv_stream(fd_server);
if(msg != NULL) {
if(ntohs(msg->type) == 3) {
Close(fd_server);
recv_done = 1;
msg_address_info = (address_info *) msg;
other_peer_addr.sin_addr.s_addr = msg_address_info->ip;
other_peer_addr.sin_port = msg_address_info->port;
}
}
}
}
char buf[512];
memset((void*)&buf, 0, 512);
char* other_peer_ip;
int other_peer_port;
other_peer_ip = inet_ntoa(other_peer_addr.sin_addr);
other_peer_port = ntohs(other_peer_addr.sin_port);
printf("other_peer ip: %s\nother_peer port: %i\n", other_peer_ip, other_peer_port); //matches on bothe peer's
int ret_con = connect(fd_udp, (const struct sockaddr *) &other_peer_addr, sizeof(other_peer_addr));
fprintf(stderr, "ret_con: %i, errno: %i, %s\n", ret_con, errno, strerror(errno));
int ret_send = send(fd_udp, buf, 512, 0);
if(ret_send < 0) {
fprintf(stderr, "ret_send: %i, errno: %i, %s\n", ret_send, errno, strerror(errno));
}
}
function.h:
#define BUFFER_SIZE (1<<16)
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <err.h>
#include <netdb.h>
#include <errno.h>
#include "Socket.h"
typedef struct {
uint16_t type;
uint16_t length;
} header;
typedef struct {
header head;
uint32_t ip;
uint16_t port;
} address_info;
int get_padding(int length);
void* recv_stream(int fd);
functions.c:
#include "functions.h"
void* recv_stream(int fd) {
if(fd < 0) {
fprintf(stderr, "recv_stream: Invaild fd\n");
return NULL;
}
ssize_t len;
int msg_length;
char buf[BUFFER_SIZE];
char* msg;
len = recv(fd, &buf, BUFFER_SIZE, MSG_PEEK);
//Client has closed the connection
if(len <= 0) {
fprintf(stderr, "recv_stream: Client closed the connection.\n");
exit(-1);
}
#ifdef DEBUG
printf("PEEKED %zd bytes.\n", len);
#endif
if(len < sizeof(header)) {
fprintf(stderr, "recv_stream: Message to small no header\n");
return NULL;
}
header *head = (header *) buf;
msg_length = ntohs(head->length);
if(len < msg_length) {
fprintf(stderr, "recv_stream: Message to small\n");
return NULL;
}
else if(len >= msg_length + get_padding(msg_length)) {
msg = malloc(msg_length + get_padding(msg_length));
len = Recv(fd, msg, msg_length + get_padding(msg_length), 0);
head = (header *) msg;
}
return head;
}
int get_padding(int length) {
if(length <= 0) {
fprintf(stderr, "get_padding: wrong length");
}
int pad = length % 4;
if(pad == 3)
pad = 1;
else if(pad == 1)
pad = 3;
return pad;
}
Socket.c with Wrapper functions
int Socket(int fd, int type, int protocol) {
int n;
if((n=socket(fd,type,protocol)) < 0) {
perror("socket");
exit(-1);
}
return n;
}
/* many more */
I read already following question Can you bind() and connect() both ends of a UDP connection but it did not solve my problem.
The transfer of the address information seems to be correct. I printed the send and received addresses on both peers and they match.
I'm stucked on this problem and can't figure out my mistake. Can you help me?
Edit:
provided new example
Now i get the following error:
ret_con: -1, errno: 97, Address family not supported by protocol
ret_send: -1, errno: 89, Destination address required
You are not populating the sin_family field of other_peer_addr before calling connect() on the UDP socket. You are only populating the sin_addr and sin_port fields, which is not enough. connect() needs to be told the type of address being passed to it and that must use the same family as the socket (just like with bind()). Since you are not populating the sin_family field, it contains a random value from the stack, and that is causing connect() to fail with the "Address family not supported" error, and send() cannot be called on an unconnected socket, thus causing the "Destination address required" error.