linux網路程式設計--UDP協議
阿新 • • 發佈:2019-02-06
特點
UDP 即使用者資料報協議,它是一種無連線協議,因此不需要像 TCP 那樣通過三次握手來建立一個連線。同時,一個 UDP 應用可同時作為應用的客戶或伺服器方。由於 UDP 協議並不需要建立一個明確的連線,因此建立 UDP 應用要比建立 TCP 應用簡單得多。
UDP和TCP協議的比較
(1)對資料可靠性的要求
對資料要求高可靠性的應用需選擇 TCP 協議,如驗證、密碼欄位的傳送都是不允許出錯的,而對資料的可靠性要求不那麼高的應用可選擇 UDP 傳送。
(2)應用的實時性
由於 TCP 協議在傳送過程中要進行三次握手、重傳確認等手段來保證資料傳輸的可靠性。使用 TCP 協議會有較大的時延,因此不適合對實時性要求較高的應用,如 VOIP、視訊監控等。相反,UDP 協議則在這些應用中能發揮很好的作用。
(3)網路的可靠性
由於 TCP 協議的提出主要是解決網路的可靠性問題,它通過各種機制來減少錯誤發生的概率。因此,在網路狀況不是很好的情況下需選用 TCP 協議(如在廣域網等情況),但是若在網路狀況很好的情況下(如區域網等)就不需要再採用 TCP 協議,選擇 UDP 協議來減少網路負荷。
UDP協議例項
客戶端應用程式
客戶端應用程式完成接收終端輸入資料,並將其傳送至伺服器,並接收伺服器的資料顯示在終端。
#include<stdio.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> /* superset of previous */ #include <arpa/inet.h> #include <stdlib.h> #include <signal.h> #include <string.h> #define BUF_SIZE 512 /**********************用到的函式******************************* int socket(int domain, int type, int protocol); 建立套接字 AF_INET IPV4協議 SOCK_STREAM int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen); struct sockaddr { sa_family_t sa_family; //地址族 char sa_data[14]; //14 位元組的協議地址,包含該 socket 的 IP 地址和埠號 } struct sockaddr_in { sa_family_t sin_family; /* address family: AF_INET in_port_t sin_port; /* port in network byte order struct in_addr sin_addr; /* internet address }; struct in_addr { uint32_t s_addr; /* address in network byte order }; int listen(int sockfd, int backlog); sighandler_t signal(int signum, sighandler_t handler); int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); char *fgets(char *s, int size, FILE *stream); ********************************************************/ int main() { int client_id,clientlen; struct sockaddr_in clientadd; char buffer[BUF_SIZE]; client_id=socket(AF_INET,SOCK_DGRAM,0); //建立套接字 採用資料報式傳送 clientadd.sin_family=AF_INET; //IPV4協議 clientadd.sin_port=htons(9736);//指定埠號 clientadd.sin_addr.s_addr=inet_addr ("192.168.1.121"); //繫結IP地址,採用inet_addr將IP地址轉換為需要的資料 memset(buffer,0,strlen(buffer)); printf("please input:"); fgets(buffer,BUF_SIZE,stdin); //向伺服器寫 clientlen=sizeof(clientadd); sendto(client_id,buffer,BUF_SIZE,0,(struct sockaddr *)&clientadd,clientlen);//將接收到的內容傳送至伺服器 sleep(rand()%3); memset(buffer,0,strlen(buffer)); recvfrom(client_id,buffer,BUF_SIZE,0,(struct sockaddr *)&clientadd,&clientlen);//接收伺服器的資料 printf("You input:%s\n",buffer); close(client_id); return 0; }
伺服器端應用程式
#include<stdio.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> /* superset of previous */ #include <arpa/inet.h> #include <stdlib.h> #include <signal.h> #include <string.h> #define BUF_SIZE 512 /***************************************************** int socket(int domain, int type, int protocol); 建立套接字 AF_INET IPV4協議 SOCK_STREAM int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen); struct sockaddr { sa_family_t sa_family; char sa_data[14]; } struct sockaddr_in { sa_family_t sin_family; /* address family: AF_INET in_port_t sin_port; /* port in network byte order struct in_addr sin_addr; /* internet address }; struct in_addr { uint32_t s_addr; /* address in network byte order }; ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); ********************************************************/ int main() { int socket_id,client_id; struct sockaddr_in serveradd; struct sockaddr_in clientadd; int clientlen; char buffer[BUF_SIZE+1]; int recvbyte; socket_id=socket(AF_INET,SOCK_DGRAM,0); //建立套接字 資料報 serveradd.sin_family=AF_INET;//IPV4 協議 serveradd.sin_port=htons(9736);//指定埠號 serveradd.sin_addr.s_addr=htonl(INADDR_ANY); //繫結IP地址 //將伺服器端的繫結要監控的埠號和IP地址 if(bind(socket_id,(struct sockaddr *)&serveradd,sizeof(serveradd))==-1) { //繫結失敗 printf("connect failed!\n"); exit(EXIT_FAILURE); } signal(SIGCHLD,SIG_IGN); memset(buffer,0,strlen(buffer)); while(1) { clientlen=sizeof(clientadd); printf("please waiting....\n"); recvbyte=recvfrom(socket_id,buffer,BUF_SIZE,0,(struct sockaddr *)&clientadd,&clientlen);//接收客戶端傳送的資料 if(fork()==0)//新建子程序用於處理接收到的資料 { printf("You input :%s\n",buffer); sendto(socket_id,buffer,BUF_SIZE,0,(struct sockaddr *)&clientadd,clientlen); memset(buffer,0,strlen(buffer)); exit(EXIT_SUCCESS); } } close(socket_id);//關閉子程序 return 0; }