简单的echo服务器

本文编写的是基于libGod网络库的echo服务器示例程序,服务器把从客户端收到的任何数据不加处理的直接发给客户端。

首先是获取本机地址,并监听端口,然后为每个监听的socket启动一个处理协程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int main(int argc, char *argv[]) {
io_scheduler scheduler;
try {
config::load_from_command_line(argc, argv);
address::addresses addrs;
address::interface_addresses(addrs, g_listen_ifname->val(), address_family::inet);
if (addrs.empty()) {
GOD_LOG_INFO(g_logger) << "无效的网卡名字: " << g_listen_ifname->val();
return 1;
}
for (address::addresses::const_iterator it = addrs.begin(); it != addrs.end(); ++it) {
address::ptr addr = *it;
std::static_pointer_cast<ip_address>(addr)->set_port(g_port);
socket::ptr s = addr->create_socket(&scheduler, socket_type::stream);
socket::reuse_address_option opt(true);
s->set_option(opt);
s->bind(addr);
s->listen();
scheduler.schedule(std::bind(&handle_accept, &scheduler, s));
}
} catch (...) {
GOD_LOG_ERROR(g_logger) << boost::current_exception_diagnostic_information();
}
scheduler.dispatch();
return 0;
}

接收到客户端连接后,再启动新的协程处理客户端连接。

1
2
3
4
5
6
7
8
9
10
11
12
13
void handle_accept(io_scheduler *scheduler, socket::ptr s) {
try {
GOD_LOG_INFO(g_logger) << "监听 " << s->local_address();
while (true) {
socket::ptr client = s->accept();
GOD_LOG_INFO(g_logger) << "收到新连接: [" << client->local_address() << ", " <<
client->remote_address() << "]";
scheduler->schedule(std::bind(&handle_read, client));
}
} catch (...) {
GOD_LOG_ERROR(g_logger) << boost::current_exception_diagnostic_information();
}
}

从客户端连接接收到任何数据,都直接发送回去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void handle_read(socket::ptr s) {
GOD_LOG_INFO(g_logger) << "处理连接: [" << s->local_address() << ", " <<
s->remote_address() << "]";
try {
buffer buf;
while (true) {
socket::size_type bytes = s->receive(buf, g_block_size);
if (bytes == 0) {
break;
}
GOD_LOG_INFO(g_logger) << "收到 " << bytes << "字节数据";
s->send(buf, 0, bytes);
buf.consume(bytes);
}
} catch (...) {
GOD_LOG_ERROR(g_logger) << boost::current_exception_diagnostic_information();
}
GOD_LOG_INFO(g_logger) << "断开连接: [" << s->local_address() << ", " <<
s->remote_address() << "]";
s->shutdown();
}

整个程序的逻辑就是这样,是不是很简单。对于不熟悉协程的同学,一定以为整个程序逻辑是接收到一个新连接,就启动一个线程处理新连接。但其实不是这样的,本程序一个纯粹的单线程程序哦,是不是很神奇。不明白的同学可以去网上了解下协程。

代码下载地址

文章目录