TCP (original) (raw)

include: co/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);

#Connection::~Connection

Connection::~Connection();

#Connection::close

#Connection::recv

int recv(void* buf, int n, int ms=-1);

#Connection::recvn

int recvn(void* buf, int n, int ms=-1);

#Connection::reset

#Connection::send

int send(const void* buf, int n, int ms=-1);

#Connection::socket

#Connection::strerror

const char* strerror() const;

#tcp::Server

tcp::Server is a TCP server based on coroutine. It has the following features:

#Server::Server

#Server::conn_num

#Server::on_connection

Server& on_connection(std::function<void(Connection)>&& f);
Server& on_connection(const std::function<void(Connection)>& f);

template<typename T>
Server& on_connection(void (T::*f)(Connection), T* o);
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::on_exit

Server& on_exit(std::function<void()>&& cb);

#Server::start

void start(const char* ip, int port, const char* key=0, const char* ca=0);
void f(tcp::Connection conn);
tcp::Server().on_connection(f).start("0.0.0.0", 7788);

#Server::exit

#tcp::Client

tcp::Client is a TCP client based on coroutine. It has following features:

#Client::Client

Client(const char* ip, int port, bool use_ssl=false);
Client(const Client& c);

#Client::~Client

#Client::close

#Client::connect

#Client::connected

#Client::disconnect

#Client::recv

int recv(void* buf, int n, int ms=-1);

#Client::recvn

int recvn(void* buf, int n, int ms=-1);

#Client::send

int send(const void* buf, int n, int ms=-1);

#Client::socket

#Client::strerror

const char* strerror() const;

#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

#TCP client 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::pool_guard<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);
}