Segmentation Fault in UDP - c

I got a segmentation fault problem when I write a client-server project in UDP. It happens on server side, when I receive a packet from client and going to send an ACK back. I tried to search the solutions and got UDP Server giving Segmentation Fault and C concurrent UDP socket , weird segmentation fault, but seems both of those are not the answer I'm looking for.
Here is my server side code
#include <ctype.h> /* for toupper */
#include <stdio.h> /* for standard I/O functions */
#include <stdlib.h> /* for exit */
#include <string.h> /* for memset */
#include <sys/socket.h> /* for socket, sendto, and recvfrom */
#include <netinet/in.h> /* for sockaddr_in */
#include <unistd.h> /* for close */
#define STRING_SIZE 1024
#define SERV_UDP_PORT 12311
int main(void) {
int sock_server;
struct sockaddr_in server_addr;
unsigned short server_port;
struct sockaddr_in client_addr;
unsigned int client_addr_len;
char sentence[STRING_SIZE];
char modifiedSentence[STRING_SIZE];
unsigned int msg_len;
int bytes_sent, bytes_recd;
unsigned int i;
struct Pkt
{
short length;
short seqnum;
char databytes[80];
};
struct Pkt* pkt;
int j ; //for loop
int seq;
short num_of_bytes;
//char ack_num[2];
struct Ack
{
short ack_num;
};
struct Ack* ack;
/* open a socket */
if ((sock_server = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
perror("Server: can't open datagram socket\n");
exit(1);
}
/* initialize server address information */
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl (INADDR_ANY);
server_port = SERV_UDP_PORT;
server_addr.sin_port = htons(server_port);
/* bind the socket to the local server port */
if (bind(sock_server, (struct sockaddr *) &server_addr,
sizeof (server_addr)) < 0) {
perror("Server: can't bind to local address\n");
close(sock_server);
exit(1);
}
/* wait for incoming messages in an indefinite loop */
printf("Waiting for incoming messages on port %hu\n\n",
server_port);
client_addr_len = sizeof (client_addr);
for (;;) {
bytes_recd = recvfrom(sock_server, pkt, sizeof(*pkt), 0, (struct sockaddr *) &client_addr, &client_addr_len);
ack->ack_num = pkt->seqnum;
printf("%02d\n", ack->ack_num);
num_of_bytes = pkt->length;
printf("The sequence number is: %d\n", ack->ack_num);
printf("Received Sentence is: %s\n with length %d\n\n", pkt->databytes, num_of_bytes);
msg_len = 3;
/* send message */
bytes_sent = sendto(sock_server, (struct Ack*)&ack, msg_len, 0, (struct sockaddr*) &client_addr, client_addr_len); //Here is the segmentation fault comes from
}
}
I'm not really good at C, so forgive me if the code is silly.
Please point out anything wrong or just looks weird.
Thanks in advance for any help.

pkt is pointer to a Pkt, but you haven't initialized it. Likewise with ack. You can either a) malloc a Pkt and assign the result to pkt, or b) change pkt to be a Pkt structure (rather than a pointer). The second option would look something like:
struct Pkt pkt;
struct Ack ack;
bytes_recd = recvfrom(sock_server, &pkt, sizeof(pkt), 0, (struct sockaddr *) &client_addr, &client_addr_len);
ack.ack_num = pkt.seqnum;
printf("%02d\n", ack.ack_num);
num_of_bytes = pkt.length;
printf("The sequence number is: %d\n", ack.ack_num);
printf("Received Sentence is: %s\n with length %d\n\n", pkt.databytes, num_of_bytes);
/* send message */
bytes_sent = sendto(sock_server, &ack, sizeof(ack), 0, (struct sockaddr*) &client_addr, client_addr_len);

Related

When requesting time from server I get a Segmentation fault (core dumped). How can I resolve this?

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, &current_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(&current_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(&current_time, ...);

Sending a single unsigned char through a socket using UDP in C

I am trying to send a single unsigned char through a buffer. I am using a buffer of size 2
unsigned char temp_buf [2];
temp_buf [0]= (unsigned char) 0xff;
temp_buf [1]= NULL;
and my sendto functions looks like this:
if (sendto(fd, temp_buf, sizeof (temp_buf), 0, (struct sockaddr *)&remaddr, addrlen) < 0)
perror("sendto");
It compiles with no issues, however at run time i get an error:
sendto: Invalid argument
Which means there is something wrong with the buffer im using. I suspected that the issue might be because im using siezeof so i changed it to strlen(temp_buf) but still no luck!
EDIT: I was trying to make the question simpler by not including the whole code but here it is, Sorry about that!
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "port.h"
#define BUFSIZE 2048
int
main(int argc, char **argv)
{
struct sockaddr_in myaddr; /* our address */
struct sockaddr_in remaddr; /* remote address */
socklen_t addrlen = sizeof(remaddr); /* length of addresses */
int recvlen; /* # bytes received */
int fd; /* our socket */
int msgcnt = 0; /* count # of messages we received */
unsigned char buf[BUFSIZE]; /* receive buffer */
/* create a UDP socket */
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("cannot create socket\n");
return 0;
}
/* bind the socket to any valid IP address and a specific port */
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(SERVICE_PORT);
if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
perror("bind failed");
return 0;
}
/* now loop, receiving data and printing what we received */
printf("waiting on port %d\n", SERVICE_PORT);
//recvfrom(fd, buf, BUFSIZE, 0, (struct sockaddr *)&remaddr, &addrlen);
//buf [0] = 0xff;
unsigned char temp_buf [2];
temp_buf [0]= (unsigned char) 0xff;
temp_buf [1]= '\0';
if (sendto(fd, temp_buf, sizeof (temp_buf), 0, (struct sockaddr *)&remaddr, addrlen) < 0)
perror("sendto");
else
printf("%s \n", "Communication established");
}
The contents of remaddr are uninitialized. In other words, you're not telling sendto where to send the data.
You need to populate this struct with the IP and port you wish to send to.
If you uncomment the call to recvfrom and subsequently get a packet from some other service, remaddr gets populated with the IP/port that sent that packet, then you can use that to send a packet back. But without that, you need to fill in remaddr.

