UDP is the abbreviation of User Datagram Protocol. Its Chinese name is the User Datagram Protocol, which is a connectionless and unreliable protocol. It also works in the line transmission layer. It simply realizes the data transmission function from one end of the host to the other end of the host. The data is sent through the IP layer and transmitted in the network. The order in which it reaches the target host is unpredictable. Therefore, the application needs to sort the data, which brings great inconvenience. In addition, the UDP protocol does not have traffic control, congestion control and other functions. On the sending end, UDP only encapsulates the data applied by the upper layer into UDP packets. In terms of error detection, it only performs a simple verification of the data, and then encapsulates it into the IP datagram and sends it out. On the receiving side, whether the data is received or not, it will not generate a reply to send to the source host. If the data is received, the receiving side will discard the UDP message and will not tell the source host. In this way, the transmitted data cannot guarantee its accuracy. If it wants its accuracy, the application needs to guarantee it.
Features of UDP protocol:
- Connection-free, unreliable;
- Provide data delivery services as much as possible, and discard them directly if there is any error, without feedback;
- For packets, the sender's UDP directly adds a UDP header when he gets the upper layer data, and then performs verification and submits it to the IP layer. After receiving the UDP message, the receiving party simply performs verification, and then directly removes the data and submits it to the upper layer application;
- The speed is fast, because the UDP protocol does not have the TCP protocol's handshake, confirmation, window, retransmission, congestion control and other mechanisms. UDP is a stateless transmission protocol, so it is very fast when transmitting data. Even when the network is congested, UDP will not reduce the transmitted data. Although UDP has many shortcomings, it also has its own advantages, so it also has many application occasions, because in today's network environment, the probability of errors in UDP protocol transmission is very small, and its real-time performance is very good. It is often used for real-time video transmission, such as live broadcast, network telephone, etc., because even if data loss occurs, resulting in video frames, this is not a big deal. Therefore, the UDP protocol will still be applied and has requirements for transmission speed, and can tolerate errors in data transmission.
In Linux, using socket network programming to implement udp communication process is as follows:
1. Initialize the socket
int sock_fd = socket(AF_INET , SOCK_DGRAM , 0); if(sock_fd < 0){ perror("failed to open socket"); return -1; }
2. Bind IP and port number
/** Bind IP and port number */ struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; // Local IPserver_addr.sin_port = htons(8888); // Specify the port numberint ret = bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)); if(ret < 0) { perror("failed to bind"); close(sock_fd); return -1; }
3. Set multicast reception (optional)
std::string multi_addr = "224.0.0.10"; struct ip_mreq mreq; mreq.imr_multiaddr.s_addr = inet_addr(multi_addr.c_str()); mreq.imr_interface.s_addr = INADDR_ANY; ret = setsockopt(sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreq)); if (0 >ret) { perror("set socket multicast error"); return false; }
4. Set the reception timeout (optional)
/** Set the reception timeout (optional) */ int mill_sec = 2000; // millisecondsstruct timeval time_out; time_out.tv_sec = mill_sec / 1000; time_out.tv_usec = (mill_sec- time_out.tv_sec * 1000) * 1000; ret = setsockopt(sock_fd, SOL_SOCKET,SO_RCVTIMEO,&time_out,sizeof (timeval)); if(ret < 0) { perror("udp setTimeOut error!"); }
5. Send data
unsigned char buf[1024]; std::string ip = "192.168.1.10"; int port = 1234; struct sockaddr_in client{}; memset(&client, 0, sizeof(client)); client.sin_addr.s_addr = inet_addr(ip.c_str()); client.sin_family = AF_INET; client.sin_port = htons(port); ret = sendto(sock_fd, buf, sizeof(buf), 0, reinterpret_cast<struct sockaddr *>(&client), sizeof(struct sockaddr)); if(ret < 0){ perror("udpServer send error!"); }else{ std::cout << "send success!" << std::endl; }
6. Receive data
unsigned char buffer[1024]; struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); while(true) { memset(buffer, 0, sizeof(buffer)); ssize_t len = recvfrom(sock_fd_, buffer, sizeof(buffer), 0, reinterpret_cast<struct sockaddr *>(&addr), &addr_len); if(len > 0) { std::cout << "received message len : " << len << std::endl; }else{ perror("recv error"); } }
7. Complete code
#include <sys/> #include <netinet/> #include <arpa/> #include <> #include <> #include <net/> #include <sys/> #include <> #include <> #include <iostream> #include <cstring> #include <thread> void recv_func(int sock_fd_) { unsigned char buffer[1024]; struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); while(true) { memset(buffer, 0, sizeof(buffer)); ssize_t len = recvfrom(sock_fd_, buffer, sizeof(buffer), 0, reinterpret_cast<struct sockaddr *>(&addr), &addr_len); if(len > 0) { std::cout << "received message len : " << len << std::endl; }else{ perror("recv error"); } } } int main(int agrc, char** argv) { int sock_fd = socket(AF_INET , SOCK_DGRAM , 0); if(sock_fd < 0){ perror("failed to open socket"); return -1; } /** Bind IP and port number */ struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; // Local IP server_addr.sin_port = htons(8888); // Specify the port number int ret = bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)); if(ret < 0) { perror("failed to bind"); close(sock_fd); return -1; } /** Set multicast reception (optional)*/ std::string multi_addr = "224.0.0.10"; struct ip_mreq mreq; mreq.imr_multiaddr.s_addr = inet_addr(multi_addr.c_str()); mreq.imr_interface.s_addr = INADDR_ANY; ret = setsockopt(sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreq)); if (0 >ret) { perror("set socket multicast error"); return false; } /** Set the reception timeout (optional) */ int mill_sec = 2000; // millisecondsstruct timeval time_out; time_out.tv_sec = mill_sec / 1000; time_out.tv_usec = (mill_sec- time_out.tv_sec * 1000) * 1000; ret = setsockopt(sock_fd, SOL_SOCKET,SO_RCVTIMEO,&time_out,sizeof (timeval)); if(ret < 0) { perror("udp setTimeOut error!"); } /** Turn on thread reception */ std::thread recv_t(recv_func, sock_fd); recv_t.detach(); /** main thread sends */ while (true) { unsigned char buf[1024]; std::string ip = "192.168.1.10"; int port = 1234; struct sockaddr_in client{}; memset(&client, 0, sizeof(client)); client.sin_addr.s_addr = inet_addr(ip.c_str()); client.sin_family = AF_INET; client.sin_port = htons(port); ret = sendto(sock_fd, buf, sizeof(buf), 0, reinterpret_cast<struct sockaddr *>(&client), sizeof(struct sockaddr)); if(ret < 0){ perror("udpServer send error!"); }else{ std::cout << "send success!" << std::endl; } usleep(50*1000); } }
8. Compile and run
#Compilationg++ udp_main.cpp -o main -lpthread # Run./main
The above is the detailed explanation of UDP network programming using C/C++ under Linux. For more information about C++ UDP network programming, please pay attention to my other related articles!