Linux 系统应用编程——网络编程(服务器模型)

       在网络通信过程中,服务端通常需要处理多个客户端。由于多个客户端的请求可能会同时到来,服务器端可采用不同的方法来处理。总体上来说,服务器端可采用两种模型来实现:循环服务器模型和并发服务器模型

        循环服务器模型是指服务器端依次处理每个客户端,直到当前客户端的所有请求处理完毕,再处理下一个客户端。这类模型的优点是简单,缺点显而易见。特别是TCP循环服务器模型,由于必须先处理完当前客户端,容易造成其他客户端等待时间较长的情况。

        为了提高服务器的并发处理能力,又引入了并发服务器模型。其基本思想是在服务器端此阿勇多任务机制(多进程或多线程),分别为每个客户端创建一个任务来处理,极大地提高了服务器的并发处理能力。

        下面具体介绍循环服务器模型和并发服务器模型的流程及实现。为了更好的进行对比。本节均以TCP为例讨论相关模型。

 

一、循环服务器(TCP)

1、运行介绍

       TCP循环服务器是一种常用的模型,其工作流程如下:

1)服务器端从连接请求队列中提取请求,建立连接并返回新的已连接套接字;

2)服务器端通过已连接套接字循环接收数据,处理并发送给客户端,知道客户端关闭连接;

3)服务器端关闭已连接套接字,返回步骤1;

 

2、特点分析

       通过上面对服务器执行过程的介绍,可以得到以下结论。

1)服务器端采用循环嵌套来实现。外层循环依次提取每个客户端的连接请求,建立TCP连接。内层循环接受并处理当前客户端的所有数据,知道客户端关闭连接;

2)如果当前客户端没有处理结束,其他客户端必须一直等待。

注意:采用这种模型的服务器无法同时为多个客户端服务。

 

3、编程示例

下面实现 TCP ECHO 服务器端和客户端。服务器端接收到客户端数据后,原封不动发送回去(回射服务);客户端运行时,用户从键盘输入字符串,发送给服务器端并接受返回的数据,直到用户输入quit 后退出。

server.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUFFER_SIZE 128
#define PORT 8888

int main()
{
	int listenfd, clientfd;
	int n;
	struct sockaddr_in serveraddr,clientaddr;
	socklen_t peerlen;
	char buffer[BUFFER_SIZE];

	if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		perror("socket error");
		exit(-1);
	}
	else
	{
		printf("listenfd:%d\n",listenfd);
	}

	memset(&serveraddr,0,sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_port = htons(PORT);
	serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);

	if(bind(listenfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr)) < 0) //绑定IP地址和端口号
	{
		perror("bind error");
		exit(-1);
	}
	else
	{
		printf("bind successfully!\n");
	}

	if(listen(listenfd,10) == -1)
	{
		perror("listen error");
		exit(-1);
	}
	else
	{
		printf("listening....\n");
	}

	peerlen = sizeof(clientaddr);
	while(1)
	{
		if((clientfd = accept(listenfd,(struct sockaddr *)&clientaddr,&peerlen)) < 0) //循环等待客户端的连接
		{
			perror("accept error");
			exit(-1);
		}
		else
		{
			printf("connection from [%s:%d]\n",inet_ntoa(clientaddr.sin_addr)
					,ntohs(clientaddr.sin_port));	
		}

		memset(buffer,0,sizeof(buffer));
		while(1)
		{
			if((n = recv(clientfd,buffer,BUFFER_SIZE,0)) == -1) //循环接收客户端发送的数据
			{
				perror("recv error");
				exit(-1);
			}
			else if(n == 0) //此时,客
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值