实现一个同步的并发型TCP服务器
来源:互联网 发布:spring boot 配置端口 编辑:程序博客网 时间:2024/04/29 02:32
1. 相关定义
- 同步: 使用会阻塞线程执行的I/O和控制操作,该阻塞会持续到相关操作完成或有错误产生
- 并发型: 服务器可以同时处理多个客户端请求
2. 基本流程
- 分配一个acceptor套接字并将其绑定到一个特定的TCP端口上.
- 服务器执行以下的循环直至停止:
- 等待客户端的连接请求
- 接受客户端的连接请求(会发生tcp的三次握手)
- 产生(spawn)一个控制线程,在这个线程的上下文中:
- 等待客户端发送的请求信息
- 读取请求信息内容
- 处理请求信息内容
- 将(处理完毕的)请求信息回送给客户端
- 关闭和客户端的连接并销毁相关套接字
3. 相关源代码
//Compile: g++ -std=c++11 -o server Server.cc -lboost_system -lpthread#include <boost/asio.hpp>#include <thread>#include <atomic>#include <memory>#include <iostream>using namespace boost;class Service { public: Service() {} void StartHandligClient(std::shared_ptr<asio::ip::tcp::socket> sock) { std::thread th(([this, sock]() { HandleClient(sock); })); th.detach(); } private: void HandleClient(std::shared_ptr<asio::ip::tcp::socket> sock) { try { asio::streambuf request; asio::read_until(*sock.get(), request, '\n'); // Emulate request processing. int i = 0; while (i != 1000000) ++i; std::this_thread::sleep_for(std::chrono::milliseconds(500)); // sending response. std::string response = "Response\n"; asio::write(*sock.get(), asio::buffer(response)); } catch (const system::system_error &e) { std::cout << "Error occured! Error code = " << e.code() << ". Message: " << e.what(); } // Clean-up.cause Service instance is allocated in heap; delete this; }};class Acceptor { public: Acceptor(asio::io_service &ios, unsigned short port_num) : ios_(ios), acceptor_(ios_, asio::ip::tcp::endpoint(asio::ip::address_v4::any(), port_num)) { acceptor_.listen(); } void Accept() { std::shared_ptr<asio::ip::tcp::socket> sock(new asio::ip::tcp::socket(ios_)); acceptor_.accept(*sock.get()); (new Service)->StartHandligClient(sock); }private: asio::io_service &ios_; asio::ip::tcp::acceptor acceptor_;};class Server { public: Server() : stop_(false) { } void Start(unsigned short port_num) { thread_.reset(new std::thread([this, port_num]() { Run(port_num); })); } void Stop() { stop_.store(true); thread_->join(); } private: void Run(unsigned short port_num) { Acceptor acc(ios_, port_num); while (!stop_.load()) { acc.Accept(); } } std::unique_ptr<std::thread> thread_; std::atomic<bool> stop_; asio::io_service ios_;};int main(){ unsigned short port_num = 3333; try { Server srv; srv.Start(port_num); std::this_thread::sleep_for(std::chrono::seconds(600)); srv.Stop(); } catch (const system::system_error &e) { std::cout << "Error occured! Error code = " << e.code() << ". Message: " << e.what(); } return 0;}
4. 缺陷及解决方案
在Server类中调用Stop()方法后,服务器可能会一直阻塞,直至最后的连接请求到来。(E.g. 当Server的线程阻塞在acc.Accept()时, 调用Stop()方法后,服务器将会等待这些阻塞操作完成而不会停止)
解决方案:
- 可以在Stop()方法中创建一个虚拟的主动连接,发送虚拟的请求
- 创建一个特殊的客户端,发送特殊的关闭服务消息(E.g.
stop\n
)
服务器容易被客户端恶意攻击(E.g. 客户端只连接,却不发送请求,那么服务器将一直处于阻塞状态)
解决方案:
- 使用非阻塞套接字(将会把我们的服务器转入reactive模式)
- 使用异步I/O
0 0
- 实现一个同步的并发型TCP服务器
- 实现一个同步的迭代型TCP服务器
- 一个简易TCP服务器的多种实现
- Java NIO 在并发型服务器设计中的应用
- Java NIO 在并发型服务器设计中的应用
- 浅谈并发服务器--多进程并发型--1
- 一个帅哥一生的发型史
- TCP并发式服务器编程实现
- 用Reactor框架实现一个简单的tcp服务器
- 一个简单的TCP服务器
- 并发式TCP服务器的设计
- 【网络】TCP服务器的实现
- Unity, C# ,TCP实现的一个简单的对话同步功能
- TCP实现客户端,服务器通信(客户端发送一个字符串,服务器回馈字符串的反序)
- 搭建服务器上的GIT并实现自动同步到站点目录(www)
- 搭建服务器上的GIT并实现自动同步到站点目录(www)
- 搭建服务器上的GIT并实现自动同步到站点目录(www)
- 搭建服务器上的Git并实现自动同步到站点目录(www)
- 蓝桥杯 算法训练 P1103 (结构体指针)
- hibernate的配置——基本映射信息
- O(1)时间删除链表结点java
- 面试中的算法
- Spring MVC学习—切面的使用(统计service中方法执行的时间)
- 实现一个同步的并发型TCP服务器
- 2016太原网络营销师如何对百度竞价的数据进行分析,讲解技巧?
- js特效-开关灯泡
- CSS3 cursor
- javascript 中的console.log
- 符号优先级
- 责任链模式
- Redis和Memcache对比及选择
- Xcode 字体 设置-- Xcode family没有显示的字体--(错手修改了,被坑全过程)