Socket programming Practice under Linux (10) basic UDP programming details

Source: Internet
Author: User
Tags socket error htons

In my two blog posts, a simple introduction and implementation of UDP (TCP)-based Windows (Unix process basically consistent) under the server and client programs, this article continues to explore some of the details of UDP programming.

is a simple UDP client/server model:

I also implemented a simple UDP back-up server/client here:

/** Practice: Implement a UDP-based echo Echo server/client**///server-end code void echoserver (int sockfd);      int main () {int SOCKFD = socket (af_inet, SOCK_DGRAM, 0);        if (SOCKFD = =-1) err_exit ("Socket error");      struct sockaddr_in servaddr;      servaddr.sin_family = af_inet;      SERVADDR.SIN_ADDR.S_ADDR = htonl (Inaddr_any);      Servaddr.sin_port = htons (8001);        if (Bind (SOCKFD, (const struct sockaddr *) &servaddr, sizeof (servaddr)) = =-1) err_exit ("Bind error");  Echoserver (SOCKFD);      } void Echoserver (int sockfd) {char buf[bufsiz];      ssize_t recvbytes = 0;      struct sockaddr_in clientaddr;      Socklen_t Addrlen;          while (true) {memset (buf, 0, sizeof (BUF));          Addrlen = sizeof (CLIENTADDR);          memset (&clientaddr, 0, Addrlen); Recvbytes = Recvfrom (sockfd, buf, sizeof (BUF), 0, (struct sockaddr *) &clientaddr, &a          Ddrlen);    If recvbytes=0, does not mean that the peer connection is off because UDP is not connected      if (Recvbytes < 0) {if (errno = = eintr) continue;          else Err_exit ("Recvfrom error");          } cout << buf;              if (SendTo (SOCKFD, buf, Recvbytes, 0, (const struct sockaddr *) &clientaddr, addrlen) = =-1)      Err_exit ("SendTo error");   }  }
/**client-side code **/void echoclient (int sockfd);      int main () {int SOCKFD = socket (af_inet, SOCK_DGRAM, 0);      if (SOCKFD = =-1) err_exit ("Socket error");      Echoclient (SOCKFD);  cout << "Client exiting ..." << Endl;      } void echoclient (int sockfd) {struct sockaddr_in servaddr;      servaddr.sin_family = af_inet;      SERVADDR.SIN_ADDR.S_ADDR = inet_addr ("");      Servaddr.sin_port = htons (8001);      Char Buf[bufsiz] = {0};                     while (Fgets (buf, sizeof (BUF), stdin)! = NULL) {if (SendTo (SOCKFD, buf, strlen (BUF), 0,          (const struct SOCKADDR *) &servaddr, sizeof (servaddr)) = =-1) err_exit ("SendTo error");          memset (buf, 0, sizeof (BUF));          int recvbytes = Recvfrom (sockfd, buf, sizeof (BUF), 0, NULL, NULL);              if (recvbytes = =-1) {if (errno = = eintr) continue;          else Err_exit ("Recvfrom error");    }      cout << buf;      memset (buf, 0, sizeof (BUF));   }  }
UDP protocol is not the same as TCP is the same as a one-off communication, UDP can achieve broadcast communication, and because it is not connected,you can proactively send data as long as you know the peer address (IP and port). You can also communicate by shutting down the server and then connecting.

Considerations and details for UDP programming:

1.UDP does not have a sticky packet problem because it is not a stream-based transmission (message-based).

2.UDP message may be lost, duplicated, disorderly question. processing loss can take the time-out processing mechanism, timer timeout retransmission; Repetition, chaos can be resolved by maintaining the serial number between the datagrams.

3.UDP lacks traffic control : When the buffer is full, the buffer is overwritten because UDP has no traffic control mechanism. can be solved by simulating the sliding window protocol of TCP.

4. Datagram truncation: if the UDP datagram sent to the end is larger than the local receive buffer, the message may be truncated and the latter part will be lost (rather than being able to receive the next one as we imagined), and if we use SendTo to send "ABCD" 4 bytes, The accepted recv function takes one character at a time in a circular manner, but the result is that we can only accept a. The rest does not exist in the buffer, which can also be judged by: the loss of the datagram Socket Interface (UDP) is not a streaming socket interface (TCP).

