Network program based on UDP protocol

The following figure is the general flow of the client/server program based on the UDP protocol:

Figure 1.1 UDP protocol communication process

UDP通讯流程

UDP sockets are connectionless, unreliable datagram protocols;

Since he is not reliable why use it? One: when the application uses broadcast or multicast, only the UDP protocol can be used; the second: because it is connectionless, it is fast. Because UDP sockets are connectionless, if one party's datagram is lost, the other party will wait indefinitely. The solution is to set a timeout.

When establishing a UDP socket, the second parameter of the socket function should be SOCK_DGRAM, indicating that a UDP socket is established; since UDP is connectionless, the server does not need the listen or accept function.

Using UDP socket programming can realize connectionless communication based on TCP/IP protocol. It is divided into two parts: server side and client side. The main implementation process is shown in Figure 1.1.

The following describes the detailed functions and processes of UDP network programming:

 1. Socket function: In order to perform network input and output, the first thing a process must do is to call the socket function to obtain a file descriptor.

-------------------------------------------------- ---------------
 #include <sys/socket.h>
 int socket(int family,int type,int protocol);    
      return: non-negative descriptor ---success-1- --failure
 ----------------------------------------------- ------------------

The first parameter specifies the protocol cluster. Currently, 5 protocol clusters are supported. The most commonly used ones are AF_INET (IPv4 protocol) and AF_INET6 (IPv6 protocol). The second parameter specifies the socket type, and there are three types available: SOCK_STREAM (word Throttling socket), SOCK_DGRAM (datagram socket) and SOCK_RAW (raw socket); if the socket type is not a raw socket, then the third parameter is 0.

2. The bind function: assigns a local IP and protocol port to the socket. For Internet Protocol, the protocol address is a combination of a 32-bit IPv4 address or a 128-bit IPv6 address and a 16-bit TCP or UDP port number; if the specified port is 0, When calling bind, the kernel will choose an ephemeral port. If a wildcard IP address is specified, the kernel will not choose a local IP address until the connection is established.

-------------------------------------------------- -----------------
#include <sys/socket.h>  
 int bind(int sockfd, const struct sockaddr * server, socklen_t addrlen);
 return: 0---success- 1---Failure 
 -------------------------------------------- ----------------------

  The first parameter is the socket descriptor returned by the socket function; the second and third parameters are a pointer to a protocol-specific address structure and the length of the address structure, respectively.

3. The recvfrom function: UDP uses the recvfrom() function to receive data, which is similar to the standard read(), but specifies the destination address in the recvfrom() function.

-------------------------------------------------------------------
#include <sys/types.h>  
#include <sys/socket.h>  
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr * from, size_t *addrlen);
 返回接收到数据的长度---成功   -1---失败 
 -------------------------------------------------------------------

  前三个参数等同于函数read()的前三个参数,flags参数是传输控制标志。最后两个参数类似于accept的最后两个参数。

4、sendto函数:UDP使用sendto()函数发送数据,他类似于标准的write(),但是在sendto()函数中要指明目的地址。

-------------------------------------------------------------------
#include <sys/types.h>  
#include <sys/socket.h>  
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr * to, int addrlen);
 返回发送数据的长度---成功   -1---失败 
 -------------------------------------------------------------------

  前三个参数等同于函数read()的前三个参数,flags参数是传输控制标志。参数to指明数据将发往的协议地址,他的大小由addrlen参数来指定。

server.c程序源码:

  #include <stdio.h>                                                                                                                 
  #include <sys/socket.h>
  #include <stdlib.h>
  #include <netinet/in.h>
  #include <unistd.h>
  #include <sys/types.h>
  #include <string.h>
 
  #define _MAXLINE_ 80
  #define _SERV_PORT_  8000
  
  int main()
  {
      struct sockaddr_in server_addr,client_addr;
      socklen_t cliaddr_len;
      int sockfd;
      char buf[_MAXLINE_];
      char str[INET_ADDRSTRLEN];
      int i, n;
  
      sockfd = socket(AF_INET, SOCK_DGRAM, 0);
      if(sockfd < 0){
          printf("create socket error!...\n");
          return -1;
      }
  
      bzero(&server_addr,sizeof(server_addr));
      server_addr.sin_family = AF_INET;
      server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
      server_addr.sin_port = htons(_SERV_PORT_);
  
      if(bind(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr)) < 0){
          printf("bind error!...");
          close(sockfd);
          return 1;
      }
  
      printf("Accepting connections ...\n");
      while(1){
          cliaddr_len = sizeof(client_addr);
          //n = recvfrom(sockfd, buf, _MAXLINE_, 0,(struct sockaddr *)&client_addr, &cliaddr_len);
          n = recvfrom(sockfd, buf, _MAXLINE_, 0,(struct sockaddr *)&client_addr, &cliaddr_len);
          if(n == -1){
              printf("recvfrom error...\n");
              exit(1);
          }
          printf("received from %s at PORT %d\n",inet_ntop(AF_INET, &client_addr.sin_addr, 
                  str,sizeof(str)),ntohs(client_addr.sin_port));
  
          for(i = 0; i < n; i++){
              buf[i] = toupper(buf[i]);
          }
          n = sendto(sockfd, buf, n, 0, (struct sockaddr *)&client_addr, sizeof(client_addr));
          if(n == -1){
              printf("sendto error...\n");
          }
      }
      return 0;
  }

UDP客户端程序设计

client.c程序源码:

   #include <stdio.h>                                                                                                                                       
   #include <string.h>
   #include <unistd.h>
   #include <netinet/in.h>
   
   #define _MAXLINE_ 80
   #define _SERV_PORT_  8000
   
   int main(int argc, int* argv[])
  {
      struct sockaddr_in servaddr;
      int sockfd, n;
      char buf[_MAXLINE_];
      char str[INET_ADDRSTRLEN];
      socklen_t servaddr_len;
  
      sockfd = socket(AF_INET, SOCK_DGRAM, 0);

      bzero(&servaddr, sizeof(servaddr));
      servaddr.sin_family = AF_INET;
      inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
      servaddr.sin_port = htons(_SERV_PORT_);
  
      while(fgets(buf, _MAXLINE_, stdin)!= NULL){
          n = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)\
                  &servaddr, sizeof(servaddr));
          if(n == -1){
              printf("sendto error\n");
          }
          n = recvfrom(sockfd, buf, _MAXLINE_, 0, NULL, 0);
          if(n == -1){
              printf("recvfrom error\n");
          }
          write(STDOUT_FILENO, buf, n);
      }
  
      close(sockfd);
      return 0;
  }


Running the display, the client sends lowercase letters, the server converts the uppercase and lowercase letters after receiving them, and sends them back to the client. The results are as follows:

capture.PNG


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324653404&siteId=291194637