如何在C中的udpclient中使用pthreads进行发送和接收

如何在C中的udpclient中使用pthreads进行发送和接收,c,udp,pthreads,client,C,Udp,Pthreads,Client,我正在尝试修改我的教授提供的一个客户端程序,以便它将pthreads用于函数sendto()和recvFrom()。我能够对它进行时间标记,让客户端接收和发送消息,并让我的udpserver.c回显消息。但是我不能让我的pthread工作。我对pthreads有点陌生。这是我得到的错误: /tmp/cciYoHsc.o:udpclient.c:(.text+0x253): undefined reference to `_sendMessage' /tmp/cciYoHsc.o:udpclien

我正在尝试修改我的教授提供的一个客户端程序,以便它将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);
}
#包括
#包括
#包括
#包括
#如果你赢了
#包括
#包括
#恩迪夫
#如果得胜
#包括
#包括
#包括
#恩迪夫
/*下面是sockaddr_in结构和sockaddr结构的一些详细信息
这些声明是从winsock.h复制的
_addr{此结构包含一个32位IP地址
联合{
结构{u_char s_b1,s_b2,s_b3,s_b4;}s_un_b;
结构{u_short s_w1,s_w2;}s_un_w;
u_long S_addr;
}苏恩;
#定义s_地址s_un.s_地址
{注意,这个结构有16个字节长
小仙姑家族;
u_短sinu端口;
结构输入地址sin地址;
char sin_zero[8];
};
struct sockaddr{这个通用地址结构也是16字节长!
u_short Sau家族;
char sa_数据[14];
};
*/
/*我们必须在服务器侦听的同一端口上发送*/
#定义端口20009
/*简单upd客户端*/
//原型
void*发送消息(void*ptr);
void*recvMessage(void*ptr);
类型定义结构信息{
整数大小;
字符缓冲区[100];
int N字节、标志、地址;
}信息;
//size=sendto(sock,(char*)缓冲区,n字节,标志,(struct sockaddr*)和target_pc,(int)ptr);
int main()
{
#如果你赢了
插座;
#否则
静态int-sock;
#恩迪夫
静态整数大小;
静态整数n字节,标志;
静态int-i;
静态字符*cp;
#如果你赢了
WSADATA WSADATA;
int-nCode;
#恩迪夫
静态字符缓冲区[100];
静态字符str_addr[20];/*保存IP地址的字符*/
目标计算机中的静态结构sockaddr_,me;
/*初始化网络I/O代码的神奇调用-只有Microsoft需要*/
#如果你赢了
如果((nCode=WSAStartup(MAKEWORD(1,1),&wsaData))!=0)
{
printf(“Opps!WSA错误%d\n”,nCode);
返回-1;
}
#恩迪夫
/*创建要发送的套接字*/
sock=插座(PF_INET,sock_DGRAM,0);
if(sock<0)
{
printf(“套接字错误=%d\n”,sock);
返回-1;
}
/*我们填写了地址族和端口,但还不知道目标IP地址*/
target_pc.sin_family=PF_INET;
target_pc.sin_port=htons(port);
/*填写我的地址和港口*/
me.sin_family=PF_INET;
me.sin_port=htons(0);
me.sin_addr.s_addr=htonl(在任何情况下);
i=bind(sock,(struct sockaddr*)&me,sizeof(me));
if(i<0)
{
printf(“绑定结果:%d\n”,i);
返回-1;
}
n字节=99;
//创建线程
pthread_t sendT;
pthread_t recvT;
而(1)
{
结构时间值;
结构时间值te2;
信息*发送信息;
信息*recvInfo;
printf(“输入目标IP地址:”);
cp=fgets(str_addr,19,stdin);
/*删除\n*/
str_addr[strlen(str_addr)-1]='\0';
/*inet_addr函数将IP地址的字符串形式转换为32位二进制整数*/
target_pc.sin_addr.s_addr=inet_addr(&str_addr[0]);
printf(“输入您的消息:”);
cp=fgets(缓冲区,99,标准输入);
/*获取字符串长度,这样我们就可以发送这么多字符*/
n字节=strlen(缓冲区);
flags=0;
int addrlen=sizeof(目标计算机);
sendInfo->size=size;
sendInfo->buffer=buffer;
sendInfo->nbytes=nbytes;
sendInfo->flags=标志;
sendInfo->addrlen=addrlen;
pthread_创建(&sendT,NULL,sendMessage,(void*)addrlen);
//size=sendto(sock,(char*)缓冲区,n字节,标志,(struct sockaddr*)和target_pc,sizeof(target_pc));
//时间
gettimeofday(&te,NULL);
长毫秒=te.tv_sec*1000LL+te.tv_usec/1000;
printf(“[发送时间:%lld]”,毫秒);
printf(“[msg size=%d size=%d]\n”,n字节,大小);
//增加
pthread_创建(&sendT,NULL,recvMessage,(void*)addrlen);
//大小=recvfrom(sock、buffer、n字节、标志、(struct sockaddr*)和target_pc和addrlen);
printf(“回显消息:”);
如果((尺寸>0)和(&(尺寸<99))
{
buffer[size]='\0';//添加空字节,以便buffer现在保存字符串
i=put((char*)buffer);//将此字符串写入显示器
}
//时间
gettimeofday(&te2,NULL);//获取当前时间
毫秒=te.tv_sec*1000LL+te.tv_usec/1000;//计算毫秒
printf(“[接收时间:%lld]\n”,毫秒);
pthread_join(sendT,NULL);
pthread_join(recvT,NULL);
}
#如果你赢了
系统(“暂停”);
#恩迪夫
返回0;
}
void*发送消息(void*ptr){
//size=sendto(sock,(char*)缓冲区,n字节,标志,(struct sockaddr*)和target_pc,(int)ptr);
}
void*recvMessage(void*ptr){
//大小=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;
}
#包括
#包括
#包括
#如果你赢了
#包括
#包括
#恩迪夫
#如果得胜
#包括
#包括
#包括
#恩迪夫
#定义端口20009
/*简单upd服务器
此程序接收短消息(0)和(大小<99)){
buffer[size]='\0';/*添加空字节,以便buffer现在保存字符串*/
i=put((char*)buffer);/*将此字符串写入显示器*/
}
//回声m
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);
}
void *sendMessage( void *ptr )
void *recvMessage( void *ptr )
/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