跳转至

io_service Class

充分利用 socket.select 多路复用模型实现网络服务,提供给上层统一的接口来进行 tcp, udp, kcp, ssl-client 通信。

语法

namespace yasio { inline namespace inet { class io_service; } }

成员

公共构造函数

Name Description
io_service::io_service 构造1个 io_service 对象

公共方法

Name Description
io_service::start 启动网络服务
io_service::stop 停止网络服务
io_service::is_running 判断网络服务是否运行中
io_service::is_stopping 判断网络服务是否停止中
io_service::open 打开信道
io_service::close 关闭传输会话
io_service::is_open 检测信道或会话是否打开
io_service::dispatch 分派网络事件
io_service::write 异步发送数据
io_service::write_to 异步发送DGRAM数据
io_service::schedule 注册定时器
io_service::init_globals 显示初始化全局数据
io_service::cleanup_globals 清理全局数据
io_service::channel_at 获取信道句柄
io_service::set_option 设置选项

注意

默认传输会话的创建会使用对象池 object_pool

要求

头文件: yasio.hpp

io_service::io_service

构造 io_service 对象。

io_service::io_service();

io_service::io_service(int channel_count);

io_service::io_service(const io_hostent& channel_ep);

io_service::io_service(const io_hostent* channel_eps, int channel_count);

参数

channel_count
信道数量。

channel_ep
信道远端地址。

channel_eps
信道远端地址数组首地址。

示例

#include "yasio/yasio.hpp"
int main() {
    using namespace yasio;
    io_service s1; // s1 only support 1 channel
    io_service s2(5); // s2 support 5 channels concurrency
    io_service s3(io_hostent{"github.com", 443}); // s3 support 1 channel
    io_hostent hosts[] = {  
        {"192.168.1.66", 20336},
        {"192.168.1.88", 20337},
    };
    io_service s4(hosts, YASIO_ARRAYSIZE(hosts)); // s4 support 2 channels concurrency
    return 0;
}

io_service::start

启动网络服务。

void start(io_event_cb_t cb);

参数

cb
网络事件回调,默认情况下在 io_service::dispatch 调用者线程调度。

示例

#include "yasio/yasio.hpp"
int main() {
    using namespace yasio;
    auto service = yasio_shared_service(io_hostent{host="ip138.com", port=80});
    service->start([](event_ptr&& ev) {
    auto kind = ev->kind();
    if (kind == YEK_ON_OPEN)
    {
        if (ev->status() == 0)
        printf("[%d] connect succeed.\n", ev->cindex());
        else
        printf("[%d] connect failed!\n", ev->cindex());
    }
    });
    return 0;
}

io_service::stop

停止网络服务。

void stop()

注意

  • 当在非网络服务线程调用此函数时,会等待服务线程退出并进入 IDLE 状态,此状态下可以再次调用 start 重新启动服务。
  • 当在网络服务自身线程调用了次函数时,会进入 STOPPING 状态,业务应该在非网络服务线程判断是否依然处于 STOPPING 状态来决定是否再次调用stop,例如:
    if (service->is_stopping()) {
      service->stop();
    }
    

io_service::is_running

判断网络服务是否在运行中。

bool is_running() const

返回值

true: 网络服务运行中,false: 网络服务处于其他状态

io_service::is_stopping

判断网络服务是否在停止中。

bool is_stopping() const

返回值

true: 网络服务停止中,false: 网络服务处于其他状态

io_service::open

打开信道。

bool open(size_t cindex, int kind);

参数

cindex
信道索引。

kind
信道类型。

返回值

true: 信道打开操作请求成功,false: 信道正在打开过程中。

注意

对于TCP, 将会请求内核发起非阻塞3次握手来建立可靠连接。

cindex 的值必须小于io_service初始化时的信道数量。

kind 必须是以下枚举值之一:

  • YCK_TCP_CLIENT
  • YCK_TCP_SERVER
  • YCK_UDP_CLIENT
  • YCK_UDP_SERVER
  • YCK_KCP_CLIENT
  • YCK_KCP_SERVER
  • YCK_SSL_CLIENT
  • YCK_SSL_SERVER: 必须在启动io_service前通过选项YOPT_S_SSL_CERT设置有效的证书和私钥文件才能正常工作。

io_service::close

关闭信道或者传输会话。

void close(transport_handle_t transport);

void close(int cindex);

参数

transport
将要关闭的传输会话。

cindex
将要关闭的信道。

注意

对于TCP, 将会发起4次握手来终止连接。

io_service::is_open

判断信道或传输会话是否处于打开状态。

bool is_open(transport_handle_t transport) const;

bool is_open(int cindex) const;

参数

transport
传输会话句柄。

cindex
信道索引。

返回值

true: 打开,false: 未打开

io_service::dispatch

分派网络线程产生的事件。

void dispatch(int max_count);

参数

max_count
本次最大分派事件数。

注意

通常此方法应当在关心网络事件的业务逻辑线程调用, 例如Cocos2d-x的渲染线程,以及其他游戏引擎(Unity,UE4)的主逻辑线程。

此方法对于安全地更新游戏界面非常有用。

示例

yasio_shared_service()->dispatch(128);

io_service::write

向传输会话远端发送数据。

