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; }