客戶端TCP時間獲取以及實現服務端獲取客戶端IP地址
這一次的問題主要是通過accept函式生成描述字,實現客戶端與伺服器的連線。
#include
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
引數cliaddr和addrlen用來返回已連線的對端程序的協議地址。addrlen是值-結果引數;呼叫前,我們將由*addrlen所引用的整數值置為由cliaddr所指的套介面地址結構的長度;返回時,該整數值即為由核心存在該套介面地址結構內的確切位元組數。
如果accept成功,那麼其返回值是由核心自動生成的一個全新描述字,代表與所返回客戶的TCP連線。我們稱它的第一個引數為監聽套介面(listening sockfd)描述字(由sockfd函式建立,隨後在bind和listen的第一個引數的描述字)。區分這兩個套介面,需要知道,一個伺服器僅僅建立一個監聽套介面,它在伺服器的生命週期中一直存在著。而當伺服器完成對於某個客戶的服務時,相應的已連線套介面就關閉。
伺服器端函式程式碼如下:daytimetcpserv1.c
#include "unp.h" #include int main(int argc, char **argv) { int listenfd, connfd; socklen_t len; struct sockaddr_in servaddr, cliaddr; char buff[MAXLINE]; time_t ticks; listenfd = Socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(13); /* daytime server */ Bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); Listen(listenfd, LISTENQ); for ( ; ; ) { len = sizeof(cliaddr); connfd = Accept(listenfd, (SA *) &cliaddr, &len); printf("connection from %s, port %d\n", Inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)), ntohs(cliaddr.sin_port)); ticks = time(NULL); snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks)); Write(connfd, buff, strlen(buff)); Close(connfd); } }
20行:bind函式繫結特定IP地址到套介面。
25-29行:我們將len初始化為套介面地址結構大小,將指向cliaddr結構的指標和指向len的指標分別作為accept的第二和第三引數。呼叫inet_ntop將套介面地址結構中的32位IP地址轉換為一個點分十進位制數ASCII字串,呼叫ntohs將16位的埠號從網路位元組序轉換為主機位元組序。
31-33行:伺服器端,將時間寫入buff,用write函式返回給客戶端。
下面進行程式編譯:
在unpv13e/lib中make後,進入unpv13e/Intro資料夾中,分別編譯daytimetcpcli.c客戶端程式和daytimetcpserv1.c伺服器端程式。
新開視窗作為伺服器端執行./daytimetcpserv1
在原視窗作為客戶端執行./daytimetcpcli 127.0.0.1
伺服器端得到客戶端的IP地址和埠號
客戶端獲得時間