Why do I get an unexpected port value in C?

I'm writing a program which gets an identifier from params, creates an UDP socket, gets a port, and prints <identifier>: <port>.
Then, receives some identifiers and ports from stdin and store them in memory.
In the code below, the problem is that the port variable (udp_port) get 0.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
typedef struct process {
char id[80];
int port;
int me;
} process;
int main(int argc, char* argv[]) {
if(argc<2) {
fprintf(stderr,"Use: process <ID>\n");
return 1;
}
/* NODES */
process * processes;
int num_process = 0;
/* CONECTION */
int udp_port;
int fd;
struct sockaddr_in addr, local_addr;
/* STDIN READS */
int port;
char line[80],proc[80];
/* I/O buffer mode */
setvbuf(stdout,(char*)malloc(sizeof(char)*80),_IOLBF,80);
setvbuf(stdin,(char*)malloc(sizeof(char)*80),_IOLBF,80);
/* Prepare socket */
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(0);
addr.sin_addr.s_addr = INADDR_ANY;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if(fd == -1){
perror("SOCKET");
return 1;
}
if(bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1){
perror("BIND");
return 1;
}
getsockname(fd, (struct sockaddr *)&local_addr, (socklen_t *) sizeof(struct sockaddr));
udp_port=ntohs(local_addr.sin_port); // Gets port
fprintf(stdout,"%s: %d\n",argv[1],udp_port); // Prints identifier: port
// Reads from stdin
for(;fgets(line,80,stdin);) {
if(!strcmp(line,"START\n"))
break;
sscanf(line,"%[^:]: %d",proc,&port);
num_process++;
processes = realloc(processes,num_process);
strcpy(processes[num_process-1].id, proc);
processes[num_process-1].port = port;
if(!strcmp(proc,argv[1])){ /* Thats me */
processes[num_process-1].me = 1;
}else{
processes[num_process-1].me = 0;
}
}
return 0;
}
But, it gets a correct value (random port) when I comment the realloc line and related lines, like this:
// Reads from stdin
for(;fgets(line,80,stdin);) {
if(!strcmp(line,"START\n"))
break;
sscanf(line,"%[^:]: %d",proc,&port);
num_process++;
//processes = realloc(processes,num_process);
//strcpy(processes[num_process-1].id, proc);
//processes[num_process-1].port = port;
if(!strcmp(proc,argv[1])){ /* Thats me */
// processes[num_process-1].me = 1;
}else{
// processes[num_process-1].me = 0;
}
}
Your code crashes if used as it is. Because you pass to realloc uninitialized pointer. Initialize processes to NULL:
process * processes = NULL;
EDIT:
Otherwise, the udp_port is non zero. And getsockname returns Bad address.
Try the following for getsockname to be successsful:
socklen_t tmp = sizeof(struct sockaddr);
getsockname (fd, (struct sockaddr *) &local_addr,&tmp);
Checking the return value of getsockname function I get a Bad address error.
The problem was that the last parameter in getsockname was incorrect:
getsockname(fd, (struct sockaddr *)&local_addr, (socklen_t *) sizeof(struct sockaddr));
sizeof returns a socklen_t instead of socklen_t *. I fixed this like this:
socklen_t size_sa = sizeof(struct sockaddr);
if(getsockname(fd, (struct sockaddr *)&local_addr, &size_sa) == -1){
perror("GETSOCKNAME");
return 1;
}

How would I go about making this udpclient asynchronous using pthreads?

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.

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