【1】单客户端单进程,统一accept()
原型介绍:
此并发服务器模型并不预先分叉进程,而是主进程统一处理客户端的连接,当客户端的请求到达时,才临时fork()进程,由子进程处理客户端请求。

利用socket()函数建立套接字,调用bind()函数绑定地址,调用listen()函数来监听队列长度,然后进入主处理过程,等待客户端连接的到来。当客户端连接到来时,服务器的accept()函数成功返回,此时服务器进行进程分叉,父进程等待客户端请求,儿子进程处理客户端请求。

框架如图:

centos 7 TCP高并发 tcp高并发服务器_高级并发服务器

代码实例:客户端发送请求,内容为TIME的字符串,服务器端handle_connect()函数接收请求,进行判断后,将时间反馈给客户端,服务器接收到客户端的一个请求之后,之后临时fork()一个进程,父进程等待下一个请求,子进程处理客户端请求。函数handle_request()接收客户端请求,判断是否与TIME匹配。

服务器端:

#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<time.h>
#include<string.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#define SERVER_PORT 7000//设置端口地址
#define BUFF_SIZE 1024
#define BACKLOG 5//设置监听队列长度


/*处理客户端请求*/
static void handle_request(int connfd)
{
	time_t now;//时间
	char buff[BUFF_SIZE];//存放数据缓冲区
	int n=0;//接收字符串长度
	memset(buff,0,BUFF_SIZE);//清零
	n=recv(connfd,buff,BUFF_SIZE,0);//接受发送数据
	/*判断是否为合法字符 */
	if(n>0&&!strncmp(buff,"TIME",4))
	{
	memset(buff,0,BUFF_SIZE);
	now=time(NULL);//获取时间
	sprintf(buff,"%24s\r\n",ctime(&now));//将时间存入buff中
	send(connfd,buff,strlen(buff),0);//向客户端发送数据
	}
	close(connfd);//关闭文件描述符

}


/*处理客户端连接*/
static int handle_connect(int sockfd)
{
	int connfd;//客户端套接字文件描述符
	struct sockaddr_in from;//客户端地址
	socklen_t len=sizeof(from);//客户端地址长度

/*主处理过程*/
	while(1)
	{
	connfd=accept(sockfd,(struct sockaddr*)&from,&len);	//客户端连接过程
	
	if(connfd>0)
	{
		if(fork()>0)//父进程
		{
		close(connfd);//关闭父进程
		}
		else//子进程
		{
		handle_request(connfd);//处理请求

		return 0;
		}
	}

	}
}


int main(int argc, const char *argv[])
{
	int sockfd;//服务器套接字文件描述符
	struct sockaddr_in local;//本地地址

	sockfd=socket(AF_INET,SOCK_STREAM,0);//建立TCP套接字

	memset(&local,0,sizeof(local));//清零
	local.sin_family=AF_INET;
	local.sin_addr.s_addr=htonl(INADDR_ANY);
	local.sin_port=(SERVER_PORT);

	if((bind(sockfd,(struct sockaddr*)&local,sizeof(local)))==-1)//将文件描述符绑定到本地端口
	{
	perror("fail to bind");
	exit(1);
	}


	listen(sockfd,BACKLOG);//监听

	handle_connect(sockfd);//处理客户端连接

	close(sockfd);

	return 0;
}

客户端:

#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<time.h>
#include<string.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>

#define SERVER_PORT 7000
#define BUFF_SIZE 1024

int main(int argc, const char *argv[])
{	
	int sockfd;//服务器套接字文件描述符
	struct sockaddr_in server;//本地地址
	char buff[BUFF_SIZE];//收发数据缓存区
	int n=0;//接收字符串长度

	/*建立TCP套接字*/
	sockfd = socket(AF_INET, SOCK_STREAM, 0);//建立TCP套接字
	
	/*初始化地址*/
	memset(&server,0,sizeof(server));//清零
	server.sin_family=AF_INET;//AF_INET协议族
	server.sin_addr.s_addr=htonl(INADDR_ANY);//任意本地地址
	server.sin_port=(SERVER_PORT);//服务器端口
	
	/*连接服务器*/
	connect(sockfd,(struct sockaddr*)&server,sizeof(server));
	memset(buff,0,BUFF_SIZE);//清零
	strcpy(buff,"TIME");//复制发送的字符串

	/*发送数据*/
	if((send(sockfd,buff,strlen(buff),0))==-1)
	{
	perror("fail to sent");
	exit(1);
	}

	memset(buff,0,BUFF_SIZE);//清零

	/*接收数据*/
	n=recv(sockfd,buff,BUFF_SIZE,0);
	if(n>0)
	{
	printf("TIME:%s",buff);
	}
	close(sockfd);
	return 0;
}

