9.1 UDP协议

  TCP 协议是面向连接的基于流的,可靠的传输服务。UDP是无连接的,基于数据报的,不可靠的传输服务,UDP没有粘包,但是会产生丢包。

UDP模型如下:

可以看到,服务器端不用listen,也不用accept。而客户端,也不用connect。

总结UDP的特点如下:

1、无连接

2、基于消息的数据传输服务

3、不可靠

4、一般情况下UDP更加高效

扫描二维码关注公众号,回复: 2556751 查看本文章

注意点:

1、UDP报文可能会丢失重复

2、UDP报文可能会乱序

3、UDP缺乏流量控制

4、UDP缓冲区写满后,没有流量控制机制,会覆盖缓冲区

5、UDP协议数据报文截断

  如果接收到的数据报,大于缓冲区,报文可以被截断,后面的部分会丢失

6、recvfrom返回0,不代表连接关闭,因为UDP是无连接的

  sendto可以发送数据0包,只包含UDP头部

7、ICMP异步错误

  观察现象:

    关闭UDP服务端,如启动UDP客户端,从键盘接收数据后,再发送数据。UDP客户端会阻塞在sendto位置。

  说明:

    1、UDP发送报文时,只把数据copy到数据缓冲区,在服务器没有起来的情况下可以发送成功。

    2、所谓ICMP异步错误是指:发送报文的时候,没有错误,recvfrom接收报文的时候,会收到ICMP应答。

    3、异步错误,是无法返回未连接的套接字,UDP也可以调用connect。

8、UDP connect

  UDP调用connect,并没有三次握手,只是维护了一个状态信息(和对等方的)

  一旦调用connect,就可以使用send函数

简单的UDP回射服务器程序如下:

服务器:

 1 #include <netinet/in.h>
 2 #include <arpa/inet.h>
 3 #include <stdlib.h>
 4 #include <stdio.h>
 5 #include <errno.h>
 6 #include <string.h>
 7 
 8 
 9 void echo_srv(int sock)
10 {
11     char recvbuf[1024] = {0};
12     struct sockaddr_in peeraddr;
13     socklen_t peerlen;
14     int n;
15     
16     while(1)
17     {
18         peerlen = sizeof(peeraddr);
19         memset(recvbuf, 0, sizeof(recvbuf));
20         
21         n = recvfrom(sock, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&peeraddr,     
22                     &peerlen);
23         
24         if(n == -1)
25         {
26             if(errno == EINTR)
27                 continue;
28             else
29             {
30                 perror("recvfrom error");
31                 exit(0);
32             }
33         }
34         else if(n > 0)
35         {
36             int ret = 0;
37             fputs(recvbuf, stdout);
38             ret = sendto(sock, recvbuf, n, 0, (struct sockaddr*)&peeraddr, peerlen);
39         }
40     }
41     
42     close(sock);
43 }
44 
45 
46 int main()
47 {
48     int sock;
49     
50     sock = socket(AF_INET, SOCK_DGRAM, 0);
51     
52     if(sock < 0)
53     {
54         perror("socket error");
55         exit(0);
56     }
57     
58     struct sockaddr_in servaddr;
59     memset(&servaddr, 0, sizeof(servaddr));
60     
61     servaddr.sin_family = AF_INET;
62     servaddr.sin_port = htons(8002);
63     
64     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
65     
66     if(bind(sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
67     {
68         perror("bind error");
69         exit(0);
70     }
71     
72     echo_srv(sock);
73     return 0;
74 }

客户端:

 1 #include <netinet/in.h>
 2 #include <arpa/inet.h>
 3 #include <stdlib.h>
 4 #include <stdio.h>
 5 #include <errno.h>
 6 #include <string.h>
 7 
 8 
 9 
10 void echo_cli(int sock)
11 {
12     struct sockaddr_in servaddr;
13     memset(&servaddr, 0, sizeof(servaddr));
14     
15     servaddr.sin_family = AF_INET;
16     servaddr.sin_port = htons(8002);
17     
18     servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
19     
20     int ret = 0;
21     char sendbuf[1024] = {0};
22     char recvbuf[1024] = {0};
23     
24     while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
25     {
26         sendto(sock, sendbuf, strlen(sendbuf), 0, (struct sockaddr*)&servaddr, 
27                 sizeof(servaddr)
28                 );
29         ret = recvfrom(sock, recvbuf, sizeof(recvbuf), 0, NULL, NULL);
30         
31         if(ret == -1)
32         {
33             if(errno == EINTR)
34                 continue;
35             else
36             {
37                 perror("recvfrom error");
38                 exit(0);
39             }
40         }
41         
42         fputs(recvbuf, stdout);
43         memset(sendbuf, 0, sizeof(sendbuf));
44         memset(recvbuf, 0, sizeof(recvbuf));
45         
46     }
47     
48     close(sock);
49 }
50 
51 
52 int main()
53 {
54     int sock;
55     sock = socket(AF_INET, SOCK_DGRAM, 0);
56     
57     if(sock < 0)
58     {
59         perror("socket error");
60         exit(0);
61     }
62     
63     echo_cli(sock);
64 
65     return 0;
66 }

运行结果如下:

用netstat - na看网络状态如下:

UDP和TCP不一样,不存在11种状态,因此,我们只能看到一个服务器端的套接字,服务器端执行了bind,所以会显示这个套接字。

猜你喜欢

转载自www.cnblogs.com/wanmeishenghuo/p/9420893.html
9.1