Wierd behaviour inside thread function - c

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.

Related

Multithread server client C

Hello i have some problem with threads and client and server implementation, i created 2 clients that write on the socket infinite numbers.
to managed the 2 client in the sever.c i create threads everytime a new connection is accept.
it runs but if one client run it works but if i run the second one the first interrupted itself; how can i printf alternately ?
i would like : G1
G2
G1 etc
G1.
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
void error(char *msg)
{
perror(msg);
exit(0);
}
struct message { //dichiarazione struct
time_t timestamp;
char g; //process identifier
int x;
};
int main(int argc, char *argv[])
{
int sockfd, portno, n,i;
struct message m1;
struct sockaddr_in serv_addr;
struct hostent *server;
struct timespec delay;
delay.tv_sec = 1;
delay.tv_nsec = 0; //in microseconds
long int offset=1000000;
struct timeval tv;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_UNIX;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
while(1){
m1.timestamp=time(NULL);
m1.x=i;
m1.g=getpid();
n = write(sockfd,&m1,sizeof(m1));
if (n < 0)
error("ERROR writing to socket");
i++;
delay.tv_nsec=offset+rand()%offset;
nanosleep(&delay,NULL);
}
return 0;
}`
R.c(server)
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include <arpa/inet.h>
#include <fcntl.h> // for open
#include <unistd.h> // for close
#include<pthread.h>
struct message { //dichiarazione struct
time_t timestamp;
char g; //process identifier
int x;
};
struct message client_message;
char buffer[1024];
static void * socketThread(void *arg)
{
while(1) {
int newSocket = *((int *)arg);
recv(newSocket , &client_message , sizeof(client_message), 0);
printf("message %d %d %ld\n",client_message.x,client_message.g,client_message.timestamp);
fflush(stdout);
sleep(1);
}
}
int main(){
int serverSocket, newSocket;
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
//Create the socket.
serverSocket = socket(AF_UNIX, SOCK_STREAM, 0);
// Configure settings of the server address struct
// Address family = Internet
serverAddr.sin_family = AF_UNIX;
//Set port number, using htons function to use proper byte order
serverAddr.sin_port = htons(6005);
//Set IP address to localhost
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
//Set all bits of the padding field to 0
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
//Bind the address struct to the socket
bind(serverSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
//Listen on the socket, with 40 max connection requests queued
if(listen(serverSocket,50)!=0)
{
printf("Error\n");
return -1;
}
printf("Listening\n");
pthread_t tid[60];
int i = 0;
while(1)
{
//Accept call creates a new socket for the incoming connection
addr_size = sizeof serverStorage;
newSocket = accept(serverSocket, (struct sockaddr *) &serverStorage, &addr_size);
//for each client request creates a thread and assign the client request to it to process
//so the main thread can entertain next request
if( pthread_create(&tid[i], NULL, socketThread, &newSocket) != 0 )
printf("Failed to create thread\n");
else
++i;
}
return 0;
}
Thanks !
As I understand in server code in thread function socketThread() you get value of socket descriptor on each iteration. But when you accept new connection in this address writes new value of new socket descriptor. And after that each thread gets data only from last socket.
You should pass in socketThread() socket descriptor by value (not by a pointer)!

Two clients write on server and another client read from it with socket in C

I'm new in socket programming.
My program creates two clients that write to a server, this server reads data using threads and then prints them. I would like to send all this data to another client when it makes a request. Have I to create another socket or is it possible to use the same used before?
Here is my code.
Thanks.
Server.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include <arpa/inet.h>
#include <fcntl.h> // for open
#include <unistd.h> // for close
#include<pthread.h>
struct message { //dichiarazione struct
time_t timestamp;
char g; //process identifier
int x;
};
struct message client_message[10000];
int q=0;
static void * socketThread(void *arg)
{
int newSocket = *((int *)arg);
while(read(newSocket , &client_message[q] , sizeof(client_message))!=0) {
printf("message %d %d %ld\n",client_message[q].x,client_message[q].g,client_message[q].timestamp);
fflush(stdout);
sleep(1);
q++;
}
pthread_exit(NULL);
}
int main(){
int serverSocket, newSocket;
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
//Create the socket.
serverSocket = socket(AF_UNIX, SOCK_STREAM, 0);
// Configure settings of the server address struct
// Address family = Internet
serverAddr.sin_family = AF_UNIX;
//Set port number, using htons function to use proper byte order
serverAddr.sin_port = htons(55555);
//Set IP address to localhost
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
//INADDR_ANY;
//Set all bits of the padding field to 0
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
//Bind the address struct to the socket
bind(serverSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
//Listen on the socket, with 40 max connection requests queued
if(listen(serverSocket,50)==0)
printf("Listening\n");
else
printf("Error\n");
pthread_t tid[2];
int i = 0;
while(i<2)
{
//Accept call creates a new socket for the incoming connection
addr_size = sizeof serverStorage;
newSocket = accept(serverSocket, (struct sockaddr *) &serverStorage, &addr_size);
//for each client request creates a thread and assign the client request to it to process
//so the main thread can entertain next request
if( pthread_create(&tid[i], NULL, socketThread, &newSocket) != 0 )
printf("Failed to create thread\n");
i++;
}
pthread_join(tid[1], NULL);
pthread_join(tid[0], NULL);
for(i=0;i<50;i++){
printf("%d aaa %d\n",client_message[i].x,client_message[i].g);
}
close(newSocket);
return 0;
}

printing client ip when server is on same machine

I am writing a simple tcp echo client server code both my client and server code are running on the same machine i did bind two different addresses to client and server but client ip address is not getting printed when connected to server i changed addresses and still i was not able to print address i don't see any mistake in code.Is this my os issue or am i making some mistake.
my server code:
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<string.h>
#include<netinet/in.h>
#define ERROR -1
#define MAX_CLIENTS 10
#define MAX_DATA 1024
int main(int argc, char *argv[]){
struct sockaddr_in server;
struct sockaddr_in client;
int sock;
int new;
int sockaddr_len = sizeof(struct sockaddr_in);
int data_len;
char data[MAX_DATA+1];
if((sock = socket(AF_INET,SOCK_STREAM,0)) == ERROR){
perror("server socket");
exit(-1);
}
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[1]));
inet_aton(argv[2],&server.sin_addr.s_addr);
bzero(&server.sin_zero,0);
if(bind(sock, (struct sockaddr *)&server,sockaddr_len) == ERROR){
perror("bind");
exit(-1);
}
if(listen(sock, MAX_CLIENTS) == ERROR){
perror("listen");
exit(-1);
}
while(1){
if((new = accept(sock,(struct sockaddr *)&client,&sockaddr_len)) == ERROR){
perror("accept");
exit(-1);
}
//ip not getting printed
printf("New client connected from port no %d IP %s\n",ntohs(client.sin_port),inet_ntoa(client.sin_addr.s_addr));
data_len = 1;
while(data_len){
data_len = recv(new,data,MAX_DATA,0);
if(data_len){
send(new, data, data_len,0);
data[data_len] = '\0';
printf("Sent message: %s", data);
}
}
printf("Client disconnected\n");
close(new);
}
}
my client code:
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<string.h>
#include<netinet/in.h>
#define ERROR -1
#define BUFFER 1024
int main(int argc, char *argv[]){
struct sockaddr_in remote_server,client;
int sock,len;
char input[BUFFER];
char output[BUFFER+1];
client.sin_family = AF_INET;
client.sin_port = htons(3000);
inet_aton("127.0.2.8",&client.sin_addr.s_addr);
bzero(&client.sin_zero,0);
if((sock = socket(AF_INET,SOCK_STREAM,0)) == ERROR){
perror("socket");
exit(-1);
}
int size = sizeof(struct sockaddr_in);
if(bind(sock, (struct sockaddr *)&client,size) == ERROR){
perror("bind");
exit(-1);
}
remote_server.sin_family = AF_INET;
remote_server.sin_port = htons(atoi(argv[2]));
remote_server.sin_addr.s_addr = inet_addr(argv[1]);
bzero(&remote_server.sin_zero , 0);
if((connect(sock ,(struct sockaddr *)&remote_server , sizeof(struct sockaddr_in))) == ERROR){
perror("connect");
exit(-1);
}
while(1){
fgets(input, BUFFER, stdin);
send(sock, input, strlen(input) , 0);
len = recv(sock,output,BUFFER,0);
output[len] = '\0';
printf("%s\n",output);
}
close(sock);
}
This is the output:
New client connected from port no 3000 and IP
First of all you need two more includes in client as well as server
#include<arpa/inet.h> // for inet_aton(), inet_addr() and inet_ntoa()
#include<unistd.h> //for close()
Secondly,
The function declaration for inet_aton() and inet_ntoa() are respectively:
int inet_aton(const char *cp, struct in_addr *inp);
and
char *inet_ntoa(struct in_addr in);
So, You must pass the entire structure i.e xyzaddr.sin_addr instead of xyzaddr.sin_addr.s_addr(which is an int)
Hence make these changes as well:
In server:
inet_aton(argv[2],&server.sin_addr.s_addr); -> inet_aton(argv[2],&server.sin_addr);
inet_ntoa(client.sin_addr.s_addr) -> inet_ntoa(client.sin_addr)
In client:
inet_aton("127.0.2.8",&client.sin_addr.s_addr); -> inet_aton("127.0.2.8",&client.sin_addr);

Recv() not working in separate thread, C socket programming

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.

How to use pthreads for sending and receiving in a udpclient in C

I'm trying to modify a client program that my professor supplied so that it will use pthreads for the functions sendto() and recvFrom(). I was able to timetag it and have the client receive as well as send messages and have my udpserver.c echo back messages. But I can't get my pthreads to work. I'm kinda new to pthreads. This is the error I got:
/tmp/cciYoHsc.o:udpclient.c:(.text+0x253): undefined reference to `_sendMessage'
/tmp/cciYoHsc.o:udpclient.c:(.text+0x2f2): undefined reference to `_recvMessage'
collect2: ld returned 1 exit status
I think it might have something to do with all the ifdef/endif keywords. I'm not really sure what all they do. This is my program udpclient.c
/*UPDATED*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.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 */
//prototypes
void *sendMessage( void *ptr );
void *recvMessage( void *ptr );
typedef struct info {
int size;
char buffer[100];
int nbytes,flags,addrlen;
} info;
//size = sendto(sock, (char *) buffer, nbytes,flags,(struct sockaddr *)&target_pc,(int)ptr);
int main()
{
#ifdef WIN
SOCKET sock;
#else
static int sock;
#endif
static int size;
static int nbytes, flags;
static int i;
static char * cp;
#ifdef WIN
WSADATA wsaData;
int nCode;
#endif
static char buffer[100];
static char str_addr[20]; /* holds the chars of an IP address */
static 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;
//create threads
pthread_t sendT;
pthread_t recvT;
while(1)
{
struct timeval te;
struct timeval te2;
info *sendInfo;
info *recvInfo;
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;
int addrlen = sizeof(target_pc);
sendInfo->size = size;
sendInfo->buffer = buffer;
sendInfo->nbytes = nbytes;
sendInfo->flags = flags;
sendInfo->addrlen = addrlen;
pthread_create( &sendT, NULL, sendMessage, (void*) addrlen);
//size = sendto(sock, (char *) buffer, nbytes,flags,(struct sockaddr *)&target_pc,sizeof(target_pc));
//time
gettimeofday(&te, NULL);
long long milliseconds = te.tv_sec*1000LL + te.tv_usec/1000;
printf("[Time Sent: %lld]", milliseconds);
printf("[msg size = %d size = %d]\n", nbytes, size);
//added
pthread_create( &sendT, NULL, recvMessage, (void*) addrlen);
//size = recvfrom(sock, buffer, nbytes, flags, (struct sockaddr *)&target_pc,&addrlen);
printf("Echo message: ");
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
}
//time
gettimeofday(&te2, NULL); // get current time
milliseconds = te.tv_sec*1000LL + te.tv_usec/1000; // caculate milliseconds
printf("[Time Received: %lld]\n", milliseconds);
pthread_join(sendT,NULL);
pthread_join(recvT,NULL);
}
#ifdef WIN
system("PAUSE");
#endif
return 0;
}
void *sendMessage( void *ptr ){
//size = sendto(sock, (char *) buffer, nbytes,flags,(struct sockaddr *)&target_pc,(int)ptr);
}
void *recvMessage( void *ptr ){
//size = recvfrom(sock, buffer, nbytes, flags, (struct sockaddr *)&target_pc,(int*)ptr);
}
Here is udpserver.c for reference:
#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;
}
Ithink i found the problem. Im not sure, im typing and reading on a iPad.
In the end of your main function, you have placed the declaration of
void *sendMessage( void *ptr )
void *recvMessage( void *ptr )
inside of the main. Move them outside.
/tmp/cciYoHsc.o:udpclient.c:(.text+0x253): undefined reference to `_sendMessage'
/tmp/cciYoHsc.o:udpclient.c:(.text+0x2f2): undefined reference to `_recvMessage'
collect2: ld returned 1 exit status
I believe that this will solve the problem.
As i said, im not able to test the code myself.
Good luck
void *sendMessage( void *ptr ){
size = sendto(sock, (char *) buffer, nbytes,flags,(struct sockaddr *)&target_pc,(int)ptr);
}
void *recvMessage( void *ptr ){
size = recvfrom(sock, buffer, nbytes, flags, (struct sockaddr *)&target_pc,(int*)ptr);
}
you define size in main then try and use it in your threaded functions, you cant do that...

Resources