原创 UDP用户数据报协议

2009-5-27 20:54 2114 4 4 分类: 软件与OS
rar
实现一个基于UDP的应用
UDP的所调用的函数和用于TCP的函数非常类似。这主要因为套接口库在底层的TCP和UDP函数上加了一层抽象。
在使用TCP和使用UDP之间,函数调用的惟一实际区别在于socket函数调用的一个参数。这个参数为SOCK_STREAM时代表TCP,而SOCK_DGRAM代表UDP。
使用UDP发送数据

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
 
int port = 6789;

void main() {
  int socket_descriptor;
  int iter = 0;
  char buf[80];
  struct sockaddr_in address;

/*   Initialize socket address structure for Internet Protocols*/
  bzero(&address, sizeof(address)); /* empty data structure */
  address.sin_family = AF_INET;
  address.sin_addr.s_addr = inet_addr("127.0.0.1");
  address.sin_port = htons(port);

/*   Create a UDP socket*/
  socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0);

/*   Loop 20 times (a nice round number)  sending data.*/
  for (iter = 0; iter <= 20; iter++)
  {
    sprintf(buf,"data packet with ID %d\n", iter);
    sendto(socket_descriptor,
           buf, sizeof(buf),
           0, (struct sockaddr *)&address, sizeof(address));
  }

/*   Send a termination message*/
   sprintf(buf, "stop\n");
   sendto(socket_descriptor,
          buf, sizeof(buf),
          0, (struct sockaddr *)&address, sizeof(address));

   close(socket_descriptor);
   printf("Messages Sent, Terminating\n");
   exit (0);
}



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
 
int port = 6789;

void main() {
  int sin_len;
  char message[256];
  int socket_descriptor;
  struct sockaddr_in sin;
  printf("Waiting for data from sender\n");

/*   Initialize socket address structure for Internet Protocols*/
  bzero(&sin, sizeof(sin)); /* empty data structure */
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = htonl(INADDR_ANY);
  sin.sin_port = htons(port);
  sin_len = sizeof(sin);

/*
   Create a UDP socket
   and bind it to the port
*/
  socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0);
  bind(socket_descriptor, (struct sockaddr *)&sin, sizeof(sin));
/*
   Loop forever (or until a termination message is received)
   Receive data through the socket and process it.  The processing
   in this program is really simple -- printing.
*/
  while (1)
  {
    recvfrom(socket_descriptor, message, sizeof(message), 0,
             (struct sockaddr *)&sin, &sin_len);
    printf("Response from server: %s\n", message);
    if (strncmp(message, "stop", 4) == 0)
    {
       printf("Sender has told me to end the connection\n");
       break;
     }
  }
  close(socket_descriptor);
  exit (0);
}


--- sender.c    2000-09-22 20:51:26.000000000 +0800
+++ sender2.c    2000-09-22 20:51:26.000000000 +0800
@@ -5,45 +5,83 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netdb.h>
+#include <errno.h>
 
 int port = 6789;
 
 void main() {
   int socket_descriptor;
   int iter = 0;
+  ssize_t sendto_rc;
+  int close_rc;
   char buf[80];
   struct sockaddr_in address;
+  struct hostent *hostbyname;
 
 /*
+   Translate a host name to IP address
+*/
+  hostbyname = gethostbyname("127.0.0.1");
+  if (hostbyname == NULL)
+  {
+    perror ("gethostbyname failed");
+    exit (errno);
+  }
+/*
    Initialize socket address structure for Internet Protocols
+   The address comes from the datastructure returned by gethostbyname()
 */
   bzero(&address, sizeof(address)); /* empty data structure */
   address.sin_family = AF_INET;
-  address.sin_addr.s_addr = inet_addr("127.0.0.1");
+  memcpy(&address.sin_addr.s_addr, hostbyname->h_addr, sizeof(address.sin_addr.s_addr));
   address.sin_port = htons(port);
 /*
    Create a UDP socket
 */
   socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0);
