boost.asio同步方式的Echo Server

同步echo server
echo_server_sync
代码:

#include <array>
#include <iostream>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;

enum { BUF_SIZE = 1024 };

void Session(tcp::socket&& socket)
{
	try 
	{
		//一次只处理一个连接
		while (true)
		{
			std::array<char, BUF_SIZE> data;
			boost::system::error_code ec;
			std::size_t length = socket.read_some(boost::asio::buffer(data), ec);
			if (ec == boost::asio::error::eof)
			{
				std::cout << "Connection closed cleanly by peer." << std::endl;
				//socket.close(); //可以这样关闭,也可以直接等socket析构时自动关闭 
				break;
			}
			else if (ec)
			{
				throw boost::system::system_error(ec);
			}

			boost::asio::write(socket, boost::asio::buffer(data, length));
		}
	}
	catch (const std::exception& e)
	{
		std::cerr << "Exception: " << e.what() << std::endl;
	}
}

int main(int argc, char* argv[])
{
	if (argc != 2)
	{
		std::cerr << "Usage: " << argv[0] << " <port>" << std::endl;
		return 1;
	}

	unsigned short port = std::atoi(argv[1]);

	boost::asio::io_context io_context;
	
	tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), port));

	try
	{
		while(true)
		{
			Session(std::move(acceptor.accept()));
		}
	}
	catch (const std::exception& e)
	{
		std::cerr << e.what() << std::endl;
	}

	getchar();
	return 0;
}

其中std::array<char, BUF_SIZE> data;是定义一个缓冲区,boost::array也是可以的,标准库里有std::array,我们尽量用标准库里的。
Session(std::move(acceptor.accept()));
是使用std::move,减少一次tcp::socket拷贝。

socket.read_some(boost::asio::buffer(data), ec);
if (ec == boost::asio::error::eof)

如果大家对这个socket.read_some可能有些陌生的话,可以把每次收到的数据打印出来。

std::cout << std::string(data.data(), length) << std::endl;

有个小技巧,就是BUF_SIZE = 10,设置小,就能看到真的是分几次去读取的。这样的socket.read_some的好处就是可以不用知道“应该”读多少个字节,只管去读就好了,最终把所有的数据读到,每次读的正确的字节数加起来,就是总数了。

同步的客户端:

#include <array>
#include <cstring>
#include <iostream>

//#include "boost/asio/connect.hpp"
//#include "boost/asio/io_context.hpp"
//#include "boost/asio/ip/tcp.hpp"
//#include "boost/asio/read.hpp"
//#include "boost/asio/write.hpp"

#include "boost/asio.hpp"

using boost::asio::ip::tcp;

#define USE_GLOBAL_READ 1

enum { BUF_SIZE = 1024 };

int main(int argc, char* argv[])
{
	if (argc != 3)
	{
		std::cerr << "Usage: " << argv[0] << " <host> <port>" << std::endl;
		return 1;
	}

	const char* host = argv[1];
	const char* port = argv[2];

	boost::asio::io_context io_context;

	try
	{
		tcp::resolver resolver{ io_context };
		auto endpoints = resolver.resolve(tcp::v4(), host, port);

		tcp::socket socket{ io_context };
		boost::asio::connect(socket, endpoints);

		//Get user input
		char request[BUF_SIZE];
		std::size_t request_length = 0;
		do
		{
			std::cout << "Enter messaget: ";
			std::cin.getline(request, BUF_SIZE);
			request_length = std::strlen(request);
		} while (request_length == 0);

		boost::asio::write(socket, boost::asio::buffer(request, request_length));

		std::cout << "Reply is: ";

#if USE_GLOBAL_READ

		char reply[BUF_SIZE];
		std::size_t reply_length = boost::asio::read(socket, boost::asio::buffer(reply, request_length));
		std::cout.write(reply, reply_length);
#else
		std::size_t total_reply_length = 0;
		while (true)
		{
			std::array<char, BUF_SIZE> reply;
			std::size_t reply_length = socket.read_some(boost::asio::buffer(reply));
			std::cout.write(reply.data(), reply_length);

			total_reply_length += reply_length;
			if (total_reply_length >= reply_length)
			{
				break;
			}
		}
#endif

		std::cout << std::endl;
	}
	catch (const std::exception& e)
	{
		std::cerr << e.what() << std::endl;
	}

	getchar();
	return 0;
}

注释:
因为是echo,所有客户端是知道自己要发多少个字节的,所以它可以先预先指定要读的长度进行读取,就可以用boost::asio::read去读,也可以假装自己不知道要读多少个字节,分多次去读,知道结束,如socket.read_some

客户端建立一次连接后,等待用户的输入,然后将用户输入的字符串发送给服务器端,等待服务器返回。
先运行echo server
我是在windows上运行的

echo_server_sync.exe 9000

再运行客户端:

echo_client_sync.exe 127.0.0.1 9000
Enter messaget: 222
Reply is: 222

此时服务器端会看到:

Connection closed cleanly by peer.

参考:
基于 Asio 的 C++ 网络编程
boost asio中关闭io_service和关闭socket

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值