Linux应用编程---15.并发服务器模型

Linux应用编程—15.并发服务器模型

​ 并发服务器模型,之前编写的基于TCP/UDP的服务器模型只支持一个客户端访问。但实际应用过程中可能同一时刻有很多的客户端进行访问。比如12360的网站、购物网站等等。对于这种需求,提出了并发服务器的模型。

​ 这里提出常见的两种并发服务器模型,多进程式与多线程式 。前者是提前创建一定数量的进程,等待客户端与之连接,优点是与客户端的响应快速,缺点是事先不知道有多少客户端,进程创建过多造成资源浪费,进程过少,导致客户端无法正常访问。后者在有客户端连接请求后,才创建线程,在线程中处理客户端相关程序。优点是来一个客户端连接请求,节约资源;缺点是客户端连接后才创建进程处理,及时性变差。

15.1 多进程式并发服务器模型

​ 代码在之前TCP_Server.c的基础上改写。在while(1)前调用4次fork()函数创建出16个进程,进程中执行阻塞等待客户端连接及以后的代码。

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define FAILE -1
#define SUCCESS 0
#define PORT 8800
#define SIZE 100

int main(void)
{
        int ret = 0, i = 0;
        int sock_fd, client_sockfd = 0;
        int addr_len = sizeof(struct sockaddr);
        char str[SIZE] = "Welcom to connect Server.";
        struct sockaddr_in my_sockaddr, client_addr;

        my_sockaddr.sin_family = AF_INET;
        my_sockaddr.sin_port = htons(PORT);
        my_sockaddr.sin_addr.s_addr = INADDR_ANY;

        sock_fd = socket(AF_INET, SOCK_STREAM, 0);

        if(sock_fd == FAILE)
                perror("socket.");

        ret = bind(sock_fd, (struct sockaddr *)&my_sockaddr, sizeof(struct sockaddr));
        if(ret == FAILE)
                perror("bind.");

        ret = listen(sock_fd, 10);

        if(ret == FAILE)
                perror("listen.");

        for(i = 0; i < 4; i++)
                fork();

        while(1)
        {
                printf("Server is waiting for client to connect:\n");
                client_sockfd = accept(sock_fd, (struct sockaddr *)&client_addr, &addr_len);
                printf("Client address = %s\n", inet_ntoa(client_addr.sin_addr));

                send(client_sockfd, str, SIZE, 0);

                printf("Disconnect the client request.\n");

                close(client_sockfd);
        }

        close(sock_fd);

        return 0;
}

​ 运行结果:

image-20221221172058889

图1 运行结果

​ 客户端代码无改变,由于主机数量限制,还是无法现实多个客户端同时访问。但原理解释的效果以达到。

15.2 多线程并发服务器模型

​ 代码在之前TCP_Server.c的基础上改写。当我接收到一个客户端连接请求后创建线程,在线程回调函数中执行代码。代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>

#define FAILE -1
#define SUCCESS 0
#define PORT 8800
#define SIZE 100

int client_sockfd = 0;
struct sockaddr_in client_addr;
char str[SIZE] = "Welcom to connect Server.";

void * thread_function(void *arg);

int main(void)
{
        int ret = 0, i = 0;
        int sock_fd;
        int addr_len = sizeof(struct sockaddr);
        struct sockaddr_in my_sockaddr;
        pthread_t thread;

        my_sockaddr.sin_family = AF_INET;
        my_sockaddr.sin_port = htons(PORT);
        my_sockaddr.sin_addr.s_addr = INADDR_ANY;

        sock_fd = socket(AF_INET, SOCK_STREAM, 0);

        if(sock_fd == FAILE)
                perror("socket.");

        ret = bind(sock_fd, (struct sockaddr *)&my_sockaddr, sizeof(struct sockaddr));
        if(ret == FAILE)
                perror("bind.");

        ret = listen(sock_fd, 10);

        if(ret == FAILE)
                perror("listen.");

        while(1)
        {
                printf("Server is waiting for client to connect:\n");
                client_sockfd = accept(sock_fd, (struct sockaddr *)&client_addr, &addr_len);
                pthread_create(&thread, NULL, thread_function, NULL);
        }

        close(sock_fd);

        return 0;
}

void * thread_function(void *arg)
{

        printf("Client address = %s\n", inet_ntoa(client_addr.sin_addr));

        send(client_sockfd, str, SIZE, 0);
        printf("Disconnect the client request.\n");

        close(client_sockfd);

        return NULL;
}

​ gcc TCP_Server.c -o SERVER -pthread,运行结果如下图2所示:

image-20221221174609627

图2 运行结果

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值