07 最原始的服务器结构

07 最原始的服务器结构 单个服务器的结构是随着业务需求的升级而不断演进。尽管我们今天看最初的一些服务器结构模型觉得非常简陋和低效但是它们是最基本的原理和最初的模型虽然我们今天在商业系统中再也不会使用那些最初的组织结构了但是了解它们能让你知道现在的复杂的结构最初是什么样子又是如何一步步地演化成今天来的面貌这就是所谓的知道“从哪里来到哪里去”。最原始的服务器结构是创建好侦听 socket在一个循环里面接受新的连接产生对应的客户端 fd然后利用这个客户端 fd 与客户端进行通信收发数据。代码如下/** * TCP服务器通信基本模型 */ #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; }上述流程的基本逻辑是程序每轮循环都只能处理一个客户端请求要处理下一个连接必须等当前的操作完成后进入下一轮循环才能继续处理。这种结构的弊端是显而易见它根本就不支持并发更不用说高并发了。