int write(
    transport_handle_t thandle,
    yasio::sbyte_buffer buffer,
    io_completion_cb_t completion_handler = nullptr
);

参数

thandle
传输会话句柄。

buffer
要发送的二进制缓冲区。

completion_handler
发送完成回调。

返回值

返回发送数据字节数, < 0: 说明发生错误。

注意

completion_handler 不支持 KCP

空buffer会直接被忽略,也不会触发 completion_handler

io_service::write_to

向UDP传输会话发送数据。

int write_to(
    transport_handle_t thandle,
    yasio::sbyte_buffer buffer,
    const ip::endpoint& to,
    io_completion_cb_t completion_handler = nullptr
);

参数

thandle
传输会话句柄。

buffer
要发送的buffer。

to
要发送的远端地址。

completion_handler
发送完成回调。

返回值

成功发送的字节数, 当 < 0 时说明发生错误,通常是传输会话已关闭(TCP连接断开等)。

注意

此函数仅可用于 DGRAM 传输会话,即 UDP,KCP

发送完成回调 completion_handler 不支持 KCP

空buffer会直接被忽略,也不会触发 completion_handler

io_service::schedule

注册一个定时器。

highp_timer_ptr schedule(
    const std::chrono::microseconds& duration,
    timer_cb_t cb
);

参数

duration
定时器超时时间,毫秒级。

cb
当定时器到期后回调。

返回值

std::shared_ptr 包装的定时器对象,以便用户对定时器安全地进行必要操作。

示例

// Register a once timer, timeout is 3 seconds.
yasio_shared_service()->schedule(std::chrono::seconds(3), []()->bool{
  printf("time called!\n");
  return true;
});

// Register a loop timer, interval is 5 seconds.
auto loopTimer = yasio_shared_service()->schedule(std::chrono::seconds(5), []()->bool{
  printf("time called!\n");
  return false;
});

io_service::init_globals

静态方法,显示地初始化全局数据

static void init_globals(print_fn2_t print_fn);

参数

print_fn
自定义网络日志打印函数。

注意

此函数是可选调用,但是当用户需要将网络日志重定向到自定义日志系统时,
则非常有用,例如重定向到UE4和U3D的日志输出。

示例

// yasio_uelua.cpp
// compile with: /EHsc
#include "yasio_uelua.h"
#include "yasio/platform/yasio_ue4.hpp"
#include "lua.hpp"
#if defined(NS_SLUA)
using namespace NS_SLUA;
#endif
#include "yasio/bindings/lyasio.cpp"

DECLARE_LOG_CATEGORY_EXTERN(yasio_ue4, Log, All);
DEFINE_LOG_CATEGORY(yasio_ue4);

void yasio_uelua_init(void* L)
{
  auto Ls            = (lua_State*)L;
  print_fn2_t log_cb = [](int level, const char* msg) {
    FString text(msg);
    const TCHAR* tstr = *text;
    UE_LOG(yasio_ue4, Log, L"%s", tstr);
  };
  io_service::init_globals(log_cb);

  luaregister_yasio(Ls);
}
void yasio_uelua_cleanup()
{
  io_service::cleanup_globals();
}

io_service::cleanup_globals

静态方法,显示地清理全局数据。

static void cleanup_globals();

注意

当用户需要卸载包含自定义日志打印回调的动态库(.dll,.so)前必须调用此函数,谨防应用程序闪退。

io_service::channel_at

通过信道索引获取信道句柄。

io_channel* channel_at(size_t cindex) const;

参数

cindex
信道索引

返回值

信道句柄指针, 当索引值超出范围时,返回 nullptr

io_service::set_option

设置选项。

void set_option(int opt, ...);

参数

opt
选项枚举, 请查看 YOPT_X_XXX.

示例

#include "yasio/yasio.hpp"

int main(){
    using namespace yasio;
    io_hostent hosts[] = {
    {"192.168.1.66", 20336},
    {"192.168.1.88", 20337},
    };
    auto service = std::make_shared<io_service>(hosts, YASIO_ARRAYSIZE(hosts));

    // for application protocol with length field, you just needs set this option.
    // it's similar to java netty length frame based decode.
    // such as when your protocol define as following
    //    packet.header: (header.len=12bytes)
    //           code:int16_t
    //           datalen:int32_t (not contains packet.header.len)
    //           timestamp:int32_t
    //           crc16:int16_t
    //    packet.data
    service->set_option(YOPT_C_UNPACK_PARAMS,
                        0,     // channelIndex, the channel index
                        65535, // maxFrameLength, max packet size
                        2,     // lenghtFieldOffset, the offset of length field
                        4,     // lengthFieldLength, the size of length field, can be 1,2,4
                        12    // lengthAdjustment:if the value of length feild == packet.header.len + packet.data.len, this parameter should be 0, otherwise should be sizeof(packet.header)
    );

    // for application protocol without length field, just sets length field size to -1.
    // then io_service will dispatch any packet received from server immediately,
    // such as http request, this is default behavior of channel.
    service->set_option(YOPT_C_UNPACK_PARAMS, 1, 65535, -1, 0, 0);
    return 0;
}

请参阅

io_event Class

io_channel Class

io_service Options

xxsocket Class

obstream Class

ibstream_view Class

ibstream Class