UDP协议简单的CS模型实现

UDP简单介绍

  传输层主要应用的协议模型有两种,一种是TCP协议,另外一种则是UDP协议。TCP协议在网络通信中占主导地位,绝大多数的网络通信借助TCP协议完成数据传输。但UDP也是网络通信中不可或缺的重要通信手段。

  相较于TCP而言,UDP通信的形式更像是发短信。不需要在数据传输之前建立、维护连接。只专心获取数据就好。省去了三次握手的过程,通信速度可以大大提高,但与之伴随的通信的稳定性和正确率便得不到保证。因此,我们称UDP为“无连接的不可靠报文传递”。

  那么与我们熟知的TCP相比,UDP有哪些优点和不足呢?由于无需创建连接,所以UDP开销较小,数据传输速度快,实时性较强。多用于对实时性要求较高的通信场合,如视频会议、电话会议等。但随之也伴随着数据传输不可靠,传输数据的正确率、传输顺序和流量都得不到控制和保证。所以,通常情况下,使用UDP协议进行数据传输,为保证数据的正确性,我们需要在应用层添加辅助校验协议来弥补UDP的不足,以达到数据可靠传输的目的。

  如下图所示,简单的UDP的CS模型通信过程,由于UDP不需要维护连接,程序逻辑简单了很多,但是UDP协议是不可靠的,保证通讯可靠性的机制需要在应用层实现。

  

代码实现:

server.c

 1 #include<stdio.h>
 2 #include<unistd.h>
 3 #include<stdlib.h>
 4 #include<sys/socket.h>
 5 #include<string.h>
 6 #include<arpa/inet.h>
 7 #include<ctype.h>
 8 
 9 #define SERVER_PORT 8000
10 
11 int main(int agrc,char* argv[])
12 {
13     int sockfd;
14     struct sockaddr_in servaddr,clieaddr;
15     socklen_t clieaddr_len;
16     char buf[BUFSIZ];
17     char str[INET_ADDRSTRLEN];
18     int i,n;
19 
20     sockfd=socket(AF_INET,SOCK_DGRAM,0);
21     bzero(&servaddr,sizeof(servaddr));
22     servaddr.sin_family=AF_INET;
23     servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
24     servaddr.sin_port=htons(SERVER_PORT);
25 
26     bind(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
27 
28     printf("Acceptint Connections ...\n");
29     while(1)
30     {
31         clieaddr_len=sizeof(clieaddr);
32         n=recvfrom(sockfd,buf,BUFSIZ,0,(struct sockaddr*)&clieaddr,&clieaddr_len);
33         if(n==-1)
34         {
35             perror("recvfrom error");
36         }
37         printf("received from %s at PORT %d\n",inet_ntop(AF_INET,&clieaddr.sin_addr,str,sizeof(str)),ntohs(clieaddr.sin_port));
38         for(i=0;i<n;i++)
39         {
40             buf[i]=toupper(buf[i]);
41         }
42         n=sendto(sockfd,buf,n,0,(struct sockaddr*)&clieaddr,sizeof(clieaddr));
43         if(n==-1)
44         {
45             perror("sendto error");
46         }
47     }
48     close(sockfd);
49 
50     return 0;
51 }

client.c

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<unistd.h>
 4 #include<arpa/inet.h>
 5 #include<ctype.h>
 6 
 7 #define SERVER_PORT 8000
 8 
 9 int main(int argc,char* argv[])
10 {
11     struct sockaddr_in servaddr;
12     int sockfd,n;
13     char buf[BUFSIZ];
14 
15     sockfd = socket(AF_INET,SOCK_DGRAM,0);
16 
17     bzero(&servaddr,sizeof(servaddr));
18     servaddr.sin_family = AF_INET;
19     inet_pton(AF_INET,"0.0.0.0",&servaddr.sin_addr);
20     servaddr.sin_port = htons(SERVER_PORT);
21 
22     bind(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
23 
24     while(fgets(buf,BUFSIZ,stdin)!= NULL)
25     {
26         n = sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&servaddr,sizeof(servaddr));
27         if(n == -1)
28         {
29             perror("sendto error");
30             //printf("*********************\n");
31         }
32         n = recvfrom(sockfd,buf,BUFSIZ,0,NULL,0);//NULL:不关心对端信息
33         if(n == -1)
34         {
35             perror("recvfrom error");
36         }
37         write(STDOUT_FILENO,buf,n);
38     }
39     close(sockfd);
40     return 0;
41 }

测试结果:

1.首先启动服务端程序

2.再启动客户端程序

3.在客户端输入一个字符串回车

4.在客户端可以看到服务端转换的大写字符串回写到客户端屏幕

5.服务端可以看到客户端连接的信息(IP和端口号)

努力不一定有结果,有结果不一定是努力
原文地址:https://www.cnblogs.com/liunianshiwei/p/6050396.html