关键词搜索

源码搜索 ×
×

Blocking sockets的读写操作该怎么玩?

发布2022-06-26浏览402次

详情内容

Blocking sockets的读写操作,我参考了redis源码,然后做了修改,用起来舒服:

  1. /* ----------------- Blocking sockets I/O with timeouts --------------------- */
  2. /* Redis performs most of the I/O in a nonblocking way, with the exception
  3. * of the SYNC command where the slave does it in a blocking way, and
  4. * the MIGRATE command that must be blocking in order to be atomic from the
  5. * point of view of the two instances (one migrating the key and one receiving
  6. * the key). This is why need the following blocking I/O functions.
  7. *
  8. * All the functions take the timeout in milliseconds. */
  9. #define SYNCIO__RESOLUTION 10 /* Resolution in milliseconds */
  10. /* Write the specified payload to 'fd'. If writing the whole payload will be
  11. * done within 'timeout' milliseconds the operation succeeds and 'size' is
  12. * returned. Otherwise the operation fails, -1 is returned, and an unspecified
  13. * partial write could be performed against the file descriptor. */
  14. ssize_t syncWrite(int fd, char *ptr, ssize_t size, long long timeout) {
  15. ssize_t nwritten, ret = size;
  16. long long start = mstime();
  17. long long remaining = timeout;
  18. while(1) {
  19. long long wait = (remaining > SYNCIO__RESOLUTION) ?
  20. remaining : SYNCIO__RESOLUTION;
  21. long long elapsed;
  22. /* Optimistically try to write before checking if the file descriptor
  23. * is actually writable. At worst we get EAGAIN. */
  24. nwritten = write(fd,ptr,size);
  25. if (nwritten == -1) {
  26. if (errno != EAGAIN) return -1;
  27. } else {
  28. ptr += nwritten;
  29. size -= nwritten;
  30. }
  31. if (size == 0) return ret;
  32. /* Wait */
  33. aeWait(fd,AE_WRITABLE,wait);
  34. elapsed = mstime() - start;
  35. if (elapsed >= timeout) {
  36. errno = ETIMEDOUT;
  37. return -1;
  38. }
  39. remaining = timeout - elapsed;
  40. }
  41. }
  42. /* Read the specified amount of bytes from 'fd'. If all the bytes are read
  43. * within 'timeout' milliseconds the operation succeed and 'size' is returned.
  44. * Otherwise the operation fails, -1 is returned, and an unspecified amount of
  45. * data could be read from the file descriptor. */
  46. ssize_t syncRead(int fd, char *ptr, ssize_t size, long long timeout) {
  47. ssize_t nread, totread = 0;
  48. long long start = mstime();
  49. long long remaining = timeout;
  50. if (size == 0) return 0;
  51. while(1) {
  52. long long wait = (remaining > SYNCIO__RESOLUTION) ?
  53. remaining : SYNCIO__RESOLUTION;
  54. long long elapsed;
  55. /* Optimistically try to read before checking if the file descriptor
  56. * is actually readable. At worst we get EAGAIN. */
  57. nread = read(fd,ptr,size);
  58. if (nread == 0) return -1; /* short read. */
  59. if (nread == -1) {
  60. if (errno != EAGAIN) return -1;
  61. } else {
  62. ptr += nread;
  63. size -= nread;
  64. totread += nread;
  65. }
  66. if (size == 0) return totread;
  67. /* Wait */
  68. aeWait(fd,AE_READABLE,wait);
  69. elapsed = mstime() - start;
  70. if (elapsed >= timeout) {
  71. errno = ETIMEDOUT;
  72. return -1;
  73. }
  74. remaining = timeout - elapsed;
  75. }
  76. }
  77. /* Read a line making sure that every char will not require more than 'timeout'
  78. * milliseconds to be read.
  79. *
  80. * On success the number of bytes read is returned, otherwise -1.
  81. * On success the string is always correctly terminated with a 0 byte. */
  82. ssize_t syncReadLine(int fd, char *ptr, ssize_t size, long long timeout) {
  83. ssize_t nread = 0;
  84. size--;
  85. while(size) {
  86. char c;
  87. if (syncRead(fd,&c,1,timeout) == -1) return -1;
  88. if (c == '\n') {
  89. *ptr = '\0';
  90. if (nread && *(ptr-1) == '\r') *(ptr-1) = '\0';
  91. return nread;
  92. } else {
  93. *ptr++ = c;
  94. *ptr = '\0';
  95. nread++;
  96. }
  97. size--;
  98. }
  99. return nread;
  100. }

比较常规的操作。

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载