大数跨境
0
0

02. 低效的服务器结构是什么样的?

02. 低效的服务器结构是什么样的? CppGuide
2024-01-18
0

关注我,更多的优质内容第一时间阅读


单个服务器的结构,是随着业务需求的升级而不断演进。尽管我们今天看最初的一些服务器结构模型觉得非常简陋和低效,但是它们是最基本的原理和最初的模型,虽然我们今天在商业系统中再也不会使用那些最初的组织结构了,但是了解它们能让你知道现在的复杂的结构最初是什么样子,又是如何一步步地演化成今天的面貌,这就是所谓的知道“从哪里来,到哪里去”。

最原始的服务器结构,是创建好侦听 socket,在一个循环里面接受新的连接,产生对应的客户端 fd,然后利用这个客户端 fd 与客户端进行通信(收发数据)。代码如下:

/**
 * TCP服务器通信基本模型
 * zhangxf 2018.12.13
 */
#include <sys/types.h> 
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <iostream>
#include <string.h>

int main(int argc, char* argv[])
{
    //1.创建一个侦听socket
    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listenfd == -1)
    {
        std::cout << "create listen socket error." << std::endl;
        return -1;
    }

    //2.初始化服务器地址
    struct sockaddr_in bindaddr;
    bindaddr.sin_family = AF_INET;
    bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    bindaddr.sin_port = htons(3000);
    if (bind(listenfd, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) == -1)
    {
        std::cout << "bind listen socket error." << std::endl;
        return -1;
    }

 //3.启动侦听
    if (listen(listenfd, SOMAXCONN) == -1)
    {
        std::cout << "listen error." << std::endl;
        return -1;
    }

    while (true)
    {
        struct sockaddr_in clientaddr;
        socklen_t clientaddrlen = sizeof(clientaddr);
  //4. 接受客户端连接
        int clientfd = accept(listenfd, (struct sockaddr *)&clientaddr, &clientaddrlen);
        if (clientfd != -1)
        {          
   char recvBuf[32] = {0};
   //5. 从客户端接受数据
   int ret = recv(clientfd, recvBuf, 32, 0);
   if (ret > 0) 
   {
    std::cout << "recv data from client, data: " << recvBuf << std::endl;
    //6. 将收到的数据原封不动地发给客户端
    ret = send(clientfd, recvBuf, strlen(recvBuf), 0);
    if (ret != strlen(recvBuf))
     std::cout << "send data error." << std::endl;
    
    std::cout << "send data to client successfully, data: " << recvBuf << std::endl;
   } 
   else 
   {
    std::cout << "recv data error." << std::endl;
   }
   
   close(clientfd);
        }
    }
 
 //7.关闭侦听socket
 close(listenfd);

    return 0;
}

上面的代码,我们抽出我们关心的主干部分并整理成伪码如下:

int main(int argc, char* argv[])
{
    //1. 初始化阶段

    while (true)
    {
        //2. 利用 accept 函数接受连接,产生客户端 fd
        
        //3. 利用步骤 2 中的 fd 与某个客户端通信
    }
 
 //3. 资源清理

    return 0;
}

上述流程的基本逻辑是程序每轮循环都只能处理一个客户端请求,要处理下一个连接,必须等当前的操作完成后进入下一轮循环才能继续处理。这种结构的弊端是显而易见,它根本就不支持并发,更不用说高并发了。

正文完。


相关阅读


小方目前在一家知名外企做 C++ 架构方面的工作。我建立 高质量 C++ 后端开发微信技术交流群,群里高手如云,不定期分享编程技术,也会提供一些求职和内推资源。


现在限时开放中,需要加群交流的同学可以加微信 cppxiaofang,备注“加群”。


关注我,更多的优质内容第一时间阅读

【声明】内容源于网络
0
0
CppGuide
专注于高质量高性能C++开发,站点:cppguide.cn
内容 1260
粉丝 0
CppGuide 专注于高质量高性能C++开发,站点:cppguide.cn
总阅读289
粉丝0
内容1.3k