5.recvfrom returns 0: does not mean that the connection is closed because UDP is not connected.

6.ICMP Async error (emphasis)

This error occurs when the server or client is opened only by one side, and this is an ICMP response errorgenerated by the TCP/IP stack, which isrecv . because it is not notified at all, it is called asynchronous and is not returned to the disconnected socket.

workaround :UDP calls connect

connect after the send recv icmp error. udp connect There is no three handshake, just to maintain a message, a state, and for this socket can not be sent to other addresses. connect sendto and can also be used send write

Further clarification:

1) When UDP sends the paper, only copy the data to the send buffer . If the server is not up, it can be sent successfully .

2) The so-called ICMP asynchronous error refers to: When the message is sent, there is no error, when receiving the message recvfrom, the return to the ICMP reply.

3) Asynchronous error, unable to return an unbound socket, so if the above example we call connect, it is possible to receive the asynchronous ICMP packet;

Further analysis of 1):

If the server does not start, the client sendto send a data, what will be the result?

The conclusion is that SendTo successfully returns, and if the client also calls Recvfrom at the same time, it will always be blocked in the Recvfrom function (which can certainly be timed out), and also through tcpdump, the server returns an ICMP Port unreachable error message, However, this message is not returned to the user process through the sendto and Recvfrom functions, in other words, the user does not know that the server has returned an ICMP error. What to do, the connet function of UDP can handle these.

For a UDP socket call to connect, called a connected UDP socket, it differs from the non-connected UDP socket as follows:

    1. Use write or send without using sendto, because the destination IP address is already specified in connect;
    2. Do not apply recvfrom, and use Read or recv or recvmsg, note that if the source address is not the destination address of the connect connection, it will not be fed back to the socket, which is precisely the kernel to help us complete the verification received response;
    3. Asynchronous errors caused by connected UDP sockets are returned to the process they are in, which solves the problem well;
    4. Call Connect, determine the destination IP and port, and also through the destination address, find the routing table, determine the local address, connect after the call getsockname can be obtained.

Summary: The UDP client or service process only calls connect when it uses its own UDP sockets to communicate with the identified unique peer, and of course, the UDP clients generally use connect a little more. At the same time, if you use Connect, its performance will also be improved, because for sendto, it sends the data before and after the need to connect sockets, disconnect sockets, if connect, these two steps will be saved.

Determination of the 7.UDP outgoing interface:

Assuming that the client has multiple IP addresses, the parameters of the remote address provided by the CONNECT/SENDTO function, the system chooses an appropriate exit, such as the server's IP is, and the client now has the IP And then will automatically choose this IP out. (Specific algorithm first skip ...) )

Finally, an example of datagram truncation is attached:

int main () {int SOCKFD = socket (af_inet, SOCK_DGRAM, 0);        if (SOCKFD = =-1) err_exit ("Socket error");      struct sockaddr_in servaddr;      servaddr.sin_family = af_inet;      SERVADDR.SIN_ADDR.S_ADDR = htonl (Inaddr_any);      Servaddr.sin_port = htons (8001);      if (Bind (SOCKFD, (const struct sockaddr *) &servaddr, sizeof (servaddr)) = =-1) err_exit ("Bind error");  Send yourself data if (SendTo (SOCKFD, "ABCDE", 5, 0, (const struct sockaddr *) &servaddr, sizeof (SERVADDR))        = =-1) err_exit ("SendTo error");          for (int i = 0; i < 5; ++i) {char ch;          int recvbytes = Recvfrom (SOCKFD, &ch, 1, msg_dontwait, NULL, NULL);              if (recvbytes = =-1) {if (errno = = eintr) continue;          else if (errno = = Eagain) err_exit ("Recvfrom error"); } else cout << "char =" << ch << ", recvbytes = "<< recvbytes << Endl;   }  }

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Socket programming Practice under Linux (10) basic UDP programming details

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.