试图让udp服务器回显到udp客户端并在屏幕上打印,同时让udp客户端接收消息

时间:2013-08-07 19:51:22

标签: c udp client echo

我正在尝试修改这两个程序。我想让udpclient.c能够接收消息并让udpserver.c将消息回送给客户端。我还希望在发送之前使用udpclient时间标记消息。收到的消息应该导致服务器的IP地址和客户端打印的往返时间(RTT)。当我测试它时,客户端发送和服务器接收但服务器不回显消息。我试图修改的地方是每个程序的无限循环,而不是“// added”

udpclient.c

#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

#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 */
         }

       //added
       sock = socket(PF_INET,SOCK_DGRAM,0);//
       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;
}

1 个答案:

答案 0 :(得分:1)

(如果您阅读我之前的回答,请忽略它。这是不正确的。)

你错过了'&amp;'在udpserver.c的第82行的addrlen前面。它应该是:

size = recvfrom(sock, buffer, nbytes, flags, (struct sockaddr *)&from, &addrlen);

除了你的代码工作正常(我运行它)。但是,我想提一下三件事:

  1. 客户端无需绑定其套接字即可从服务器接收消息。
  2. 服务器无需创建新套接字即可向客户端发送消息。只需使用名为recvfrom的套接字。
  3. 套接字应在不再使用后关闭(即使在程序结束时)。打开太多套接字会导致无法创建任何新套接字。