#Coroutine based network programming model
It is easy to write high-concurrency and high-performance network programs with coroutine. Although a coroutine may block, the scheduling thread can quickly switch between a large number of coroutines. Therefore, to achieve high concurrency, we just need to create more coroutines.
#Network model for TCP server
void on_connection(int fd) {
while (true) {
co::recv(fd, ...); // recv request from client
process(...); // process the request
co::send(fd, ...); // send response to client
}
}
void server_fun() {
while (true) {
int fd = co::accept(...);
if (fd != -1) go(on_connection, fd);
}
}
go(server_fun);
- One coroutine for each connection.
- In one coroutine, call
co::accept()
to accept client connections. - When a connection is accepted, create a new coroutine to handle the connection.
on_connection()
is the coroutine function for handling connections, receiving, processing and sending data are performed in a synchronous manner in the coroutine, and we do not need any asynchronous callback.
#Network model for TCP client
void client_fun() {
while (true) {
if (!connected) co::connect(...); // connect to the server
co::send(...); // send request to the server
co::recv(...); // recv response from the server
process(...); // process the response
if (over) co::close(...); // close the connection
}
}
go(client_fun);
- Connecting, sending, recving and processing data are performed in a synchronous manner in the coroutine.
In actual applications, co::pool is generally used as a connection pool to avoid creating too many connections:
co::pool g_p;
void client_fun() {
while (true) {
co::pool_guard<Connection> conn(g_p); // get a idle connection from the pool
conn->send(...); // send request to the server
conn->recv(...); // recv response from the server
process(...); // process the response
if (over) conn->close(...); // close the connection
}
}
go(client_fun);