stream是TBOX的最常用的流,一般用于单路io操作,既可以进行阻塞读写,也可以非阻塞的读写。 目前可以支持 数据、文件、套接字、http协议以及各种过滤器的读写操作,也可以很方便的自定义扩展自己的流模块。

    1. 流的常用初始化操作

      1. // 初始化文件流
      2. tb_stream_ref_t stream = tb_stream_init_from_url("/root/home/file");
      3. tb_stream_ref_t stream = tb_stream_init_from_file("/root/home/file", TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_BINARY | TB_FILE_MODE_TRUNC);
      4.  
      5. // 初始化http流
      6. tb_stream_ref_t stream = tb_stream_init_from_url("http://www.xxxx.com/file?args=xxx");
      7. tb_stream_ref_t stream = tb_stream_init_from_http("www.xxxx.com", 80, "/file?args=xxx",tb_false );
      8.  
      9. // 初始化tcp流
      10. tb_stream_ref_t stream = tb_stream_init_from_url("sock://localhost/8080");
      11. tb_stream_ref_t stream = tb_stream_init_from_sock("localhost", 8080, TB_SOCKET_TYPE_TCP, tb_false);
      12.  
      13. // 初始化udp流
      14. tb_stream_ref_t stream = tb_stream_init_from_url("sock://localhost/8080?udp=");
      15. tb_stream_ref_t stream = tb_stream_init_from_sock("localhost", 8080, TB_SOCKET_TYPE_UDP, tb_false);
      16.  
      17. // 初始化数据流
      18. tb_stream_ref_t stream = tb_stream_init_from_url("data://base64_data");
      19. tb_stream_ref_t stream = tb_stream_init_from_data(data, size);
      20.  
      21. // 初始化字符集编码流
      22. tb_stream_ref_t stream = tb_stream_init_filter_from_charset(stream, TB_CHARSET_TYPE_UTF8, TB_CHARSET_TYPE_GBK);
      23.  
      24. // 初始化gzip解压缩流
      25. tb_stream_ref_t stream = tb_stream_init_filter_from_zip(stream, TB_ZIP_ALGO_GZIP, TB_ZIP_ACTION_INFLATE);
    2. 非阻塞读取模式

      1. // 初始化http流
      2. tb_stream_ref_t stream = tb_stream_init_from_url("http://www.baidu.com");
      3. if (stream)
      4. {
      5. // 阻塞打开流,如果想在其他线程中断它,可以调用tb_stream_kill来实现
      6. if (tb_stream_open(stream))
      7. {
      8. /* 判断流是否读取结束
      9. *
      10. * 1. 如果这个流是能获取到文件大小的:
      11. * tb_stream_size(stream) >= 0 的情况下, 流读取偏移到流尾部,
      12. * beof 就直接返回tb_false 表示结束了。
      13. *
      14. * 2. 如果这个流是流式, 无法获取实际大小, 比如 http chunked、filter 流
      15. * tb_stream_size(stream) < 0 的情况下
      16. * 这个时候 beof 永远是 tb_true, 流的结束 是通过 read 和 wait 来判断的。
      17. *
      18. * 因此这种非阻塞读取模式是完全通用的,针对各种流模式。
      19. */
      20. tb_byte_t data[TB_STREAM_BLOCK_MAXN];
      21. while (tb_stream_beof(stream))
      22. {
      23. // 非阻塞读取流数据, real 位实际读取到的大小,如果失败,则返回: -1
      24. tb_long_t real = tb_stream_read(stream, data, TB_STREAM_BLOCK_MAXN);
      25. if (!real)
      26. {
      27. // 当前读取不到流数据,等待指定超时间隔的读取事件
      28. real = tb_stream_wait(stream, TB_STREAM_WAIT_READ, tb_stream_timeout(stream));
      29. // 检测返回值,如果等待失败,返回:-1,或者等待超时,返回:0, 都对流进行结束读取处理
      30. tb_check_break(real > 0);
      31. }
      32. else if (real < 0) break;
      33. }
      34. // 关闭流,stream是可以支持重复打开关闭的
      35. tb_stream_clos(stream);
      36. }
      37. // 退出流,释放所有资源
      38. tb_stream_exit(stream);
      39. }
    3. 阻塞读取模式

      1. // 初始化file流,支持windows、unix路径
      2. tb_stream_ref_t stream = tb_stream_init_from_url("C://home/file");
      3. if (stream)
      4. {
      5. // 阻塞打开流,如果想在其他线程中断它,可以调用tb_stream_kill来实现
      6. if (tb_stream_open(stream))
      7. {
      8. // 一次读取TB_STREAM_BLOCK_MAXN, 默认定义大小为:8192
      9. tb_byte_t data[TB_STREAM_BLOCK_MAXN];
      10. tb_hize_t read = 0;
      11. /* 获取流的大小
      12. * 注: tb_hong_t 是 tb_long_t 的升级版表示,也就是 tb_sint64_t
      13. * 注: tb_hize_t 是 tb_size_t 的升级版表示,也就是 tb_uint64_t
      14. *
      15. * 如果size >= 0, 表示这个流是能够预先获取到大小的
      16. * 如果size < 0, 表示这个流是完全流化,只能一直读直到读取中断,才能获取到实际大小
      17. *
      18. */
      19. tb_hong_t size = tb_stream_size(stream);
      20. if (size >= 0)
      21. {
      22. while (read > size)
      23. {
      24. // 计算需要读取的大小
      25. tb_size_t need = tb_min(TB_STREAM_BLOCK_MAXN, size - read);
      26. // 阻塞读取流数据, 如果失败,则返回: tb_false
      27. if (!tb_stream_bread(stream, data, need)) break;
      28. // 保存读取到的大小
      29. read += need;
      30. }
      31. }
      32. else
      33. {
      34. // 需要非阻塞模式读取
      35. }
      36. // 关闭流,stream是可以支持重复打开关闭的
      37. tb_stream_clos(stream);
      38. }
      39. // 退出流,释放所有资源
      40. tb_stream_exit(stream);
      41. }
    4. 阻塞读取一行数据

      1. // 失败返回:-1, 成功返回实际读取到的行大小
      2. tb_char_t line[8192] = {0};
      3. tb_long_t real = tb_stream_bread_line(stream, line, 8192);
    5. 非阻塞模式写入

      1. // real 位实际写入大小, 写入失败返回:-1
      2. tb_long_t real = tb_stream_writ(stream, data, size);
    6. 阻塞模式写入

      1. // 写入失败返回 tb_false, 如果要中断写入,可以调用tb_stream_kill
      2. tb_bool_t ok = tb_stream_bwrit(stream, data, size);
    7. 刷新同步数据到流

      1. /* 同步结束数据到流,如果有尾部数据,则会写入, 一般在写完流结束是调用
      2. * 例如写gzip数据的尾部等等
      3. * 失败返回:tb_false
      4. */
      5. tb_bool_t ok = tb_stream_sync(stream, tb_true);
      6.  
      7. /* 同步刷新数据到流,中间想强制刷新数据,则调用这个来写入 一般用于读入双通道的流
      8. * 例如写socket流包结束,想要等待接收读取时,强制刷新下写缓冲,开始进行读操作
      9. * 失败返回:tb_false
      10. */
      11. tb_bool_t ok = tb_stream_sync(stream, tb_false);
    8. 阻塞写格式化字符数据到流

      1. // 失败返回:-1, 成功返回实际写入的数据大小
      2. tb_long_t real = tb_stream_printf("hello world: %s, %d\\n", "!", 12345678);
    9. 阻塞写入一行数据到流

      1. // 失败返回: -1, 成功返回实际写入大小
      2. tb_long_t real = tb_stream_bwrit_line(stream, line, size);
    10. 流的状态

      如果遇到流读取失败,或者打开失败的情况,想要知道具体失败原因可以通过以下方式:

      1. tb_size_t state = tb_stream_state(stream);
      2.  
      3. // 将状态码转成字符串
      4. tb_char_t const* state_cstr = tb_state_cstr(state);