1. 程式人生 > >客戶端TCP時間獲取以及實現服務端獲取客戶端IP地址

客戶端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地址和埠號

客戶端獲得時間