Can I get remote IP from UDP socket recvfrom() in threads?

We need to get remote IP to identiy which remote nodes reply through
recvfrom(), and the recvfrom() can’t be in main thread. No matter the
socket() is created in main thread or send threads, the recvfrom() on
another thread returns remote IP address all zero which not correct.
It is a necessary feature for us. The TCP socket does not have such
problem, but UDP had. Below is the source code for client and server.
We tested on QNX 6.3.0 SP2.

You can compile the server source code, you can compile with “qcc
-w9 -g -lsocket -o recv receive.c”, and execute through
“./recv”.

You can compile the clinet source code with “qcc -w9 -g -lsocket
-o send send.c” and execute as "./send .
You will find on server console, below code does not return correct
remot IP address.

printf(“got packet from
%s\n”,inet_ntoa(talker_addr.sin_addr));


The server source code as recv.c

#define testing 1
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <pthread.h>
#include <pthread.h>
#include <sched.h>
#include <sys/neutrino.h>

#define MYSENPORT 6001 // the port users will be connecting to
#define RECVPORT 6001
#define MAXBUFLEN 1000

void *acsRecv_thread_function( void *arg);


int main(int argc, char *argv[])
{
pthread_t acsRecv_thread;
int res;

res=pthread_create( &acsRecv_thread, NULL,
acsRecv_thread_function, NULL);
if(res!=0){
perror(“acsRecv_thread creation failed”);
exit(EXIT_FAILURE);
}
sleep(10);
return (0);

}

void *acsRecv_thread_function( void *arg)
{
int numbytes;
int sockfd;
struct sockaddr_in my_addr; // my address information
struct sockaddr_in talker_addr; // connector’s address
information
int addr_len;
char buf[MAXBUFLEN];


if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror(“socket”);
exit(1);
}
my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = htons(RECVPORT); // short, network byte
order
my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with
my IP
memset(&(my_addr.sin_zero), ‘\0’, :sunglasses:; // zero the rest of the
struct

memset(&(talker_addr.sin_zero), ‘\0’, :sunglasses:; // zero the rest of
the struct

if (bind(sockfd, (struct sockaddr *)&my_addr,
sizeof(struct sockaddr)) == -1) {
perror(“bind”);
exit(1);
}



if ((numbytes=recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,
(struct sockaddr *)&talker_addr, &addr_len)) == -1) {
perror(“recvfrom”);
exit(1);
}

printf(“got packet from
%s\n”,inet_ntoa(talker_addr.sin_addr));
printf(“packet is %d bytes long\n”,numbytes);
buf[numbytes] = ‘\0’;
printf(“packet contains “%s”\n”,buf);
return(NULL);
}


The client source code as send.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <pthread.h>
#include <sched.h>
#include <sys/neutrino.h>


#define MYSENPORT 6001 // the port users will be connecting to
#define MAXBUFLEN 1000

void *acsSend_thread_function( void arg);


int main(int argc, char
argv[])
{
int res;
pthread_t acsSend_thread;

if (argc != 2)
{
printf(“need and only need receive address\n”);
exit(0);
}

res=pthread_create( &acsSend_thread, NULL,
acsSend_thread_function, (void**)argv); // *arg=acs_sem ;
arg=&acs_sem
if(res!=0){
perror(“acsSend_thread creation failed”);
exit(EXIT_FAILURE);
}
sleep(2);
return(0);

}
void *acsSend_thread_function( void *data)
{

int sockfd;
struct sockaddr_in their_addr; // connector’s address information
struct hostent he;
int numbytes;
char
* argv;
char word2[10]= “1234567899”;

argv = (char**)data;
if ((he=gethostbyname(argv[1])) == NULL) { // get the host info
perror(“gethostbyname”);
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror(“socket”);
exit(1);
}

their_addr.sin_family = AF_INET; // host byte order
their_addr.sin_port = htons(MYSENPORT); // short, network byte
order
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(&(their_addr.sin_zero), ‘\0’, :sunglasses:; // zero the rest of
the struct
if ((numbytes=sendto(sockfd, word2, 10, 0,
(struct sockaddr *)&their_addr, sizeof(struct sockaddr)))
== -1) {
perror(“sendto”);
exit(1);
}
printf(“sent %d bytes to %s\n”, numbytes,
inet_ntoa(their_addr.sin_addr));
close(sockfd);
return (NULL);
}

asmart <tsunghsunwu@fpc.com-dot-tw.no-spam.invalid> wrote:

We need to get remote IP to identiy which remote nodes reply through
recvfrom(), and the recvfrom() can’t be in main thread. No matter the
socket() is created in main thread or send threads, the recvfrom() on
another thread returns remote IP address all zero which not correct.
It is a necessary feature for us. The TCP socket does not have such
problem, but UDP had. Below is the source code for client and server.
We tested on QNX 6.3.0 SP2.

You can compile the server source code, you can compile with “qcc
-w9 -g -lsocket -o recv receive.c”, and execute through
“./recv”.

You can compile the clinet source code with “qcc -w9 -g -lsocket
-o send send.c” and execute as "./send .
You will find on server console, below code does not return correct
remot IP address.

printf(“got packet from
%s\n”,inet_ntoa(talker_addr.sin_addr));

You need to initialize the last paramater to recvfrom() before
calling it. See below.

-seanb


The server source code as recv.c

#define testing 1
#include <stdio.h
#include <stdlib.h
#include <unistd.h
#include <errno.h
#include <string.h
#include <sys/types.h
#include <sys/socket.h
#include <netinet/in.h
#include <arpa/inet.h
#include <netdb.h
#include <pthread.h
#include <pthread.h
#include <sched.h
#include <sys/neutrino.h

#define MYSENPORT 6001 // the port users will be connecting to
#define RECVPORT 6001
#define MAXBUFLEN 1000

void *acsRecv_thread_function( void *arg);


int main(int argc, char *argv[])
{
pthread_t acsRecv_thread;
int res;

res=pthread_create( &acsRecv_thread, NULL,
acsRecv_thread_function, NULL);
if(res!=0){
perror(“acsRecv_thread creation failed”);
exit(EXIT_FAILURE);
}
sleep(10);
return (0);

}

void *acsRecv_thread_function( void *arg)
{
int numbytes;
int sockfd;
struct sockaddr_in my_addr; // my address information
struct sockaddr_in talker_addr; // connector’s address
information
int addr_len;
char buf[MAXBUFLEN];


if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror(“socket”);
exit(1);
}
my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = htons(RECVPORT); // short, network byte
order
my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with
my IP
memset(&(my_addr.sin_zero), ‘\0’, > :sunglasses:> ; // zero the rest of the
struct

memset(&(talker_addr.sin_zero), ‘\0’, > :sunglasses:> ; // zero the rest of
the struct

if (bind(sockfd, (struct sockaddr *)&my_addr,
sizeof(struct sockaddr)) == -1) {
perror(“bind”);
exit(1);
}

addr_len = sizeof(talker_addr);

if ((numbytes=recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,
(struct sockaddr *)&talker_addr, &addr_len)) == -1) {
perror(“recvfrom”);
exit(1);
}

printf(“got packet from
%s\n”,inet_ntoa(talker_addr.sin_addr));
printf(“packet is %d bytes long\n”,numbytes);
buf[numbytes] = ‘\0’;
printf(“packet contains “%s”\n”,buf);
return(NULL);
}

According to your advice, add this line

addr_len = sizeof(talker_addr);

before that line

if ((numbytes=recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,
(struct sockaddr *)&talker_addr, &addr_len)) == -1) {
perror(“recvfrom”);
exit(1);
}

It works. Thank you very much