UDP服务器与客户端的实现

标签: 网络

UDP服务器

传输层主要应用的协议模型有两种,一种是TCP协议,另外一种则是UDP协议。TCP协议在网络通信中占主导地位,绝大多数的网络通信借助TCP协议完成数据传输。但UDP也是网络通信中不可或缺的重要通信手段。
相较于TCP而言,UDP通信的形式更像是发短信。不需要在数据传输之前建立、维护连接。只专心获取数据就好。省去了三次握手的过程,通信速度可以大大提高,但与之伴随的通信的稳定性和正确率便得不到保证。因此,我们称UDP为“无连接的不可靠报文传递”。
那么与我们熟知的TCP相比,UDP有哪些优点和不足呢?由于无需创建连接,所以UDP开销较小,数据传输速度快,实时性较强。多用于对实时性要求较高的通信场合,如视频会议、电话会议等。但随之也伴随着数据传输不可靠,传输数据的正确率、传输顺序和流量都得不到控制和保证。所以,通常情况下,使用UDP协议进行数据传输,为保证数据的正确性,我们需要在应用层添加辅助校验协议来弥补UDP的不足,以达到数据可靠传输的目的。
与TCP类似的,UDP也有可能出现缓冲区被填满后,再接收数据时丢包的现象。由于它没有TCP滑动窗口的机制,通常采用如下两种方法解决:

  1. 服务器应用层设计流量控制,控制发送数据速度。
  2. 借助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发送:

[email protected]:~/net/11UDP$ ./client 127.0.0.1 8888
hello
已经发送:hello

HELLO

client2发送:

hellohello

已经发送:hellohello

HELLOHELLO

server接收:

client ip = 127.0.0.1 port=59024
HELLO

client ip = 127.0.0.1 port=34412
HELLOHELLO

版权声明:本文为YanWenCheng_原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/YanWenCheng_/article/details/104351761