I am building a multiclient UDP server in c,but when i tried to connect to my server from a system, i get this error ERROR on gethostbyaddr: Success
Please find the below server code.I have tried the solutions from similar questions(gethostbyaddr() returns NULL but errno result in SUCCESS) but i couldn't get it working.Any help will be greatly appreciated
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUFSIZE 1024
/*
* error - wrapper for perror
*/
void error(char *msg) {
perror(msg);
exit(1);
}
int main(int argc, char **argv) {
int sockfd; /* socket */
int portno; /* port to listen on */
int clientlen; /* byte size of client's address */
struct sockaddr_in serveraddr; /* server's addr */
struct sockaddr_in clientaddr; /* client addr */
struct hostent *hostp; /* client host info */
char buf[BUFSIZE]; /* message buf */
char *hostaddrp; /* dotted decimal host addr string */
int optval; /* flag value for setsockopt */
int n; /* message byte size */
FILE *fp; /* file variable */
char str[10];
int i = 0;
char userlist[10];
int array_size;
char line[256];
int cred,flag;
/*
* check command line arguments
*/
if (argc != 2) {
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(1);
}
portno = atoi(argv[1]);
/*
* socket: create the parent socket
*/
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
/* setsockopt: Handy debugging trick that lets
* us rerun the server immediately after we kill it;
* otherwise we have to wait about 20 secs.
* Eliminates "ERROR on binding: Address already in use" error.
*/
optval = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
(const void *)&optval , sizeof(int));
/*
* build the server's Internet address
*/
bzero((char *) &serveraddr, sizeof(serveraddr));
memset(&serveraddr,0,sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)portno);
/*
* bind: associate the parent socket with a port
*/
if (bind(sockfd, (struct sockaddr *) &serveraddr,
sizeof(serveraddr)) < 0)
error("ERROR on binding");
/*
* main loop: wait for a datagram, then echo it
*/
clientlen = sizeof(clientaddr);
while (1) {
/*
* recvfrom: receive a UDP datagram from a client
*/
bzero(buf, BUFSIZE);
n = recvfrom(sockfd, buf, BUFSIZE, 0,
(struct sockaddr *) &clientaddr, &clientlen);
if (n < 0)
error("ERROR in recvfrom");
/*
* gethostbyaddr: determine who sent the datagram
*/
hostp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
sizeof(clientaddr.sin_addr.s_addr), AF_INET);
if (hostp == NULL)
error("ERROR on gethostbyaddr");
hostaddrp = inet_ntoa(clientaddr.sin_addr);
if (hostaddrp == NULL)
error("ERROR on inet_ntoa\n");
printf("server received datagram from %s (%s)\n",
hostp->h_name, hostaddrp);
printf("server received %d/%d bytes: %s\n", strlen(buf), n, buf);
fp = fopen("users.txt", "r");
while (fgets(line, sizeof(line), fp)) {
//printf("%s\n",line);
cred = strncmp(buf,line,strlen(line)-1);
//printf("%d",strlen(line)-1);
if(cred == 0){
printf("Authenticated....");
flag = 1;
break;
}
else{
printf("Invalid username/password");
}
}
fclose(fp);
gethostbyaddr() expects a pointer to a struct in_addr as 1st parameter, which would be &clientaddr.sin_addr for the code you show.
Form the relevant (Linux) documentation (man gethostbyaddr):
[...] The host address argument is a pointer to a struct of a type depending on the address type, for example a struct in_addr * (probably obtained via a call to inet_addr(3)) for address type AF_INET.
gethostbyaddr() sets the error code in h_errno not in errno.
Form the relevant (Linux) documentation (man gethostbyaddr):
RETURN VALUE
[...[ The gethostbyname() and gethostbyaddr() functions return the hostent structure or a null pointer if an error occurs. On error, the h_errno variable holds an error number.
The possible error code are given by the man-page as well:
ERRORS
The variable h_errno can have the following values:
HOST_NOT_FOUND
The specified host is unknown.
NO_ADDRESS or NO_DATA
The requested name is valid but does not have an IP address.
NO_RECOVERY
A nonrecoverable name server error occurred.
TRY_AGAIN
A temporary error occurred on an authoritative name server. Try again later.
Related
I am writing a program where the client sends the server a time request. I also want to send my name and get the server to echo it back. So far the program will echo my name but then I get a Segmentation fault (core dumped) where the time should be display. I have attached the code for the clien and server and also a screenshot of the terminal.
SERVER CODE
#include <stdio.h> /* I/O functions */
#include <string.h> /* string functions */
#include <stdlib.h> /* C standard functions */
#include <sys/socket.h> /* socket functions */
#include <sys/types.h> /* library of basic types */
#include <netinet/in.h> /* library of Internet address functions */
#include <arpa/inet.h> /* Internet operations */
#include <time.h> /* time functions */
#define PORT 8080 /* server port # */
#define BUFFSIZE 200 /* buffer size */
int main()
{
int sockfd;
int addrlen;
char buffer[BUFFSIZE];
struct sockaddr_in server;
struct sockaddr_in client;
time_t current_time;
/* Populate socket data structures with IP address and port number */
memset((char *) &server, 0, sizeof(struct sockaddr_in));
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
/* Create a UDP socket; returns -1 on failure */
sockfd = socket(AF_INET,SOCK_DGRAM,0);
if (sockfd == -1) {
printf("Socket error\n");
exit(1); /* Exit on error */
}
/* Bind the socket address */
if ((bind(sockfd,(struct sockaddr*)&server,sizeof(struct sockaddr_in))) == -1) {
printf("Server bind error\n");
exit (1); /* Exit on error */
}
/* Status message */
printf("The server is listening on port: %d\n", PORT);
printf("Waiting for client request...\n");
printf("Press CTRL + C to exit\n");
while(1) {
addrlen = sizeof(struct sockaddr_in);
recvfrom(sockfd, buffer,BUFFSIZE, 0,(struct sockaddr *)&client, (socklen_t *)&addrlen);
current_time = time(NULL);
memcpy(buffer + strlen(buffer) + 1, ¤t_time, sizeof(current_time));
sendto(sockfd, buffer, strlen(buffer) + 1 + sizeof(current_time), 0, (struct sockaddr *)&client, addrlen);
}
exit(0);
} /* End of time server program */
CLIENT CODE
#include <stdio.h> /* I/O functions */
#include <string.h> /* string functions */
#include <stdlib.h> /* C standard functions */
#include <sys/socket.h> /* socket functions */
#include <sys/types.h> /* library of basic types */
#include <netinet/in.h> /* library of Internet address functions */
#include <arpa/inet.h> /* Internet operations */
#include <time.h> /* time functions */
#define BUFFSIZE 200 /* buffer size */
int main(int argc, char *argv[])
{
int sockfd;
int addrlen;
char buffer[BUFFSIZE] = "GET TIME\r\n";
struct sockaddr_in server;
struct sockaddr_in client;
char *servIP = argv[1]; // Server IP address from command line
int servPort = atoi(argv[2]); // Server port number from command line
char *name = argv[3];
time_t current_time;
/* Check that two arguments were passed on the command line */
if (argc != 4) {
printf("Usage: udp-time-client [IP address] [Port] [Name] \n");
exit(1);
}
/* Populate server socket data structure with IP address and port number */
memset((char *) &server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(servPort);
server.sin_addr.s_addr = inet_addr(servIP);
/* Populate client socket data structure with IP address and port number */
memset((void *)&client, '\0', sizeof(client));
client.sin_family = AF_INET;
client.sin_port = htons(servPort);
client.sin_addr.s_addr = inet_addr(servIP);
/* Create a UDP socket; returns -1 on failure */
sockfd = socket(AF_INET,SOCK_DGRAM,0);
if (sockfd == -1) {
printf("Socket error\n");
exit(1);
}
/* Status message */
printf("Client is sending on IP address %s port: %d\n", servIP, servPort);
/* Send the time request to the server */
addrlen = sizeof(struct sockaddr_in);
strcpy(buffer, name);
sendto(sockfd, buffer, (int)strlen(buffer) + 1, 0, (struct sockaddr *)&server, addrlen);
printf("Request sent to server\n");
/* Receive the time request from server */
recvfrom(sockfd, (char *) buffer, sizeof(buffer), 0, (struct sockaddr *)&server, (socklen_t *)&addrlen);
/* Print the name received from the server */
printf("\n The name received from the server:%s\n", buffer);
memcpy((void *)current_time, buffer + strlen(buffer) + 1, sizeof(current_time));
/* Print the time received from the server */
printf("\n The time received from the server:%s\n", ctime(¤t_time));
exit(0);
} /* End of time client program */
Screenshot of terminal As you can see, my name is echoed back but I get the error where the time should be
memcpy((void *)current_time, ...);
should be
memcpy(¤t_time, ...);
I'm trying to implement communication by UDP protocol, and I'm getting an error: "Error sending: Address family not supported by protocol". I've checked in Google for this problem but couldn't managed to find answer.
Please be patient, I'm only starting my adventure with coding in C.
Here is a C code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#define BUFLEN 512
// define function that deals with errors
void error(const char *msg)
{
perror(msg); // print error msg
exit(1); // exit the main() function
}
int main(int argc, char *argv[])
{
struct sockaddr_in serv1_addr, serv2_addr, cli1_addr, cli2_addr; //definicja struktur adresów servera i clienta
struct hostent *server; //defines host addres struct
int cl1_sockfd, se1_sockfd, se2_sockfd, i, c1len = sizeof(cli1_addr), c2len = sizeof(cli2_addr), recv_len, portno1,portno2; // creates inits
int cli1_len = sizeof(cli1_addr);
int cli2_len = sizeof(cli2_addr);
char buf[BUFLEN];
if (argc < 4) {
fprintf(stderr,"ERROR, no port provided\n"); // deal with wrong port
exit(1);
}
//tworzenie soceketu servera
if ((se1_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
error("socket1"); //if socket() return -1 -- error
}
if ((se2_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
error("socket2"); //if socket() return -1 -- error
}
//zero out the structure
memset( &serv1_addr, 0, sizeof(serv1_addr)); //put zero into structure
memset( &serv2_addr, 0, sizeof(serv2_addr)); //put zero into structure
portno1 = atoi(argv[2]); // get port number
portno2 = atoi(argv[3]);
serv1_addr.sin_family = AF_INET; // specify address family (IPv4)
serv1_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv1_addr.sin_port = htons(portno1); // set port number
serv2_addr.sin_family = AF_INET; // specify address family (IPv4)
serv2_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv2_addr.sin_port = htons(portno2); // set port number
if(connect(se1_sockfd,(struct sockaddr *) &serv1_addr, sizeof(serv1_addr)) < 0)
error ("ERROR connecting1"); //if connection failed
if(connect(se2_sockfd,(struct sockaddr *) &serv2_addr, sizeof(serv2_addr)) < 0)
error ("ERROR connecting2"); //if connection failed
while(1) //inf loop
{
printf("Please enter the message: "); //write the msg to socket
bzero(buf, 512); //fill buffer with zeros
fgets(buf, 512, stdin); //read into buffer
if( sendto( se1_sockfd, buf, BUFLEN, 0, (struct sockaddr*) &cli1_addr, cli1_len) < 0)
error ("Error sending1");
if( sendto( se2_sockfd, buf, BUFLEN, 0, (struct sockaddr*) &cli2_addr, cli2_len) < 0)
error ("Error sending2");
if (recvfrom(se1_sockfd, buf, BUFLEN, 0, (struct sockaddr *) &cli1_addr, &cli1_len) == -1){
error("recivfrom()1"); //if reciving failed -- error
}
printf("Data: %s\n", buf);
if (recvfrom(se2_sockfd, buf, BUFLEN, 0, (struct sockaddr *) &cli2_addr, &cli2_len) == -1){
error("recivfrom()2"); //if reciving failed -- error
}
printf("Data: %s\n", buf);
}
close(se1_sockfd);
close(se2_sockfd);
return 0;
}
Thanks for your help. ;)
Your issue is likely because of uninitialized destination address. sendto() takes destination address as the one before the last argument. But you are trying to provide not-initialized address (like for recvfrom())
if( sendto( se1_sockfd, buf, BUFLEN, 0, (struct sockaddr*) &cli1_addr, cli1_len) < 0)
error ("Error sending1");
^^^
Try serv1_addr instead ?
Also need to provide appropriate size.
One more thing. As long as you use sendto() - no need to perform connect(). UDP is connectionless and connect() only establishes default destination address for those who is going to use send() on such socket. But this is not your case because you provide destination address each time you call sendto(). Even more - you may use different addresses each time.
P.S. Reference: sendto()
Hell all. I was working on a server c project, using UDP for a whois service.
But I got error: "No whois is service on this host." Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pwd.h>
#define BACKLOG 5 /* # of requests we're willing to queue */
#define MAXHOSTNAME 32 /* maximum host name length we tolerate */
main(argc,argv)
int argc; /* standard UNIX argument declarations */
char *argv[];
{
int s,t; /* socket descriptors */
int i; /* general purpose integer */
struct sockaddr_in sa,isa; /* Internet socket address structure */
struct hostent *hp; /* result of host name lookup */
char *myname; /* pointer to name of this program */
struct servent *sp; /* result of service lookup */
char localhost[MAXHOSTNAME+1]; /* local host name as character string */
myname = argv[0];
/*
* Look up the WHOIS service entry
*/
if((sp = getservbyname("whois","udp")) == NULL){
fprintf(stderr, "%s: No whois service on this host\n", myname);
exit(1);
}
/*
* Get our own host information
*/
gethostname(localhost, MAXHOSTNAME);
if((hp = gethostbyname(localhost)) == NULL){
fprintf(stderr, "%s: cannot get local host info?\n", myname);
exit(1);
}
printf("host name is: %s\n",hp->h_name);
printf("my name is: %s\n",myname);
/*
* Put the WHOIS socket number and our address info into the socket structure
*/
u_short portbase = 0;
portbase = 5000;
sa.sin_port = sp->s_port;
sa.sin_port = htons(ntohs((u_short)sp->s_port)+portbase);
bcopy((char *)hp->h_addr, (char *)&sa.sin_addr, hp->h_length);
sa.sin_family = hp->h_addrtype;
/*
* Allocate an open socket for incoming connections
*/
if((s = socket(hp->h_addrtype, SOCK_DGRAM, 0)) < 0){
perror("socket");
exit(1);
}
/*
* Bind the socket to the service port
*/
if(bind(s, (struct sockaddr *)&sa, sizeof sa) < 0){
perror("bind");
exit(1);
}
/*
* Set maximum connections we will fall behind
*/
//listen(s,BACKLOG);
/*
* Go into an infinite loop waiting for new connections
*/
while(1){
i = sizeof isa;
/*
* We hang in accept() while waiting for new customers
*/
/*
if((t = accept(s, (struct sockaddr *)&isa, &i)) < 0){
perror("accept");
exit(1);
}
*/
whois(s); /* perform the actual WHOIS service */
close(s);
}
}
/*
* Get the WHOIS request from remote host and format a reply.
*/
whois(sock)
int sock;
{
struct sockaddr_in clientAddr;
socklen_t len = sizeof(clientAddr);
memset(&clientAddr, 0, sizeof(clientAddr));
struct passwd *p;
char buf[BUFSIZ+1];
int i;
/*
* Get one line request
*/
printf("start to recv data\n");
if((i = recvfrom(sock, buf, BUFSIZ, 0, (struct sockaddr*)&clientAddr, &len)) <= 0)
printf("recv failed\n");
return;
buf[i] = '\0'; /* Null terminate */
printf("After the read, the buf is: %s \n",buf);
/*
* Look up the requested user and format reply
*/
if((p = getpwnam(buf)) == NULL)
strcpy(buf, "User not found\n");
else
sprintf(buf, "%s: %s (from me)\n", p->pw_name, p->pw_gecos);
/*
* Return reply
*/
//write(sock, buf, strlen(buf));
sendto(sock, buf, strlen(buf), 0, (struct sockaddr*)&clientAddr, len);
return;
}
I couldn't figure out where's error. I have a similar code using TCP for whois which runs no problem.
WHOIS is a TCP service. It is not available over UDP.
Additionally, what you are writing is not a WHOIS server at all. WHOIS is a protocol implemented by domain and IP registrars to communicate ownership information (e.g, to look up the owner of a domain name). What you are writing here appears to be a NIS service of some sort - this is not WHOIS, and should not use the same port.
I'm looking forward to achive this: Server recieves from number of clients a string(file name) which he has to take from the folder and return it to the the client by a bufferSize which is defined from the command line. It has to be implemented with UDP communication. i'm familiarized with TCP sockets, but i don't get how can i get a fileDescriptor for the udp connection since accepts is missing.
So I'm thinking about this: after the config i do a while-loop in the server where i get 'some kind of descriptor' which i'll send to a new thread which knows where to send the data back... Any ideas?
I've checked the net but didn't found a concrete explanation for this kind of operation.
You don't get connections with UDP; you use sendto() and recvfrom() to send and receive messages.
So the server will call recvfrom() on the socket; unwrap the request from the data it receives, do the appropriate actions, and use sendto() to send the response back to the client from which the request was received.
The client will call sendto() to package a message to the server, and then call recvfrom() to get the response. Note that UDP is an unreliable protocol; there is no guarantee that each message will be delivered. The client has to implement timeouts in case the server dropped a UDP request. Servers have to be able to deal with duplicate requests, too.
I have finally found something helpful, maybe it will be useful for others so here it is: the code is commented and really clear.
PS: sorry for the long paste, but google doesn't let me copy the link.
/*
* udpserver.c - A simple UDP echo server
* usage: udpserver <port>
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUFSIZE 1024
/*
* error - wrapper for perror
*/
void error(char *msg) {
perror(msg);
exit(1);
}
int main(int argc, char **argv) {
int sockfd; /* socket */
int portno; /* port to listen on */
int clientlen; /* byte size of client's address */
struct sockaddr_in serveraddr; /* server's addr */
struct sockaddr_in clientaddr; /* client addr */
struct hostent *hostp; /* client host info */
char buf[BUFSIZE]; /* message buf */
char *hostaddrp; /* dotted decimal host addr string */
int optval; /* flag value for setsockopt */
int n; /* message byte size */
/*
* check command line arguments
*/
if (argc != 2) {
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(1);
}
portno = atoi(argv[1]);
/*
* socket: create the parent socket
*/
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
/* setsockopt: Handy debugging trick that lets
* us rerun the server immediately after we kill it;
* otherwise we have to wait about 20 secs.
* Eliminates "ERROR on binding: Address already in use" error.
*/
optval = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
(const void *)&optval , sizeof(int));
/*
* build the server's Internet address
*/
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)portno);
/*
* bind: associate the parent socket with a port
*/
if (bind(sockfd, (struct sockaddr *) &serveraddr,
sizeof(serveraddr)) < 0)
error("ERROR on binding");
/*
* main loop: wait for a datagram, then echo it
*/
clientlen = sizeof(clientaddr);
while (1) {
/*
* recvfrom: receive a UDP datagram from a client
*/
bzero(buf, BUFSIZE);
n = recvfrom(sockfd, buf, BUFSIZE, 0,
(struct sockaddr *) &clientaddr, &clientlen);
if (n < 0)
error("ERROR in recvfrom");
/*
* gethostbyaddr: determine who sent the datagram
*/
hostp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
sizeof(clientaddr.sin_addr.s_addr), AF_INET);
if (hostp == NULL)
error("ERROR on gethostbyaddr");
hostaddrp = inet_ntoa(clientaddr.sin_addr);
if (hostaddrp == NULL)
error("ERROR on inet_ntoa\n");
printf("server received datagram from %s (%s)\n",
hostp->h_name, hostaddrp);
printf("server received %d/%d bytes: %s\n", strlen(buf), n, buf);
/*
* sendto: echo the input back to the client
*/
n = sendto(sockfd, buf, strlen(buf), 0,
(struct sockaddr *) &clientaddr, clientlen);
if (n < 0)
error("ERROR in sendto");
}
}
I complile the following C code of UDP client
after I run './udpclient localhost 9191' in terminal.I put "Enter Text= " as Hello, but it is showing error in sendto as below:
Enter text: hello
hello
: error in sendto()guest-1SDRJ2#md-K42F:~/Desktop$
"
Note: I open 1st the server port as below in other terminal
./server 9191.
I beleive there is no error in server code. The udp client is not passing message to server. If I don't use thread , the message is passing .But I have to do it by thread.
UDP client Code:
/* simple UDP echo client */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <pthread.h>
#define STRLEN 1024
static void *readdata(void *);
static void *writedata(void *);
int sockfd, n, slen;
struct sockaddr_in servaddr;
char sendline[STRLEN], recvline[STRLEN];
int main(int argc, char *argv[]) {
pthread_t readid,writeid;
struct sockaddr_in servaddr;
struct hostent *h;
if(argc != 3) {
printf("Usage: %s <proxy server ip> <port>\n", argv[0]);
exit(0);
}
/* create hostent structure from user entered host name*/
if ( (h = gethostbyname(argv[1])) == NULL) {
printf("\n%s: error in gethostbyname()", argv[0]);
exit(0);
}
/* create server address structure */
bzero(&servaddr, sizeof(servaddr)); /* initialize it */
servaddr.sin_family = AF_INET;
memcpy((char *) &servaddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
servaddr.sin_port = htons(atoi(argv[2])); /* get the port number from argv[2]*/
/* create a UDP socket: SOCK_DGRAM */
if ( (sockfd = socket(AF_INET,SOCK_DGRAM, 0)) < 0) {
printf("\n%s: error in socket()", argv[0]);
exit(0);
}
pthread_create(&readid,NULL,&readdata,NULL);
pthread_create(&writeid,NULL,&writedata,NULL);
while(1)
{
};
close(sockfd);
}
static void * writedata(void *arg)
{
/* get user input */
printf("\nEnter text: ");
do {
if (fgets(sendline, STRLEN, stdin) == NULL) {
printf("\n%s: error in fgets()");
exit(0);
}
/* send a text */
if (sendto(sockfd, sendline, sizeof(sendline), 0, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
printf("\n%s: error in sendto()");
exit(0);
}
}while(1);
}
static void * readdata(void *arg)
{
/* wait for echo */
slen = sizeof(servaddr);
if ( (n = recvfrom(sockfd, recvline, STRLEN, 0, (struct sockaddr *) &servaddr, &slen)) < 0) {
printf("\n%s: error in recvfrom()");
exit(0);
}
/* null terminate the string */
recvline[n] = 0;
fputs(recvline, stdout);
}
The problem is that you're using the same sockaddr struct (servaddr) for both the sendto and revfrom calls. The recvfrom happens first, so it clears out servaddr in preparation for writing in the source address of the received packed (once it receives one -- that thread is still blocked in the kernel waiting for a packet). Then, when the sendto call occurs, the sockaddr is all zeros, so it immediately returns EINVAL.
You may be getting confused by the fact that the sockaddr argument to recvfrom is an OUTPUT, not an input -- it gets filled in with the source address of the packet that is received (which could be from anywhere). If you want to only receive packets from a particular place (the server?), you need to check the address after the recvfrom returns and toss the packet if it comes from somewhere else, looping back to recvfrom again.