C++ 网络编程 asio 使用总结 - 知乎 (zhihu.com)
基于Boost::asio的多线程异步TCP服务器,实现了io_service线程池,测试了1万左右的并发访问,读写无压力_boost asio支持最大并发_E404的博客-CSDN博客
单线程
server.cpp
#include
#include
#include
#include
#include
#include
#include
using boost::asio::ip::tcp;
class session : public std::enable_shared_from_this //从enable_shared_from_this继承的类需要使用智能指针管理资源
{
public:
session(tcp::socket socket) : socket_(std::move(socket)) { }
void start()
{
do_read();
}
private:
void do_read()
{
auto self(shared_from_this()); //对自己的引用计数+1
socket_.async_read_some(boost::asio::buffer(data_,max_length),[this,self](boost::system::error_code ec , std::size_t length)
{
printf("recv data:%s\n",data_);
if(!ec)
{
do_write(length);
}
});
}
void do_write(std::size_t length)
{
auto self(shared_from_this());
boost::asio::async_write(socket_,boost::asio::buffer(data_,length),[this,self](boost::system::error_code ec , std::size_t)
{
if(!ec)
{
do_read();
}
});
}
private:
tcp::socket socket_;
enum {max_length = 1024};
char data_[max_length];
};
class Server
{
public:
Server(boost::asio::io_service &io_service,short port) : acceptor_(io_service, tcp::endpoint(tcp::v4(),port)) , socket_(io_service) { }
void start()
{
do_accept();
}
private:
void do_accept()
{
acceptor_.async_accept(socket_ , [this](boost::system::error_code ec) //创建一个socket连接
{
if(!ec)
{
auto newSession = std::make_shared(std::move(socket_));
newSession->start();
}
do_accept();
});
}
tcp::acceptor acceptor_;
tcp::socket socket_;
};
int main(int argc,char *argv[])
{
try
{
if(argc != 2)
{
std::cerr << "请输入端口号:" << std::endl;
return 1;
}
boost::asio::io_service io_service;
Server s(io_service,std::atoi(argv[1]));
s.start();
io_service.run();
}catch(std::exception &e)
{
std::cerr << "异常:" << e.what() << std::endl;
}
return 0;
}
client.cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXSIZE 1024
#define IP_ADDR "127.0.0.1"
#define IP_PORT 8888
int i_sockfd = -1;
void SigCatch(int sigNum) //信号捕捉函数(捕获Ctrl+C)
{
if(i_sockfd != -1)
{
close(i_sockfd);
}
printf("Bye~! Will Exit...\n");
exit(0);
}
int main()
{
struct sockaddr_in st_clnsock;
char msg[1024];
int nrecvSize = 0;
signal(SIGINT, SigCatch); //注册信号捕获函数
if((i_sockfd = socket(AF_INET, SOCK_STREAM, 0) ) < 0) //建立套接字
{
printf("socket Error: %s (errno: %d)\n", strerror(errno), errno);
exit(0);
}
memset(&st_clnsock, 0, sizeof(st_clnsock));
st_clnsock.sin_family = AF_INET; //IPv4协议
//IP地址转换(直接可以从物理字节序的点分十进制 转换成网络字节序)
if(inet_pton(AF_INET, IP_ADDR, &st_clnsock.sin_addr) <= 0)
{
printf("inet_pton Error: %s (errno: %d)\n", strerror(errno), errno);
exit(0);
}
st_clnsock.sin_port = htons(IP_PORT); //端口转换(物理字节序到网络字节序)
if(connect(i_sockfd, (struct sockaddr*)&st_clnsock, sizeof(st_clnsock)) < 0) //主动向设置的IP和端口号的服务端发出连接
{
printf("connect Error: %s (errno: %d)\n", strerror(errno), errno);
exit(0);
}
printf("======connect to server, sent data======\n");
while(1) //循环输入,向服务端发送数据并接受服务端返回的数据
{
fgets(msg, MAXSIZE, stdin);
printf("will send: %s", msg);
if(write(i_sockfd, msg, MAXSIZE) < 0) //发送数据
{
printf("write Error: %s (errno: %d)\n", strerror(errno), errno);
exit(0);
}
memset(msg, 0, sizeof(msg));
if((nrecvSize = read(i_sockfd, msg, MAXSIZE)) < 0) //接受数据
{
printf("read Error: %s (errno: %d)\n", strerror(errno), errno);
}
else if(nrecvSize == 0)
{
printf("Service Close!\n");
}
else
{
printf("Server return: %s\n", msg);
}
}
return 0;
}