UDP服务器
传输层主要应用的协议模型有两种,一种是TCP协议,另外一种则是UDP协议。TCP协议在网络通信中占主导地位,绝大多数的网络通信借助TCP协议完成数据传输。但UDP也是网络通信中不可或缺的重要通信手段。
相较于TCP而言,UDP通信的形式更像是发短信。不需要在数据传输之前建立、维护连接。只专心获取数据就好。省去了三次握手的过程,通信速度可以大大提高,但与之伴随的通信的稳定性和正确率便得不到保证。因此,我们称UDP为“无连接的不可靠报文传递”。
那么与我们熟知的TCP相比,UDP有哪些优点和不足呢?由于无需创建连接,所以UDP开销较小,数据传输速度快,实时性较强。多用于对实时性要求较高的通信场合,如视频会议、电话会议等。但随之也伴随着数据传输不可靠,传输数据的正确率、传输顺序和流量都得不到控制和保证。所以,通常情况下,使用UDP协议进行数据传输,为保证数据的正确性,我们需要在应用层添加辅助校验协议来弥补UDP的不足,以达到数据可靠传输的目的。
与TCP类似的,UDP也有可能出现缓冲区被填满后,再接收数据时丢包的现象。由于它没有TCP滑动窗口的机制,通常采用如下两种方法解决:
- 服务器应用层设计流量控制,控制发送数据速度。
- 借助setsockopt函数改变接收缓冲区大小。如:
#include <sys/socket.h>
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
int n = 220x1024
setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n));
C/S模型-UDP
server端
1 #include<stdio.h>
2 #include<netinet/in.h>
3 #include<stdlib.h>
4 #include<sys/types.h>
5 #include<sys/socket.h>
6 #include<assert.h>
7 #include<arpa/inet.h>
8 #include<string.h>
9 #include<ctype.h>
10 #define BUFF_SIZE 64
11 int main(int argc, char*argv[])
12 {
13 if(argc < 3)
14 {
15 printf("argc less 3\n");
16 exit(1);
17 }
18 const char * ip=argv[1];
19 int port=atoi(argv[2]);
20
21 struct sockaddr_in saddr,caddr;
22
23 int sfd = socket(AF_INET,SOCK_DGRAM,0);
24
25 saddr.sin_family=AF_INET;
26 saddr.sin_port=htons(port);
27 inet_pton(AF_INET,ip,&saddr.sin_addr.s_addr);
28 int ret = bind(sfd,(struct sockaddr*)&saddr,sizeof(saddr));
29 assert(ret != -1);
30
31 char buff[BUFF_SIZE],str[BUFF_SIZE];
32 int i;
33 memset(buff,'\0',BUFF_SIZE);
34 while(1)
35 {
36 socklen_t len = sizeof(caddr);
37 ret = recvfrom(sfd,buff,BUFF_SIZE-1,0,(struct sockaddr*)&caddr,&len);
38 assert(ret!=-1);
39 printf("client ip = %s port=%d\n",inet_ntop(AF_INET,&caddr.sin_addr.s_addr,str,
40 sizeof(str)),ntohs(caddr.sin_port));
41
42 for(i=0;i<BUFF_SIZE;++i)
43 buff[i]=toupper(buff[i]);
44
45 ret = sendto(sfd,buff,ret,0,(struct sockaddr*)&caddr,len);
46 assert(ret !=-1);
47 printf("%s\n",buff);
48 }
49
50 return 0;
51 }
client端
1 #include<stdio.h>
2 #include<netinet/in.h>
3 #include<stdlib.h>
4 #include<sys/types.h>
5 #include<sys/socket.h>
6 #include<assert.h>
7 #include<arpa/inet.h>
8 #include<string.h>
9 #include<ctype.h>
10 #define BUFF_SIZE 64
11 int main(int argc, char*argv[])
12 {
13 if(argc < 3)
14 {
15 printf("argc less 3\n");
16 exit(1);
17 }
18 const char * ip=argv[1];
19 int port=atoi(argv[2]);
20
21 struct sockaddr_in saddr;
22 saddr.sin_family=AF_INET;
23 saddr.sin_port=htons(port);
24 inet_pton(AF_INET,ip,&saddr.sin_addr.s_addr);
25
26 int cfd = socket(AF_INET,SOCK_DGRAM,0);
27
28 char buff[BUFF_SIZE],str[BUFF_SIZE];
29 int i;
30 memset(buff,'\0',BUFF_SIZE);
31 while(fgets(buff,BUFF_SIZE-1,stdin)!=NULL)
32 {
33
34 socklen_t len = sizeof(saddr);
35 int ret = sendto(cfd,buff,sizeof(buff),0,(struct sockaddr*)&saddr,len);
36 assert(ret !=-1);
37 printf("已经发送:%s\n",buff);
38 ret = recvfrom(cfd,buff,BUFF_SIZE-1,0,NULL,NULL);
39 assert(ret!=-1);
40 printf("%s\n",buff);
41
42 }
43
44 return 0;
45 }
结果分析
client1发送:
yan@ubuntu:~/net/11UDP$ ./client 127.0.0.1 8888
hello
已经发送:helloHELLO
client2发送:
hellohello
已经发送:hellohello
HELLOHELLO
server接收:
client ip = 127.0.0.1 port=59024
HELLOclient ip = 127.0.0.1 port=34412
HELLOHELLO