我正在尝试修改我的教授提供的客户端程序,以便它将 pthreads 用于函数 sendto() 和 recvFrom()。我能够给它加上时间标签,让客户端接收和发送消息,并让我的 udpserver.c 回显消息。但我无法让我的 pthread 工作。我对pthreads有点陌生。这是我得到的错误:
/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
我认为这可能与所有 ifdef/endif 关键字有关。我不太确定他们所做的一切。这是我的程序 udpclient.c
/ *更新* /
#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);
}
这是 udpserver.c 供参考:
#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;
}