uv_stream_t --- 流句柄

流句柄提供对双工通信通道的一种抽象。 uv_stream_t 是一个抽象类型,libuv提供了3种流的实现以 uv_tcp_tuv_pipe_tuv_tty_t 的形式。

数据类型

uv_stream_t

流句柄类型。

uv_connect_t

连接请求类型。

uv_shutdown_t

停机请求类型。

uv_write_t

写请求类型。 当复用这种对象时必须小心注意。 当一个流处在非阻塞模式,用 uv_write 发送的写请求将被排队。 在此刻复用对象是未定义的行为。 仅在传递给 uv_write 的回调函数执行完毕后才能安全地复用 uv_write_t 对象。

void (*uv_read_cb)(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)

数据在流上读取时的回调函数。

nread 是 > 0 如果有可用的数据,或 < 0 当错误时。 当我们已经到达EOF, nread 将被设置为 UV_EOF 。 当 nread < 0 时 buf 参数可能并不指向一个合法的缓冲区; 在那种情况下 buf.lenbuf.base 都被设为0。

注解

nread 可能是0,并 预示着一个错误或EOF。 这等同于在 read(2) 下的 EAGAINEWOULDBLOCK

调用者负责在错误发生时通过调用 uv_read_stop()uv_close() 停止/关闭流。 尝试从流再次读取是未定义的。

调用者负责释放缓冲区,libuv不会复用它。 在错误时缓冲区可能是一个空缓冲区(这里 buf->base=NULL 且 buf->len=0)。

void (*uv_write_cb)(uv_write_t* req, int status)

数据已经在流上写后的回调函数。 status 若成功将是0,否则 < 0。

void (*uv_connect_cb)(uv_connect_t* req, int status)

uv_connect() 开启连接完成后的回调函数。 status 若成功将是0,否则 < 0。

void (*uv_shutdown_cb)(uv_shutdown_t* req, int status)

停机请求完成后的回调函数。 status 若成功将是0,否则 < 0。

void (*uv_connection_cb)(uv_stream_t* server, int status)

当流服务器接收到新来的连接时的回调函数。 用户能够通过调用 uv_accept() 来接受连接。 status 若成功将是0,否则 < 0。

公共成员

size_t uv_stream_t.write_queue_size

包含等待发送的排队字节的数量。 只读。

uv_stream_t* uv_connect_t.handle

指向此连接请求所运行于的流的指针。

uv_stream_t* uv_shutdown_t.handle

指向此停机请求所运行于的流的指针。

uv_stream_t* uv_write_t.handle

指向此写请求所运行于的流的指针。

uv_stream_t* uv_write_t.send_handle

指向使用此连接请求被发送的的流的指针。

参见

uv_handle_t 的成员也适用。

API

int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb)

停机双工流的向外(写)端。 它等待未处理的写请求完成。 handle 应该指向已初始化的流。 req 应该是一个未初始化的停机请求结构体。 cb 在停机完成后被调用。

int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb)

开始侦听新来的连接。 backlog`指内核可能排队的连接数,与 :man:`listen(2) 相同。 当接受到新来的连接时,调用 uv_connection_cb 回调函数。

int uv_accept(uv_stream_t* server, uv_stream_t* client)

调用用来配合 uv_listen() 接受新来的连接。 在接收到 uv_connection_cb 后调用这个函数以接受连接。 在调用这个函数前,客户端句柄必须被初始化。 < 0 返回值表示错误。

uv_connection_cb 回调函数被调用时,保证这个函数将会成功第一次。 如果你尝试使用超过一次,它可能失败。 建议每个 uv_connection_cb 调用只调用这个函数一次。

注解

serverclient 必须是运行在同一个循环之上的句柄。、

int uv_read_start(uv_stream_t* stream, uv_alloc_cb alloc_cb, uv_read_cb read_cb)

从内向的流读取数据。 将会调用 uv_read_cb 回调函数几次直到没有更多数据可读或是调用了 uv_read_stop()

int uv_read_stop(uv_stream_t*)

停止从流读取数据。 uv_read_cb 回调函数将不再被调用。

这个函数是幂等的且可以在已停止的流上安全地被调用。

int uv_write(uv_write_t* req, uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb)

写数据到流。 缓冲区按序写入。例如:

void cb(uv_write_t* req, int status) {
    /* 处理写结果的逻辑 */
}

uv_buf_t a[] = {
    { .base = "1", .len = 1 },
    { .base = "2", .len = 1 }
};

uv_buf_t b[] = {
    { .base = "3", .len = 1 },
    { .base = "4", .len = 1 }
};

uv_write_t req1;
uv_write_t req2;

/*  "1234" */
uv_write(&req1, stream, a, 2, cb);
uv_write(&req2, stream, b, 2, cb);

注解

被缓冲区指向的内存必须保持有效直到回调函数执行完。 这也适用于 uv_write2()

int uv_write2(uv_write_t* req, uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_stream_t* send_handle, uv_write_cb cb)

扩展的写函数用于在管道上发送句柄。 管道必须以 ipc == 1 初始化。

注解

send_handle 必须是一个TCP套接字或者管道,且为一个服务器或一个连接(侦听或已连接状态)。 绑定的套接字或管道将被假设是服务器。

int uv_try_write(uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs)

uv_write() 相同,但是如果无法立刻完成时不会排队写请求。

将返回以下之一:

  • > 0: 已写字节数(可能小于提供的缓冲区大小)。
  • < 0: 负的错误代码(返回 UV_EAGAIN 如果没有数据能立刻发送)。
int uv_is_readable(const uv_stream_t* handle)

如果流可读返回1,否则0。

int uv_is_writable(const uv_stream_t* handle)

如果流可写返回1,否则0。

int uv_stream_set_blocking(uv_stream_t* handle, int blocking)

启用或禁用流的阻塞模式。

当阻塞模式开启时所有的写都是同步完成的。 别的界面保持不变,比如操作完成或失败将仍然通过回调函数异步被报告。

警告

太依赖于这个API是不推荐的。 它可能在未来明显地变化。

当前在Windows上只工作于 uv_pipe_t 句柄。 在UNIX平台,所有的 uv_stream_t 句柄都被支持。

另外当前libuv当阻塞模式在已经提交写请求之后改变时没有作顺序保证。 因此推荐在打开或创建流之后立即设置阻塞模式。

在 1.4.0 版更改: 新增UNIX实现。

size_t uv_stream_get_write_queue_size(const uv_stream_t* stream)

返回 stream->write_queue_size

1.19.0 新版功能.

参见

uv_handle_t 的API函数也适用。