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發送:

yan@ubuntu:~/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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章