【2】单客户单线程,统一accept()

线程与进程相比,速度更快,占用资源更少,而且数据可以共享。其框架如下:

centos 7 TCP高并发 tcp高并发服务器_Linux网络编程_02


**代码实例:**客户端发送请求,内容为TIME的字符串,服务器端handle_connect()函数接收请求,进行判断后,将时间反馈给客户端,服务器接收到客户端的一个请求之后,之后创建一个线程程,处理客户端请求。函数handle_request()接收客户端请求,判断是否与TIME匹配。

服务器端:

#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<time.h>
#include<string.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include<pthead.h>
#define SERVER_PORT 7000//设置端口地址
#define BUFF_SIZE 1024
#define BACKLOG 5//设置监听队列长度


/*处理客户端请求*/
static void handle_request(void *argv)
{
	int connfd=*((int *)argv);
	time_t now;//时间
	char buff[BUFF_SIZE];//存放数据缓冲区
	int n=0;//接收字符串长度
	memset(buff,0,BUFF_SIZE);//清零
	
	/*判断是否为合法字符 */
	if(n>0&&!strncmp(buff,"TIME",4))
	{
	memset(buff,0,BUFF_SIZE);
	now=time(NULL);//获取时间
	sprintf(buff,"%24s\r\n",ctime(&now));//将时间存入buff中
	send(connfd,buff,strlen(buff),0);//向客户端发送数据
	}
	close(connfd);//关闭文件描述符

}


/*处理客户端连接*/
static int handle_connect(int sockfd)
{
	int connfd;//客户端套接字文件描述符
	struct sockaddr_in from;//客户端地址
	socklen_t len=sizeof(from);//客户端地址长度
	
	pthread_t thread_do;//创建线程
/*主处理过程*/
	while(1)
	{
	connfd=accept(sockfd,(struct sockaddr*)&from,&len);	//客户端连接过程
	
	if(connfd>0)
	{
	pthread_craete(&thread_do,NULL,(void*)handle_request,&connfd);//创建线程处理连接
	}
	}
}


int main(int argc, const char *argv[])
{
	int sockfd;//服务器套接字文件描述符
	struct sockaddr_in local;//本地地址

	sockfd=socket(AF_INET,SOCK_STREAM,0);//建立TCP套接字

	memset(&local,0,sizeof(local));//清零
	local.sin_family=AF_INET;
	local.sin_addr.s_addr=htonl(INADDR_ANY);
	local.sin_port=(SERVER_PORT);

	if((bind(sockfd,(struct sockaddr*)&local,sizeof(local)))==-1)//将文件描述符绑定到本地端口
	{
	perror("fail to bind");
	exit(1);
	}


	listen(sockfd,BACKLOG);//监听

	handle_connect(sockfd);//处理客户端连接

	close(sockfd);

	return 0;
}

客户端:

#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<time.h>
#include<string.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>

#define SERVER_PORT 8889
#define BUFF_SIZE 1024

int main(int argc, const char *argv[])
{	
	int sockfd;//服务器套接字文件描述符
	struct sockaddr_in server;//本地地址
	char buff[BUFF_SIZE];//收发数据缓存区
	int n=0;//接收字符串长度

	/*建立TCP套接字*/
	sockfd = socket(AF_INET, SOCK_STREAM, 0);//建立TCP套接字
	
	/*初始化地址*/
	memset(&server,0,sizeof(server));//清零
	server.sin_family=AF_INET;//AF_INET协议族
	server.sin_addr.s_addr=htonl(INADDR_ANY);//任意本地地址
	server.sin_port=(SERVER_PORT);//服务器端口
	
	/*连接服务器*/
	connect(sockfd,(struct sockaddr*)&server,sizeof(server));
	memset(buff,0,BUFF_SIZE);//清零
	strcpy(buff,"TIME");//复制发送的字符串

	/*发送数据*/
	if((send(sockfd,buff,strlen(buff),0))==-1)
	{
	perror("fail to sent");
	exit(1);
	}

	memset(buff,0,BUFF_SIZE);//清零

	/*接收数据*/
	n=recv(sockfd,buff,BUFF_SIZE,0);
	if(n>0)
	{
	printf("TIME:%s",buff);
	}
	close(sockfd);
	return 0;
}