include: co/so/tcp.h.
#tcp::Connection
tcp::Connection
is a simple encapsulation of TCP connection, it is designed for TCP server. When SSL is enabled in a TCP server, tcp::Connection will transfer data by SSL.
#Connection::Connection
Connection(int sock);
Connection(void* ssl);
Connection(Connection&& c);
- The constructor,
Connection
is created bytcp::Server
, users do not need to create it manually. - The first version constructs a normal TCP connection, the second version constructs a TCP connection that support SSL, and the third is a move constructor.
#Connection::~Connection
Connection::~Connection();
- Destructor, call close() to close the connection.
#Connection::close
int close(int ms = 0);
- Close the connection. When the parameter ms > 0, close the connection after a certain delay.
- Since v2.0.1, this method can be called anywhere(in coroutine or non-coroutine).
#Connection::recv
int recv(void* buf, int n, int ms=-1);
- Receive data, similar to co::recv.
- This method must be called in the coroutine.
- Return > 0 on success, < 0 on timeout or any error, and 0 will be returned if the peer closed the connection.
#Connection::recvn
int recvn(void* buf, int n, int ms=-1);
- Receive data of specified length, similar to co::recvn.
- Return n on success, < 0 on timeout or any error, and 0 will be returned if the peer closed the connection.
#Connection::reset
int reset(int ms = 0)
- Reset the TCP connection, unlike close(), it will not enter the
TIME_WAIT
state. When the parameter ms > 0, the connection will be reset after a certain delay. - This method must be called in the I/O thread (usually a coroutine that performs the I/O operations).
#Connection::send
int send(const void* buf, int n, int ms=-1);
- Send data, similar to co::send().
- return n on success, <= 0 on timeout or error.
#Connection::socket
int socket() const;
- Return the internal socket descriptor, -1 will be returned if the connection was closed.
#Connection::strerror
const char* strerror() const;
- When an error occurs in a method of Connection, the user can call this method to get the error message.
#tcp::Server
tcp::Server
is a TCP server based on coroutine. It has the following features:
- Support IPv4 and IPv6.
- Support SSL (openssl is required).
- One coroutine for each client connection.
#Server::Server
Server();
- The constructor, initialization.
#Server::on_connection
void on_connection(std::function<void(Connection)>&& f);
void on_connection(const std::function<void(Connection)>& f);
template<typename T> void on_connection(void (T::*f)(Connection), T* o);
-
Set a callback for handling connections.
-
In the first 2 versions, the parameter f is a function of type
void f(Connection)
, or a function object of typestd::function<void(Connection)>
. -
In the third version, the parameter f is a method in the class T, and the parameter o is a pointer to type T.
-
Since v2.0.2, the parameter of f is an object of tcp::Connection, rather than a pointer, and users do not need to delete it any more.
-
When the server receives a connection, it will create a new coroutine and call the callback set by this method in the coroutine to handle the connection.
-
Example
void f(tcp::Connection conn);
tcp::Server s;
s.on_connection(f);
void f(tcp::Connection conn) {
while (true) {
conn.recv(...);
process(...);
conn.send(...);
}
conn.close();
}
#Server::start
void start(const char* ip, int port, const char* key=0, const char* ca=0);
- Start the TCP server, this method will not block the current thread.
- The parameter ip is the server ip, which can be an IPv4 or IPv6 address, and the parameter port is the server port.
- The parameter key is path of a PEM file which stores the SSL private key, and the parameter ca is path of a PEM file which stores the SSL certificate. They are NULL by default, and SSL is disabled.
#Server::exit
void exit();
- Added since v2.0.2.
- Exit the TCP server, close the listening socket, and no longer receive new connections.
- This method will not close the connections that has been established before.
#tcp::Client
tcp::Client
is a TCP client based on coroutine. It has following features:
- Support IPv4 and IPv6.
- Support SSL (openssl is required).
- One client corresponds to one connection.
- It must be used in coroutine.
- It is not coroutine-safe, and it cannot be used by multiple coroutines at the same time.
#Client::Client
Client(const char* ip, int port, bool use_ssl=false);
Client(const Client& c);
- Constructor. The parameter ip is the ip of the server, which can be a domain name, or an IPv4 or IPv6 address; the parameter port is the server port; the parameter use_ssl indicates whether to enable SSL transmission, the default is false, and SSL is not enabled.
- The second version is the copy constructor, value of ip, port and use_ssl will be copied from another client.
- The connection is not established in the constructor. It is generally recommended to check whether the connection has been established before calling recv, send. If not, call the connect() method to establish the connection. It is easy to support auto-reconnection in this way.
#Client::~Client
Client::~Client();
- Destructor, call the disconnect() method to close the connection.
#Client::close
void close();
- Close the connection, same as disconnect().
#Client::connect
bool connect(int ms);
- Establish a connection, the parameter ms is the timeout period in milliseconds.
- This method must be called in the coroutine.
- This method returns true on success, otherwise it returns false. When it fails, the user can use the
strerror()
method to get the error message.
#Client::connected
bool connected() const;
- Determine whether the connection has been established.
#Client::disconnect
void disconnect();
- Since v2.0.1, it can be called anywhere(in coroutine or non-coroutine).
- It is safe to call this method multiple times, and it will be called automatically in the destructor.
#Client::recv
int recv(void* buf, int n, int ms=-1);
- Receive data, similar to co::recv().
- This method must be called in the coroutine.
- Return > 0 on success, < 0 on timeout or any error, and 0 will be returned if the peer closed the connection.
#Client::recvn
int recvn(void* buf, int n, int ms=-1);
- Receive data of specified length, similar to co::recvn().
- This method must be called in the coroutine.
- Return n on success, < 0 on timeout or any error, and 0 will be returned if the peer closed the connection.
#Client::send
int send(const void* buf, int n, int ms=-1);
- Send data, similar to co::send().
- This method must be called in the coroutine.
- return n on success, <= 0 on timeout or error.
#Client::socket
int socket() const;
- Return the internal socket descriptor.
- When the connection is not established or the connection has been closed, the return value is -1.
#Client::strerror
const char* strerror() const;
- When an error occurs in a method of tcp::Client, the user can call this method to get the error message.
#TCP server example
void on_connection(tcp::Connection conn) {
char buf[8] = { 0 };
while (true) {
int r = conn.recv(buf, 8);
if (r == 0) { /* client close the connection */
conn.close();
break;
} else if (r < 0) { /* error */
conn.reset(3000);
break;
} else {
LOG << "server recv " << fastring(buf, r);
LOG << "server send pong";
r = conn.send("pong", 4);
if (r <= 0) {
LOG << "server send error: " << conn.strerror();
conn.reset(3000);
break;
}
}
}
}
tcp::Server s;
s.on_connection(on_connection);
s.start("0.0.0.0", 7788); // no ssl
s.start("0.0.0.0", 7788, "privkey.pem", "certificate.pem"); // use ssl
- The above example implements a simple ping-pong server, when it receives a ping sent by the client, it will reply with a pong.
#TCP client code example
bool use_ssl = false;
std::unique_ptr<tcp::Client> proto;
co::Pool pool(
[]() {return (void*) new tcp::Client(*proto); },
[](void* p) {delete (tcp::Client*) p;}
);
void client_fun() {
co::PoolGuard<tcp::Client> c(pool);
if (!c->connect(3000)) {
LOG << "connect failed: "<< c->strerror();
return;
}
char buf[8] = {0 };
while (true) {
LOG << "client send ping";
int r = c->send("ping", 4);
if (r <= 0) {
LOG << "client send error: "<< c->strerror();
break;
}
r = c->recv(buf, 8);
if (r < 0) {
LOG << "client recv error: "<< c->strerror();
break;
} else if (r == 0) {
LOG << "server close the connection";
break;
} else {
LOG << "client recv "<< fastring(buf, r) <<'\n';
co::sleep(3000);
}
}
}
proto.reset(new tcp::Client("127.0.0.1", 7788, use_ssl));
for (int i = 0; i <8; ++i) {
go(client_fun);
}
- In the above example, we use co::Pool to cache client connections, and different coroutines can share connections in co::Pool.
- co::PoolGuard automatically pop an idle connection from co::Pool during construction, and automatically puts the connection back into co::Pool during destruction.