I am having some issues with the recv() function returning a -1 in a C program with threading. The basis of the program is to receive a few request packets in one thread and having a second thread send out a multicast to all registered clients.
Below is the code for my server:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <arpa/inet.h>
#include <pthread.h>
#define SERVER_PORT 5654
#define MAX_LINE 256
#define MAX_PENDING 5
/*structure of the packet*/
struct packet{
short type;
char data[MAX_LINE];
};
struct data_packet{
short header;
char data[MAX_LINE];
};
/* structure of Registration Table */
struct registrationTable{
int port;
char name[MAX_LINE];
int req_no;
};
struct global_table{
int sockid;
int reqno;
};
void *join_handler(struct global_table *rec){
int new_s;
struct packet packet_reg;
new_s = rec->sockid;
printf("In thread: %i\n",new_s);
printf("In thread: %i\n",rec->reqno);
if(recv(new_s,&packet_reg,sizeof(packet_reg),0)<0){
printf("\ncouldnt receive first reg packet\n");
exit(1);
}
pthread_exit(NULL);
}
int main(int argc, char* argv[])
{
/* initilizing all of the packets*/
struct packet packet_reg;
struct registrationTable table[10];
struct global_table record[20];
struct sockaddr_in sin;
struct sockaddr_in clientAddr;
char buf[MAX_LINE];
int s, new_s;
int len;
int i;
struct hostent *he;
struct in_addr **addr_list;
pthread_t threads[2];
/* setup passive open */
if((s = socket(PF_INET, SOCK_STREAM, 0)) < 0){
perror("tcpserver: socket");
exit(1);
}
/* build address data structure */
bzero((char*)&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(SERVER_PORT);
if(bind(s,(struct sockaddr *)&sin, sizeof(sin)) < 0){
perror("tcpclient: bind");
exit(1);
}
listen(s, MAX_PENDING);
/* wait for connection, then receive and print text */
while(1){
if((new_s = accept(s, (struct sockaddr *)&clientAddr, &len)) < 0){
perror("tcpserver: accept");
exit(1);
}
/* print the port of the client*/
printf("\n Client's port is %d \n", ntohs(clientAddr.sin_port));
/* receive the first registration packet*/
if(recv(new_s,&packet_reg,sizeof(packet_reg),0)<0){
printf("\ncouldnt receive first reg packet\n");
exit(1);
}
struct global_table client_info;
client_info.sockid = ntohs(clientAddr.sin_port);
client_info.reqno = 1;
pthread_create(&threads[0],NULL,join_handler, &client_info);
}
}
Client:
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#define SERVER_PORT 5654
#define MAX_LINE 256
/*structure of the packet*/
struct packet{
short type;
char data[MAX_LINE];
};
struct data_packet{
short header;
char data[MAX_LINE];
};
int main(int argc, char* argv[])
{
struct packet packet_reg;
struct hostent *hp;
struct sockaddr_in sin;
char *host;
char buf[MAX_LINE];
int s;
int len;
char hostname[1024];
hostname[1023] = '\0';
if(argc == 2){
host = argv[1];
}
else{
fprintf(stderr, "usage:newclient server\n");
exit(1);
}
/* translate host name into peer's IP address */
hp = gethostbyname(host);
if(!hp){
fprintf(stderr, "unkown host: %s\n", host);
exit(1);
}
/* active open */
if((s = socket(PF_INET, SOCK_STREAM, 0)) < 0){
perror("tcpclient: socket");
exit(1);
}
/* build address data structure */
bzero((char*)&sin, sizeof(sin));
sin.sin_family = AF_INET;
bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
sin.sin_port = htons(SERVER_PORT);
if(connect(s,(struct sockaddr *)&sin, sizeof(sin)) < 0){
perror("tcpclient: connect");
close(s);
exit(1);
}
/* main loop: get and send lines of text
all you have to do to start the program is
enter any key */
while(fgets(buf, sizeof(buf), stdin)){
/* Find the hostname and print it*/
gethostname(hostname, 1023);
printf("Hostname: %s\n", hostname);
/* populate the info for the first registration packet*/
packet_reg.type = htons(121);
strcpy(packet_reg.data,hostname);
/*send the registration packet to the server*/
if(send(s,&packet_reg,sizeof(packet_reg),0)<0){
printf("\nsend failed\n");
exit(1);
}
/* Print the contents of the first registration packet*/
printf("Sent 1st reg packet data: %s\n",packet_reg.data );
printf("Sent 1st reg packet type: %i\n",ntohs(packet_reg.type));
/* create the second registration packet.
I created separate packets for this so
it was clearer*/
packet_reg.type = htons(121);
strcpy(packet_reg.data,hostname);
/*send the second registration packet to the server*/
if(send(s,&packet_reg,sizeof(packet_reg),0)<0){
printf("\nsend failed\n");
exit(1);
}
/* Print the contents of the second registration packet*/
printf("Sent 2nd reg packet data: %s\n",packet_reg.data );
printf("Sent 2nd reg packet type: %i\n",ntohs(packet_reg.type));
}
}
So Basically, I am creating the connection and wait to receive the first registration packet (packet_reg). This works and I receive the packet. I then send control of the program to the thread. However, while the "rec" variable correctly passes the information, the subsequent receive does not work and exits with a value less than 0.
Other information: The packets are all sent and received correctly, but the client's port, printed from
printf("\n Client's port is %d \n", ntohs(clientAddr.sin_port));
is listed as 0. I am not sure if this is a problem, but the code works fine when all of the receives are in the main function.
Another issue could be that I get the following warning:
passing argument 3 pf pthread_create from incompatible pointer type expected 'void * (*) (void *)' but argument of type 'void * (*) (struct global_table*)'
I have researched this warning and know that it has to do with receiving the data as void and then casting. However, the data is being sent to the thread properly when I print from there to check.
Basically, the problem is that while I can receive the packets from the client outside the thread, with the same statements, when I am inside the thread the packets are not received and recv() returns -1.
I accidentally set the receive to the port and not the socket. I am a dummy. I know that a lot of you were telling me how bad the code is constructed regarding TCP conventions. I am building off of code for an assignment, nothing I can do about the professor telling us that this is the way to do it.
Related
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.
I have a server program written in C with a thread function join_handler. When i invoke this function in main- nothing after the statement -- printf("inside join handler %d",newsock); executes inside the thread function .
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include<string.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include<pthread.h>
#define SERVER_PORT 5498
#define MAX_LINE 256
#define MAX_PENDING 5
#define MAXNAME 256
int req_no;
char packet_type[50];
//void* join_handler(struct*);
struct packet{
short type;
char data[MAXNAME];
};
struct packet packet_reg;
struct global_table{
int sockid;
int reqno;
};
struct global_table record[20];
void *join_handler(void *rec)
{
//pthread_mutex_t my_mutex= PTHREAD_MUTEX_INITIALIZER;
int *newsock;
newsock=(int*)rec;
printf("inside join handler %d",newsock); /// the last statement which gets executed
printf("\n %d",newsock);
if(recv(newsock,&packet_reg,sizeof(packet_reg),0)<0)
{
printf("\n Could not receive \n");
exit(1);
}
printf("\n joinhandler sockid is %d",newsock);
//other operation
pthread_exit(NULL);
}
int main(int argc, char* argv[])
{
pthread_t threads[2];
struct sockaddr_in sin;
struct sockaddr_in clientAddr;
char buf[MAX_LINE];
int s, new_s;
struct in_addr addr;
struct hostent *host;
int len;
struct registrationTable
{
int port;
char name[MAXNAME];
int req_no;
};
struct registrationTable table[10];
int *exit_value;
req_no=0;
char clientname[500];
/* setup passive open */
if((s = socket(PF_INET, SOCK_STREAM, 0)) < 0){
perror("tcpserver: socket");
exit(1);
}
/* build address data structure */
bzero((char*)&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(SERVER_PORT);
if(bind(s,(struct sockaddr *)&sin, sizeof(sin)) < 0){
perror("tcpclient: bind");
exit(1);
}
listen(s, MAX_PENDING);
/* wait for connection, then receive and print text */
while(1){
if((new_s = accept(s, (struct sockaddr *)&clientAddr, &len)) < 0){
perror("tcpserver: accept");
exit(1);
}
recv(new_s,&packet_reg, sizeof(packet_reg), 0);
if(recv(new_s,&packet_reg, sizeof(packet_reg), 0)<0)
{
printf("\n Could not receive first registration packet \n");
exit(1);
}
pthread_create(&threads[0],NULL,join_handler,new_s);
pthread_join(threads[0],&exit_value);
}
}
You won't see any output until a \n.
Therefore, you won't see this line executed:
printf("\n %d",newsock);
That doesn't mean it isn't executing, just that the output is buffered and you won't see it until recv receives something. But, my guess is it won't until you send something back to the client, since you read the first packet before starting the thread.
This is a simple server that merely accepts connections, then prints the socket descriptor. For some reason, whenever I run this the only socket descriptors I receive are of value 0. This even occurs with multiple clients connecting simultaneously. I seem to be misunderstanding something to do with the behavior of accept(), or there is some bug I cannot locate in my code. Here is the code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
/* Utility for consisely killing the program. */
void abort_program(const char *error_message)
{
fputs(error_message, stderr);
exit(EXIT_FAILURE);
}
/* Establishes a passive listening port, returns socket descriptor. */
int setup_passive_port(int port)
{
struct protoent *ptrp; // pointer to a protocol table entry
struct sockaddr_in sad; // structure to hold server's address
int sd; // socket descriptor for listening
/* Map TCP transport protocol name to protocol number. */
if (((long int) (ptrp = getprotobyname("tcp"))) == 0)
abort_program("ERROR: Cannot map TCP to protocol number\n");
/* Create a socket. */
sd = socket(PF_INET, SOCK_STREAM, ptrp->p_proto);
if (sd < 0)
abort_program("ERROR: Socket creation failed\n");
/* Prepare the socket address structure. */
memset((char *) &sad, 0, sizeof(sad));
sad.sin_family = AF_INET;
sad.sin_addr.s_addr = INADDR_ANY;
sad.sin_port = htons((u_short) port);
/* Bind a local address to the socket. */
if (bind(sd, (struct sockaddr*) &sad, sizeof(sad)) < 0)
abort_program("ERROR: Bind failed\n");
/* Establish passive listener socket. */
if (listen(sd, 0) < 0)
abort_program("ERROR: Listen failed\n");
return sd;
}
int main(int argc, char *argv[])
{
struct sockaddr_in cad; // structure to hold client's address
int alen; // length of address
int sd; // incoming socket
int listener; // listening socket
listener = setup_passive_port(30000);
while (1) {
if (sd = accept(listener, (struct sockaddr*) &cad, &alen) < 0)
abort_program("ERROR: Accept failed\n");
printf("%d\n", sd);
}
}
Can you help me understand why? Thanks for your consideration.
One thing you need to do is to set your alen to the sizeof(sockaddr_in) prior to calling accept(). The other is that at least clang complains about the missing brackets within your if( accept()...) line. Here the fixed up version.
telnet localhost 30000 worked as expected.
Also changed your int alen to socklen_t alen while being at it.
int main(int argc, char *argv[])
{
struct sockaddr_in cad; // structure to hold client's address
socklen_t alen = sizeof(sockaddr_in); // length of address
int sd; // incoming socket
int listener; // listening socket
listener = setup_passive_port(30000);
while (1) {
if ((sd = accept(listener, (struct sockaddr*) &cad, &alen)) < 0)
abort_program("ERROR: Accept failed\n");
printf("%d\n", sd);
}
}
How would I go about making this udpclient asynchronous using pthreads? I want to make sure UDP datagram won't be lost and also don't want the client program to wait forever and not be able to send any more messages
/*udpclient.c program */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN
#include <winsock.h>
#include <windows.h>
#endif
#ifndef WIN
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#endif
/* Here are some details of the sockaddr_in structure and the sockaddr structure
These declarations are copied from winsock.h
struct in_addr { this struct holds a 32 bit IP address
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
} S_un;
#define s_addr S_un.S_addr
struct sockaddr_in { notice this structure is 16 bytes long
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
struct sockaddr { this generic address structure is 16 bytes long, too!
u_short sa_family;
char sa_data[14];
};
*/
/* we have to send on the same port the server is listening on */
#define PORT 20009
/* simple upd client */
int main()
{
#ifdef WIN
SOCKET sock;
#else
int sock;
#endif
int size;
int nbytes, flags;
int i;
char * cp;
#ifdef WIN
WSADATA wsaData;
int nCode;
#endif
char buffer[100];
char str_addr[20]; /* holds the chars of an IP address */
struct sockaddr_in target_pc, me;
/* magic call to initialize the network I/O code - only Microsoft requires this */
#ifdef WIN
if((nCode = WSAStartup(MAKEWORD(1,1), &wsaData)) != 0){
printf("Opps! WSA error %d\n",nCode);
return -1;
}
#endif
/* create a socket to send on */
sock = socket(PF_INET,SOCK_DGRAM,0);
if(sock < 0) {
printf("socket error = %d\n", sock);
return -1;
}
/* we fill in the address family and port, but we do not know the destination IP address yet */
target_pc.sin_family = PF_INET;
target_pc.sin_port = htons(PORT);
/* fill in my address and port */
me.sin_family = PF_INET;
me.sin_port = htons(0);
me.sin_addr.s_addr = htonl(INADDR_ANY);
i = bind(sock, (struct sockaddr *) &me, sizeof(me));
if( i < 0) {
printf("bind result: %d\n", i);
return -1;
}
nbytes = 99;
while(1){
printf("Enter the target IP address: ");
cp = fgets(str_addr,19,stdin);
/* remove the \n */
str_addr[strlen(str_addr)-1] = '\0';
/* the inet_addr function converts a string form of IP address to a 32 binary integer */
target_pc.sin_addr.s_addr = inet_addr(&str_addr[0]);
printf("Enter your message: ");
cp = fgets(buffer,99,stdin);
/* get the string length so we send exactly this many characters */
nbytes = strlen(buffer);
flags = 0;
size = sendto(sock, (char *) buffer, nbytes,flags,(struct sockaddr *)&target_pc,sizeof(target_pc));
printf("msg size = %d size = %d\n", nbytes, size);
//added
int addrlen = sizeof(target_pc);
size = recvfrom(sock, buffer, nbytes, flags, (struct sockaddr *)&target_pc,&addrlen);
if((size > 0) && (size < 99)){
buffer[size] = '\0'; //add the null byte so buffer now holds a string
i = puts((char *) buffer); // write this string to the display
}
}
#ifdef WIN
system("PAUSE");
#endif
return 0;
}
/udpserver.c program/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#ifdef WIN
#include <winsock.h>
#include <windows.h>
#endif
#ifndef WIN
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#endif
#define PORT 20009
/* simple upd server
this program receives short messages (<99 characters) from any IP address
and writes them to the display
be sure to use the linker line option "-l wsock32"
*/
int main()
{
/* first define a socket
a socket is an I/O port like a file descriptor
*/
#ifdef WIN
SOCKET sock; /* SOCKET is a typedef for a structure */
#else
int sock;
#endif
int size;
int nbytes, flags;
#ifdef WIN
int addrlen;
#else
socklen_t addrlen;
#endif
int i;
/* char loopback[20]="127.0.0.1"; */
#ifdef WIN
WSADATA wsaData; /* This is struct holds Windows required data */
int nCode;
#endif
char buffer[100];
struct sockaddr_in server; /* this holds my IP address and port info */
struct sockaddr_in from; /* this holds the same info for the sender of the packet
I received */
/* the call to WSAStartup is Windows magic */
#ifdef WIN
if((nCode = WSAStartup(MAKEWORD(1,1), &wsaData)) != 0){
printf("Opps! WSA error %d\n",nCode);
exit;
}
#endif
/* create a socket called sock. It is a datagram socket */
sock = socket(AF_INET,SOCK_DGRAM,0);
if(sock < 0){
printf("socket error = %d\n", sock);
return -1;
}
server.sin_family = AF_INET; /* initialize the server address family */
server.sin_addr.s_addr = htonl(INADDR_ANY); /* notice this struct within a struct */
/* printf("%x\n",server.sin_addr.s_addr); */
server.sin_port = htons(PORT);
/* associate the socket with the address structure - this is called binding */
i = bind(sock, (struct sockaddr *) &server, sizeof(server));
if( i < 0) {
printf("bind result: %d\n", i);
return -1;
} else
printf("Simple UDP server is ready!\n\n");
nbytes = 99; /* receive packets up to 99 bytes long */
flags = 0; /* must be zero or this will not work! */
while(1){
/* the recvfrom function is a read and the arguments are:
sock - the socket we are reading
buffer - array into which to read the data
nbytes - read up to this many bytes
flags - used for special purposes - not needed here
from - sockaddr struct to hold the IP address and port of the sender of the packet
addrlen - the size of the sockaddr struct written by this function
*/
addrlen = sizeof(from);
size = recvfrom(sock, buffer, nbytes, flags, (struct sockaddr *)&from, &addrlen);
if((size > 0) && (size < 99)){
buffer[size] = '\0'; /* add the null byte so buffer now holds a string */
i = puts((char *) buffer); /* write this string to the display */
}
//echo message back to client
if(sock < 0) {//
printf("socket error = %d\n", sock);//
return -1;//
}//
sendto(sock, buffer, nbytes, flags, (struct sockaddr *)&from,addrlen); //
}
#ifdef WIN
system("PAUSE");
#endif
return 0;
}
We could create two threads: one for the sendto (that waits for the user input) and the other for recvfrom(). Next, we can have the recvrom() use Pthread condvar (by calling pthread_cond_wait() on a condvar and a Pthread mutex) and wait. When the user provides an input, we can sendto (which is not really blocking) and then call pthread_cond_signal() to wake up the other thread.
You could certainly simply this, if you wanted. If your application permits, you could completely skip the pthread_cond_wait() since recvfrom() is anyways a blocking call. So, this way, recvfrom() would block but then it would go out of sync with the send calls. The other option is to use the main() thread for the sendto() thread -- in that case, you would just need one additional thread for the recv calls.
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.