Linux UDP coding interface and code implementation

1. Encoding interface of UDP

1.1 programming flow of UDP

1.2 binding address information

  int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

  sockfd: the socket descriptor returned by the socked function, which binds the created socket to the network card and port
  addr: address information structure

  sa_family_t sa_family;// The address domain information takes up 2 bytes. The address information determines what network protocol is currently used (AF_INET, AF_INET6, AF_UNIX)
  char sa_data[14];// In essence, any network program will not directly fill the 14 byte character array and define the second parameter, which takes a total of 14 bytes.
  addrlen: length of address information structure

ipv4:
  struct sockaddr_in{...}
  path: VIM / usr / include / netinet / in h

  address domain information, AF_INET,AF_INET6, AF_UNIX: 2 bytes
  port information: 2 bytes
  ip address of ipv4 version: 4 bytes

Common data structure:

Data structure of ipv4:

   the network protocol stack judges which data structure is passed in through the address domain information. After judging, it will know how to parse the following bytes.

1.3 sending interface

  ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)

  sockfd: socket descriptor
  buf: data to be sent
   len: length of data to be sent
  flags:
   0: blocking transmission
  dest_addr: address information structure (ip,port) of the target host
   addrlen: the length of the address information structure of the target host
Return value:
╭ number of bytes returned successfully
  failed: - 1

Question: why does the client not recommend binding address information?
   in essence, I don't want the client program port to be written dead, because a port can only be bound by one process. If the client binds to one port when it starts, the binding will fail when other clients bind. If the client does not actively bind the port and the udp client calls sendto, It will automatically bind an idle port, which is an idle port allocated by the operating system.

1.4 receiving interface

  ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

  sockfd: socket descriptor
  buf: receive data into buf
  len: maximum receiving capacity of buf
  flags:
     0 blocking reception
  src_addr: the address information structure of the host of this data source
   addrlen: input / output type parameter
  input: the length of the peer address information structure prepared before receiving
   output: the length of the address information actually received
Return value:
  number of bytes received
  -1

Command: netstat -anp | grep [port]
Function: view port information

  close(int sockfd)

1.5 conversion function between host byte order and network byte order

Convert host byte order to network byte order

uint32_t htonl(uint32_t hostlong);//host to network long
uint16_t htons(uint16_t hostshort);//host to network short

Convert network byte order to host byte order

uint32_t ntohl(uint32_t netlong);//network to host long
uint16_t ntohs(uint16_t netshort);//network to host short

Convert the dotted decimal ip address of the string to uint32_t

in_addr_t inet_addr(const char *cp);

Set uint32_t convert from host byte order to network byte order

char *inet_ntoa(struct in_addr in);

1.6 code

client

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>

int main()
{
    //int socket(int domain, int type, int protocol);
    int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if(sockfd < 0)
    {
        perror("sockfd failed");
        return 0;
    }

    while(1)
    {
        sleep(1);
        char buf[1024] = "i am client";

        //General structure
        struct sockaddr_in  dest_addr;
        dest_addr.sin_family = AF_INET;
        dest_addr.sin_port = htons(18989);
        dest_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

        //ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
        //                      const struct sockaddr *dest_addr, socklen_t addrlen);
        int sendto_ret = sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr));

        if(sendto_ret < 0)
        {
            perror("sendto failed");
            return 0;
        }

        memset(buf, '\0', sizeof(buf));
        //ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
        //                        struct sockaddr *src_addr, socklen_t *addrlen);
        ssize_t recv_size = recvfrom(sockfd, buf, sizeof(buf) - 1, 0, NULL, NULL);
        if(recv_size < 0)
        {
            perror("recvfrom failed");
            continue;
        }
        printf("server say: %s\n", buf);
    }
    return 0;
}

server

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
    // int socket(int domain, int type, int protocol);
    // What protocol does the current address domain of damain use
    //        AF_INET:ipv4
    //        AF_INET6:ipv6
    //        AF_UNIX: local domain socket
    // Type create socket type
    //        SOCK_DGRAM user datagram socket UDP protocol
    //        SOCK_STREAM streaming socket TCP protocol
    // What type of socket protocol does protocol use
    //        0: indicates the default protocol of socket type
    //        IPPROTO_UDP:17
    //        IPPROTO_TCP:6
    int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if(sockfd < 0)
    {
        perror("socket failed");
        return 0;
    }

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    //Convert host byte order to network byte order
    addr.sin_port = htons(18989);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    int bind_ret = bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
    if(bind_ret < 0)
    {
        perror("bind failed");
        return 0;
    }

    while(1)
    {
        //receive
    
        char buf[1024] = {0};
    
        sockaddr_in addr_recvfrom;
        socklen_t addr_recvfromlen = sizeof(addr_recvfrom);
        //ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
        //                        struct sockaddr *src_addr, socklen_t *addrlen);
        ssize_t recvfrom_ret = recvfrom(sockfd, buf, sizeof(buf) - 1, 0, (struct sockaddr*)&addr_recvfrom, &addr_recvfromlen);
        if(recvfrom_ret < 0)
        {
            continue;
        }
        printf("i am server, i recv %s from %s:%d\n", buf, inet_ntoa(addr_recvfrom.sin_addr), ntohs(addr_recvfrom.sin_port));

        //send out
        memset(buf, '\0', sizeof(buf));
        sprintf(buf, "client: %s : %d, i am server", inet_ntoa(addr_recvfrom.sin_addr), ntohs(addr_recvfrom.sin_port));

        sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&addr_recvfrom, sizeof(addr_recvfrom));
    }
    return 0;
}

Keywords: Linux

Added by revdev on Tue, 08 Feb 2022 06:11:01 +0200