TCP迭代服务器程序设计

2011年6月7日 由 edsionte 留言 »

TCP客户/服务器程序设计模型-迭代服务器

本博客将从本文开始持续更新基于TCP的C/S程序设计基本模型系列文章。一开始我们以一个简单的C/S模型为例进行学习,在后续的文章中我们将给出不同的客户/服务器模型。

下面将要示例的程序具有这样的功能:客户程序与服务器建立一个TCP连接后,服务器以友好的方式将当前的时间和日期发送给客户程序。我们接下来重点对示例程序的设计模式和一些设计细节作以说明,程序中所涉及的socket接口具体可以参考这里的文章。

1.客户程序设计

在基于socket的C/S模型中,客户程序往往比服务器程序简单的多。客户程序通常完成的工作是:通过socket函数创建一个套接字;connect到服务器;如果连接成功,则与服务器进行数据交互,具体为从服务器读取数据或向服务器写入数据。客户程序的核心代码如下:

int main(int argc, char **argv)
{
	int sockfd, n;
	char recvline[MAXLINE + 1];
	struct sockaddr_in serv_addr;

	if (argc != 2) {
		printf("Usage:a.out \n");
		exit(1);
	}

	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		my_error("socket", errno, __LINE__);

	memset(&serv_addr, 0, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(4555);

	if (inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0)
 		my_error("inet_pton", errno, __LINE__);
 	if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)) == -1)
  		my_error("connect", errno, __LINE__);
 	while ((n = read(sockfd, recvline, MAXLINE)) > 0) {
		recvline[n] = 0;
		if (fputs(recvline, stdout) == EOF)
			my_error("fputs", errno, __LINE__);
	}

	if (n < 0)
		printf("Error:read error\n");

	exit(0);
}

关于客户端程序的设计,说明如下:

1.客户端程序每次启动时,以命令行参数形式将服务器IP传递给客户端。因此程序一开始必须检测命令行参数的合理性;

2.由于我们的C/S模型是基于TCP的字节流套接字,因此相应的对socket函数使用AF_INET和SOCK_STREAM参数。socket函数返回一个整形的套接字描述符,在客户程序中要使用的connet和read等函数将依靠此描述符来对套接字进行操作;

3.在客户连接至服务器之前前,必须设置网际套接字地址结构,即依次对sockaddr_in结构中的字段填入正确的值。htons函数将主机字节序列转换成网络字节序列;inet_pton函数则是将字符形式的IP地址转换成二进制数值形式;

4.connect将与其第二个参数所指定的服务器建立一个TCP连接。connect函数的第二个参数为通用套接字地址结构sockaddr,因此必须对网际套接字地址结构进行强制类型转换;

5.通过套接字描述符sockfd从服务器端进行读数据,并通过fputs函数将读到的数据显示在标准输出设备;

2.服务器程序设计

服务器程序按照以下步骤进行设计:socket一个套接字;将服务器端口bind到服务器套接字上;通过listen函数将服务器套接字转换成监听套接字;accept客户端的连接;如果连接成功,则与客户端进行数据交互;终止连接。服务器程序核心程序如下所示。

int main(int argc, char **argv)
{
	int listenfd, connfd;
	struct sockaddr_in serv_addr, client_addr;
	char buf[MAXLINE];
	time_t ticks;
	int addr_size;

	if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
		my_error("socket", errno, __LINE__);

	memset(&serv_addr, 0, sizeof(struct sockaddr_in));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	serv_addr.sin_port = htons(4555);

	if (bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)) == -1)
		my_error("bind", errno, __LINE__);

	if (listen(listenfd, LISTENQ) == -1)
		my_error("listen", errno, __LINE__);

	for (;;) {
		addr_size = sizeof(struct sockaddr);
		if ((connfd = accept(listenfd, (struct sockaddr*)&client_addr, &addr_size)) == -1)
			my_error("accept", errno, __LINE__);

		printf("%s has connectd to server..\n", inet_ntoa(client_addr.sin_addr));
		ticks = time(NULL);
		snprintf(buf, sizeof(buf), "%.24s\r\n", ctime(&ticks));
		if (write(connfd, buf, strlen(buf)) < 0)
			my_error("write", errno, __LINE__);

		close(connfd);
	}
}

关于服务器程序的相关细节,说明如下:

1.在设置网际套接字地址时,将IP地址指定为INADDR_ANY。如果服务器主机有多个网络接口,那么服务器进程就可以在任意网络接口上接受客户连接;

2.listen函数将套接字转换成监听套接字,这样内核就可以通过该套接字接受客户端的外来连接请求;

3.socket、bind和listen这三步是TCP服务器获得监听套接字描述符的通用步骤;

4.服务器的连续运转是通过死循环来实现的,并通过accept函数使得服务器程序不会过于占据系统内存。通常服务器进程通过accept函数进入阻塞状态,直到某个客户连接到达时才会被唤醒。客户和服务器之间的TCP连接是通过三次握手来建立的,accept函数建立连接成功后会返回另一个套接字描述符——已连接套接字。该套接字用于和刚刚连接的客户进行通信。

5.time函数将返回1970年1月1日至现在的秒数,而ctime函数将这些秒数转换成友好的时间格式;

6.wirte函数通过已连接套接字connfd将时间信息发送至客户端;

通过服务器程序我们可以看到,如果服务器没有处理客户端的请求,那么它将一直处于阻塞状态;如果服务器正在处理来自客户端的连接请求,那么其他请求连接至服务器的客户进程则一直处于阻塞状态。只有当服务器处理完当前客户的连接请求时,其他客户的连接请求才有机会被服务器处理。我们将此服务器称之为迭代式服务器,也就是说服务器对于每个客户都将迭代执行一次。

上述所示例的迭代服务器适用性很差,因为在服务器处理当前的客户请求之前,其余等待的客户程序都不能被处理。但它作为一个基本的C/S模型,对于初学者以及理解后续C/S模型都有极大帮助。

广告位

发表回复

windows 7 ultimate product key

windows 7 ultimate product key

winrar download free

winrar download free

winzip registration code

winzip registration code

winzip free download

winzip free download

winzip activation code

winzip activation code

windows 7 key generator

windows 7 key generator

winzip freeware

winzip freeware

winzip free download full version

winzip free download full version

free winrar download

free winrar download

free winrar

free winrar

windows 7 crack

windows 7 crack

windows xp product key

windows xp product key

windows 7 activation crack

windows7 activation crack

free winzip

free winzip

winrar free download

winrar free download

winrar free

winrar free

download winrar free

download winrar free

windows 7 product key

windows 7 product key