TCP客户/服务器程序设计模型-并发服务器
上文中所说的迭代服务器简单易懂,将它作为学习socket编程的例子再适合不过了。但是在一般的实际应用中我们并不会使用这个简单的迭代服务器,因为这样的服务器每次只能服务一个客户,如果这个客户请求长时间占用服务器,那么其他客户将一直不能被服务。较为理想的情况是服务器可以同时为多个客户服务,接下来将要说明的并发服务器就可以满足这样的要求。
1.并发服务器原理
关于并发服务器的基本原理可以参考本博客之前的文章,这里不在赘述。下面将通过一个具有并发服务器的C/S模型示例来说明并发服务器程序设计的细节。
2客户程序设计
客户程序与上文所述的客户程序类似,只不过在客户端进行connect之后,客户端与服务器之间的所有数据交互都封装在了str_cli函数中。客户程序主函数在调用该函数时不仅要向该函数传递套接字,还要传递标准输入文件指针stdin。具体代码如下:
void str_cli(FILE *fp, int sockfd) { char sendline[DATA_MAX], recvline[DATA_MAX]; memset(sendline, 0, DATA_MAX); memset(recvline, 0, DATA_MAX); while(fgets(sendline, DATA_MAX, fp) != NULL) { if (write(sockfd, sendline, strlen(sendline)) < 0) { printf("write error!\n"); exit(1); } if (read(sockfd, recvline, DATA_MAX) == 0) { printf("read error!\n"); exit(1); } fputs(recvline, stdout); memset(sendline, 0, DATA_MAX); memset(recvline, 0, DATA_MAX); } }
从客户端的数据交互函数str_cli中可以看出客户端进行的操作如下:
1.客户程序通过fgets从标准输入文件读入数据,并通过write将数据发送至服务器端;
2.客户程序通过read函数读取服务器发来的数据,并通过fputs将数据写入标准输出文件;
3.如果fgets读入数据错误时,整个循环结束,客户端也将结束;
3.服务器程序设计
并发服务器的经典模型在本博客之前的文章中有所提到,这里只是特别说明服务器数据处理函数。
void str_echo(int sockfd) { int n; char buf[DATA_MAX]; again: while((n = read(sockfd, buf, DATA_MAX)) > 0) if (write(sockfd, buf, n) < 0) { printf("write error!\n"); exit(1); } if (n < 0 && errno == EINTR) goto again; else if (n < 0) printf("str_echo error!\n"); }
服务器程序完成的工作如下:
1.通过read读取客户程序发送的数据;
2.通过write将刚刚读到的数据重新发送给客户程序;
3.如果客户端正常退出,那么服务器的read函数将返回0并退出循环;否则将显示错误信息;
通过上述对客户和服务器程序的描述,我们可以得知该C/S模型的工作方式是:客户程序从标准输入读入用户输入的数据,并发送至服务器;服务器从网络输入读入该数据,立即将读入的数据发送给客户程序;客户从网络输入读取服务器发来的数据,并将其显示在标准输出上。
也就是说,每当用户在客户端输入数据,客户端在终端上又会立即回显用户所输入的数据。因此,我们将上述所举例的具有并发服务器的C/S模型称之为回射客户/服务器程序。