+  if (socket_descriptor == -1)
+  {
+    perror ("socket call failed");
+    exit (errno);
+  }
 /*
    Loop 20 times (a nice round number)  sending data.
 */
   for (iter = 0; iter <= 20; iter++)
   {
     sprintf(buf,"data packet with ID %d\n", iter);
-    sendto(socket_descriptor,
+    sendto_rc = sendto(socket_descriptor,
            buf, sizeof(buf),
            0, (struct sockaddr *)&address, sizeof(address));
+    if (sendto_rc == -1)
+    {
+      perror ("sendto call failed");
+      exit (errno);
+    }
   }
 /*
    Send a termination message
 */
    sprintf(buf, "stop\n");
-   sendto(socket_descriptor,
+   sendto_rc = sendto(socket_descriptor,
           buf, sizeof(buf),
           0, (struct sockaddr *)&address, sizeof(address));
+   if (sendto_rc == -1)
+   {
+     perror ("sendto STOP call failed");
+     exit (errno);
+   }
+/*
+    Most people don't bother to check the return code
+    returned by the close function
+*/
+   close_rc = close(socket_descriptor);
+   if (close_rc == -1)
+   {
+     perror ("close call failed");
+     exit (errno);
+   }
-   close(socket_descriptor);
    printf("Messages Sent, Terminating\n");
    exit (0);
 }



--- receiver.c    2000-09-22 20:51:26.000000000 +0800
+++ receiver2.c    2000-09-22 20:51:26.000000000 +0800
@@ -5,6 +5,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netdb.h>
+#include <errno.h>
 
 int port = 6789;
 
@@ -13,6 +14,9 @@
   char message[256];
   int socket_descriptor;
   struct sockaddr_in sin;
+  int bind_rc, close_rc;
+  ssize_t recv_rc;
+
   printf("Waiting for data from sender\n");
 /*
    Initialize socket address structure for Internet Protocols
@@ -27,7 +31,18 @@
    and bind it to the port
 */
   socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0);
-  bind(socket_descriptor, (struct sockaddr *)&sin, sizeof(sin));
+  if (socket_descriptor == -1)
+  {
+    perror ("socket call failed");
+    exit (errno);
+  }
+
+  bind_rc = bind(socket_descriptor, (struct sockaddr *)&sin, sizeof(sin));
+  if (bind_rc == -1)
+  {
+    perror ("bind call failed");
+    exit (errno);
+  }
 /*
    Loop forever (or until a termination message is received)
    Receive data through the socket and process it.  The processing
@@ -35,16 +50,33 @@
 */
   while (1)
   {
-    recvfrom(socket_descriptor, message, sizeof(message), 0,
+    recv_rc = recvfrom(socket_descriptor, message, sizeof(message), 0,
              (struct sockaddr *)&sin, &sin_len);
+    if (recv_rc == -1)
+    {
+      perror ("recvfrom call failed");
+      exit (errno);
+    }
+
     printf("Response from server: %s\n", message);
+
     if (strncmp(message, "stop", 4) == 0)
     {
        printf("Sender has told me to end the connection\n");
        break;
      }
   }
-  close(socket_descriptor);
+/*
+    Most people don't bother to check the return code
+    returned by the close function
+*/
+   close_rc = close(socket_descriptor);
+   if (close_rc == -1)
+   {
+     perror ("close call failed");
+     exit (errno);
+   }
+   
   exit (0);
 }


--- sender2.c    2000-09-22 20:51:26.000000000 +0800
+++ sender3.c    2000-09-22 20:51:26.000000000 +0800
@@ -58,7 +58,10 @@
       perror ("sendto call failed");
       exit (errno);
     }
+    sleep(3); /* this is the only difference from sender2.c */
   }
+
+
 /*
    Send a termination message
 */


--- receiver2.c    2000-09-22 20:51:26.000000000 +0800
+++ receiver3.c    2000-09-22 20:51:26.000000000 +0800
@@ -6,6 +6,7 @@
 #include <arpa/inet.h>
 #include <netdb.h>
 #include <errno.h>
+#include <fcntl.h>
 
 int port = 6789;
 
@@ -16,6 +17,7 @@
   struct sockaddr_in sin;
   int bind_rc, close_rc;
   ssize_t recv_rc;
+  long save_file_flags;
 
   printf("Waiting for data from sender\n");
 /*
@@ -44,20 +46,41 @@
     exit (errno);
   }
 /*
+   set socket to non-blocking:
+*/
+  save_file_flags = fcntl(socket_descriptor, F_GETFL);
+  printf("file flags are %ld\n", save_file_flags);
+  save_file_flags |= O_NONBLOCK;
+  if (fcntl(socket_descriptor, F_SETFL, save_file_flags) == -1)
+  {
+    perror("trying to set input socket to non-blocking");
+    exit (errno);
+  }
+  printf("file flags are now %ld\n", save_file_flags);
+
+/*
    Loop forever (or until a termination message is received)
    Receive data through the socket and process it.  The processing
    in this program is really simple -- printing.
 */
   while (1)
   {
+    sleep (1); /* wait a moment... */
     recv_rc = recvfrom(socket_descriptor, message, sizeof(message), 0,
              (struct sockaddr *)&sin, &sin_len);
-    if (recv_rc == -1)
+    if (recv_rc == -1 && errno != EAGAIN)
     {
-      perror ("recvfrom call failed");
+      fprintf(stderr, "errno %d  ", errno); perror ("recvfrom call failed");
       exit (errno);
     }
+    else if (recv_rc == 0 || errno == EAGAIN)  /* no data */
+    {
+      printf("no data yet\n");
+      errno = 0;   /* clear the error */
+      continue;
+    }
 
+    errno = 0;   /* clear the error */
     printf("Response from server: %s\n", message);
 
     if (strncmp(message, "stop", 4) == 0)


PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
4
关闭 站长推荐上一条 /3 下一条