TCP的高并发服务器模型

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

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

框架如图:

代码实例:客户端发送请求,内容为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()
线程与进程相比,速度更快,占用资源更少,而且数据可以共享。其框架如下:

**代码实例:**客户端发送请求,内容为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;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值