ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I am in a bit of a pickle. I have scoured google for ways to get the source address of the client sent to my server which receives using UDP sockets.
I get the packet with no issue, but I would like to get the source address. Where it currently uses 192.168.0.103, I would like it to be this address.
Any Ideas?
Code:
#include "rbsocket.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
/// Address and port info to send/recv to/from
#define SERVER_PORT 7001
#define SERVER_DPORT 7000
#define CLIENT_PORT 12345
/// Buffer size for reading - smaller size = more packets sent
#define BUFFER_SIZE 1024
// forward declaration since C is a parse once compiler
long fileSize(char *filename);
int main() {
struct sockaddr_in srcaddr; // client address - ( not really needed for this example )
struct sockaddr_in srcaddr2;
int srcaddrSize; // client address size - ( not really needed for this example )
FILE *output; // file to output to
long outputSize = 0; // to store the expected # bytes to receive from client
char buffer[BUFFER_SIZE]; // buffer to use for recving & writing
int bread = 0; // temp-var for bytes read from socket
int bwritten = 0; // temp-var for bytes written to file
int fd, fd2; // socket descriptor
printBanner();
fd = get_bound_udp_socket(SERVER_ADDR, SERVER_PORT); // Open socket for controls
fd2 = get_bound_udp_socket(SERVER_ADDR, SERVER_DPORT);
while (1) {
struct cmd_s *cmdrecieved;
char bufferd[BUFFER_SIZE];
recvfrom(fd, bufferd, BUFFER_SIZE, 0, (struct sockaddr *) & srcaddr, (socklen_t*) & srcaddrSize);
cmdrecieved = (struct cmd_s *) bufferd;
printf("Server recieved-> cmd: %s \n", cmdrecieved->cmd); // This works
//This is what I would like it to do
if (strncmp(cmdrecieved->cmd, "send", 3) == 0) {
// Prepare command packet to be sent to the client.
prep_sockaddr_in(&srcaddr2, "0.0.0.0", CLIENT_PORT);
// This is the control packet to tell the client to start sending to port 7000
struct cmd_s cmdsent;
memset(&cmdsent, 0, sizeof (cmdsent));
strcpy(cmdsent.cmd, "rvck"); // rvck means I am ready to recieve fire away old boy.
strcpy(cmdsent.filename, "0xBEEF");
printf("Server sent-> cmd: %s\n", cmdsent.cmd); //this works
sendto(fd2, (char *) & cmdsent, sizeof (cmdsent), 0, (struct sockaddr *) & srcaddr, sizeof (srcaddr));
// // open file to save to
output = fopen(cmdrecieved->filename, "w");
// if either open failed
if ((fd2 == -1) || (output == NULL)) { // print error
printf(" ERROR: %s \n", strerror(errno));
// cleanup any open file/socket
if (output)
fclose(output);
if (fd2 != -1)
close(fd2);
// bail
return -1;
}
// recieve from the client the file size
// so we know how many bytes to expect
bread = recvfrom(fd2, &outputSize, sizeof (outputSize), 0,
(struct sockaddr *) & srcaddr2,
(socklen_t*) & srcaddrSize);
// check that we received a filesize
if (bread != sizeof (outputSize)) { // if not print error
printf(" ERROR: failed to read file size: %d:%s\n",
errno, strerror(errno));
// cleanup
close(fd2);
fclose(output);
// bail
return -1;
}
// Now we can loop until either
// we error in reading from the ssocket
// - or we received all the expected bytes
while (bread > 0 && outputSize > 0) // while we have read stuff
{
// read some file data from the socket
// in this example - we do not care about whom the data is from
bread = recvfrom(fd2, buffer, BUFFER_SIZE, 0,
(struct sockaddr *) & srcaddr,
(socklen_t*) & srcaddrSize);
// did we read something ?
if (bread > 0) { // read stuff - write it to file
bwritten = fwrite(buffer, 1,
bread, output);
// check that we wrote the received data to the file
if (bwritten != bread) // wtf!
{
// print error
printf(" write to file fail! :%d: %s\n", errno, strerror(errno));
// get out of loop to cleanup
break;
}
// lower the remaining expected bytes
outputSize -= bwritten;
printf(" Recv: %d bytes -\t %ld bytes remaining \n", bwritten, outputSize);
} else { // We had some error reading the socket
printf(" Socket read failed \n");
// get out of loop to cleanup
break;
}
}
if (output) {
fclose(output);
}
}
if (strncmp(cmdrecieved->cmd, "get", 3) == 0) {
long inputSize = 0; // to store the file size
// Prepare command packet to be sent to the client.
prep_sockaddr_in(&srcaddr2, "0.0.0.0", CLIENT_PORT);
// Open file to write
FILE *input = fopen(cmdrecieved->filename, "r");
// If file exists - start transfer
// If file does not exist - send error message to client
if (input) {
printf("File exists -> commencing sending to client\n");
struct cmd_s cmdsent;
memset(&cmdsent, 0, sizeof (cmdsent));
strcpy(cmdsent.cmd, "sdck");
strcpy(cmdsent.filename, "0xBEEF\n");
printf("Server sent-> cmd: %s\n", cmdsent.cmd);
sendto(fd2, (char *) & cmdsent, sizeof (cmdsent), 0, (struct sockaddr *) & srcaddr, sizeof (srcaddr));
if ((fd2 == -1) || (input == NULL)) { // puke error
printf(" ERROR: %s \n", strerror(errno));
// cleanup open socket or file
if (fd2 != -1) close(fd2);
if (input != NULL) fclose(input);
// bail
return -1;
}
// We need to send the filesize so the server knows
// how much data to expect
// get the size
if ((inputSize = fileSize(cmdrecieved->filename)) == -1) {
printf(" Server didn't recieve size packet \n");
// cleanup open files / sockets
close(fd);
fclose(input);
// bail
return -1;
}
//Send the size to the client - ( single packet containing a long = fileSize in bytes)
bwritten = sendto(fd2, &inputSize, sizeof (inputSize), 0,
(struct sockaddr *) & srcaddr2, sizeof (srcaddr2));
// verify that it was all sent - ( or so the stack thinks )
if (bwritten != sizeof (inputSize)) {
printf(" send of filesize failed: %d: %s \n", errno, strerror(errno));
// cleanup open files / sockets
close(fd2);
fclose(input);
// bail
return -1;
}
// yippy - now we can beam inputSize bytes to the server
// While there is stuff to send - and we have not sent inputSize bytes
while (!feof(input) && inputSize > 0) { // read some data from file
bread = fread(buffer, 1, BUFFER_SIZE, input);
if (bread > 0) { // if there was no read error
// send the data read to the server
bwritten = sendto(fd2, buffer, bread, 0, (struct sockaddr *) & srcaddr2,
sizeof (srcaddr2));
// check if we sent it all - ( or at least the stack thinks so )
if (bwritten != bread) // wtf
{ // doh!
printf(" Socket Write failed: %d: %s\n",
errno, strerror(errno));
// get out of loop - in order to cleanup
break;
}
// decriment the size remaining
inputSize -= bwritten;
printf(" Sent: %d bytes -\t %ld bytes remaining \n", bwritten, inputSize);
} else if (bread < 0) { // We had some error reading the file
printf(" file read error %d: %s\n", errno, strerror(errno));
// get out of loop - in order to cleanup
break;
}
// End case - (bread = 0) - only occurs if there is nothing remaining
// in the file to read.
} //End for while loop
fclose(input);
}
else {
// This is the control packet to tell the client there was an error
// - uses port 7000
struct cmd_s cmdsent;
memset(&cmdsent, 0, sizeof (cmdsent));
strcpy(cmdsent.cmd, "err");
strcpy(cmdsent.filename, "ERROR: File not found!\n");
printf("Server sent-> cmd: %s\n", cmdsent.cmd);
sendto(fd2, (char *) & cmdsent, sizeof (cmdsent), 0, (struct sockaddr *) & srcaddr, sizeof (srcaddr));
close(fd2);
}
}
}
// cleanup
close(fd);
return 0;
}
// Function to display server banner
void printBanner() {
printf("\n========================\n");
printf("\n File Muncher \n");
printf("\n========================\n");
printf("Version: 1.0\n");
printf("\nServer Listening on UDP 7001 \n");
}
/// returns the filesize of regular files
// -1 on error
long fileSize(char *fileName) {
struct stat sBuf;
// get the file's stats
if (stat(fileName, &sBuf) != 0) { // wtf
printf(" ERROR: stat of file failed: %d: %s\n", errno, strerror(errno));
return -1;
}
// check that it is a regular file
if (!S_ISREG(sBuf.st_mode)) {
printf(" ERROR: stat of file that is not a regular file \n");
return -1;
}
// return the size
return sBuf.st_size;
}
The source address is stored in the sockaddr struct passed to recvfrom. Using inet_ntoa(srcaddr.sin_addr) you can get the ascii representation of the address.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.