嵌入式linux的網絡編程(4)--UDP Server程序設計
前面介紹了基於TCP的通信程序的設計,TCP協議實現了連接的,可靠的,傳輸數據流的傳輸控制協議,而UDP是非連接的,不可靠的,傳遞數據報的傳輸協議.由於UDP不提供可靠性保證,使得具有較少的傳輸時延,因而UDP協議常常用在一些對速度要求較高的場合.
UDP通信的基本過程如下:在服務器端,服務器首先創建一個UDP數據報類型的套接字,該socket的類型為SOCK_DGRAM;然後服務器端調用bind函數,給比UDP套接字綁定一個端口.由於不需要建立連接,因此服務器端就可以通過調用recvfrom函數在指定的端口等待客戶端發送來的UDP數據報.在客戶端,同樣要先通過socket函數創建一個數據報套接字,然後由操作系統為這個套接字分配端口號.此後客戶端就可以使用sendto函數向一個地址發送一個UDP數據報.服務器端接收到數據後,從recvfrom中返回,在對數據進行處理後,再調用sendto函數將處理的結果返回客戶端.UDP連接的通信過程如下圖所示:
可見,UDP連接的通信過程相對於TCP連接的來說要簡單不少.由於UDP服務器進程不需要向TCP協議的服務器那樣要在傾聽套接字上接收新建的連接,而只需要在綁定的端口上等待客戶端發來的數據報,因此UDP服務器通常以循環的方式進行工作.
還有一點不同之處,TCP服務器通常在於客戶端建立連接後就被一個客戶端獨占,若要實現能同時為多個客戶端提供服務,則需要采取多個服務器子線程或子進程.而UDP服務器並不同客戶機建立連接,所以客戶機並不會獨占UDP服務器.例如,DNS服務器采用的UDP協議,當服務器處理完某個客戶端發來的數據報後,便可理解去處理另外一個客戶端的數據報,中間省略了許多費時的建立連接和銷毀連接的過程.提高了服務器的處理容量.
下面我們來看一個UDP服務器端程序的例子.下一篇文章會講解客戶端程序的編寫.
/**************************************************************************************/ /*簡介:UDPServer示例。 */ /*************************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <strings.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define PORT 2000 /* 監聽端口 */ #define MAXDATASIZE 100 /* 緩沖區的大小 */ #define STR "Welcome to my server.\n" int main() { int sockfd; /* 服務器的地址信息 */ struct sockaddr_in server; /* 客戶端的地址信息 */ struct sockaddr_in client; int sin_size; int num; /* 接收緩沖區 */ char msg[MAXDATASIZE]; /* 創建UDP套接字 */ if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { perror("Creating socket failed."); exit(1); } bzero(&server,sizeof(server)); server.sin_family=AF_INET; server.sin_port=htons(PORT); server.sin_addr.s_addr = htonl (INADDR_ANY); if (bind(sockfd, (struct sockaddr *)&server, \ sizeof(struct sockaddr)) == -1) { /* handle exception */ perror("Bind error."); exit(1); } sin_size=sizeof(struct sockaddr_in); while (1) { num = recvfrom(sockfd,msg,MAXDATASIZE,0,\ (struct sockaddr *)&client,&sin_size); if (num < 0) { perror("recvfrom error\n"); exit(1); } msg[num] = '\0'; printf("You got a message (%s) from %s\n",msg,\ inet_ntoa(client.sin_addr) ); /*向客戶端發送消息*/ sendto(sockfd,STR,strlen(STR),0,\ (struct sockaddr *)&client,sin_size); /*若消息是quit,則退出服務器程序*/ if (!strcmp(msg,"quit")) break; } /*關閉套接字*/ close(sockfd); return 0; }
這個服務器要實現的功能是:創建一個UDP的socket,在端口2000上等待數據報.當收到信的數據報後,獲得客戶端發來的消息,而後根據數據報中包含的發送者的地址信息,向客戶端發回一條歡迎信息,最後判斷該消息是否為退出命令,如果不是就繼續上述的工作,否則就結束服務器進程.