編寫與客戶端之間維持連接的應用程序,我們用面向連接的TCP套接字來完成這一工作。但在有些情況下,在程序中花費時間來建立和維持一個套接字連接是不必要的。比如 daytime 服務,我們首先創建一個套接字,然後建立連接,讀取一個響應,最後關閉連接。在這一過程中,我們使用了很多操作步驟,僅僅爲了獲取一個日期。
daytime 服務還可以用數據報通過UDP來訪問。爲了訪問它,發送一個數據報給該服務,然後在響應中獲取一個包含日期和時間的數據報。這一過程非常簡單。當客戶需要發送一個短小的查詢請求給服務器,並且期望接受到一個短小的響應時,我們一般使用由UDP提供的服務。如果服務器處理客戶請求的時間足夠短,服務器就可以通過一次處理一個客戶請求的方式來提供服務,從而允許操作系統將客戶進入的請求放入隊列。這簡化服務器程序的編寫。
爲了使用UDP提供的服務,你需要像往常一樣使用套接字和 close 系統調用,但你需要用兩個數據報專用的系統調用 sendto 和 recvfrom 來代替使用TCP服務時的 read 和 write 調用。下面是一個簡單的示範程序,如有需要可以擴展其功能:
- /* server.cc */
- #include <cstdio>
- #include <cstdlib>
- #include "sys/socket.h"
- #include "netinet/in.h"
- #include "unistd.h"
- #define SRV_PORT 6500
using namespace std;- char buffer[512];
- int main(int argc, char *argv[])
- {
- /* Create a UDP socket */
- int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- /* Construct the address for use with sendto/recvfrom */
- struct sockaddr_in address;
- address.sin_family = AF_INET;
- address.sin_addr.s_addr = htonl(INADDR_ANY);
- address.sin_port = htons(SRV_PORT);
- int len = sizeof(address);
- /* Bind address to socket */
- bind(sockfd, (struct sockaddr *)&address, sizeof(address));
- /* serving */
- while(1) {
- /* receive */
- recvfrom(sockfd, buffer, sizeof(buffer), 0,
- (struct sockaddr *)&address, (socklen_t *)&len);
- /* handle */
- sprintf(buffer, "i am server");
- /* response */
- sendto(sockfd, buffer, sizeof(buffer), 0,
- (struct sockaddr *)&address, sizeof(address));
- }
- /* close */
- close(sockfd);
- return 0;
- }
- /* client.cc */
- #include <cstdio>
- #include <cstdlib>
- #include "arpa/inet.h"
- #include "sys/socket.h"
- #include "netinet/in.h"
- #include "unistd.h"
- #define SRV_ADDR "127.0.0.1"
- #define SRV_PORT 6500
- #include "client.h"
- using namespace std;
- char buffer[512];
- int main(int argc, char *argv[])
- {
- /* Create a UDP socket */
- int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- /* Construct the address for use with sendto/recvfrom */
- struct sockaddr_in address;
- address.sin_family = AF_INET;
- address.sin_addr.s_addr = inet_addr(SRV_ADDR);
- address.sin_port = htons(SRV_PORT);
- int len = sizeof(address);
- /* sendto */
- sendto(sockfd, buffer, sizeof(buffer), 0,
- (struct sockaddr *)&address, sizeof(address));
- /* receive */
- recvfrom(sockfd, buffer, sizeof(buffer), 0,
- (struct sockaddr *)&address, (socklen_t *)&len);
- /* debug */
- printf("RECV: %s", buffer);
- /* close */
- close(sockfd);
- return 0;
- }