HTTP/1.1,Select 与 SSL_read

要写一个简单的WebSocket客户端,在写的过程中手贱于是重写了所有的Socket,TCP,SSL和HTTP的代码。因为原来的HTTP只是一个简单的HTTP/1.0的客户端,为了让能给WebSocket使用,决定对HTTP/1.1进行有限的支持。

在开发HTTP/1.1的时候遇到一个问题:Request发送出去之后,迟迟收不到Response。查找了半天发现因为WebSocket是一个长连接和原来的HTTP/1.0的一锤子买卖不一样。原有的处理逻辑是一直read,直到Socket连接断开就可以了。但是对于一个长连接来说这种处理方法显然是不合适的。

借鉴了很多的HTTP Client的代码,后来选择在recv的过程中就把HTTP Response给处理了,对Header以及Content进行分别处理。然后发现可以一次recv一个Byte,这样处理起来很方便,而且逻辑很顺畅。

前面已经测试完毕了,但是挂到环境里一测试又出问题了,还是Response收不到。原因是Select和SSL_read不太兼容导致的。代码中为了能加入timeout,所以在所有读写之前都进行了Select:

   int ret = select (....);
   if (ret > 0) {
     SSL_read(...)/SSL_write(...)/ recv(...)/ send(...);
   }

这里有一个问题,因为每一次都只收1 byte。在之前测试时用的是recv,没有问题。但是在用SSL_read的时候,再进行select就会超时。想了半天,可能是SSL_read会一次把Tcp的Buffer读进来,从而导致下次select的时候可能没有数据了,也就超时了。实际测试发现这个猜测是对的。怎么办呢?解决方案是请SSL_pending出马,这个函数可以检测目标SSL中到底有多少可读数据。那么在Select之前先用它来做一次测试,这样就解决了有数据却读不出来的问题。最后贴上真实的代码,以备后用。

int Tls::recv(char * buf, int len) {
    if (ssl == NULL) {
        return Socket::recv(buf, len);
    }

    if (buf == NULL || len <= 0) {
        err = ERR_PARAM_NULL;
        return -1;
    }

    int pending = SSL_pending(ssl);
    if (pending <= 0) {
        if (!blocking) {
            if (waitReadable(timeout) < 0) {
                return -1;
            }
        }
    }

    if (pending > 0 && len > pending) {
        len = pending;
    }

    int ret = SSL_read(ssl, buf, len);
    if (ret <= 0) {
        sslerr = SSL_get_error(ssl, ret);
        if (sslerr == SSL_ERROR_WANT_READ) {
            err = ERR_TLS_WANT_READ;
        }
    }

    return ret;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,948评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,766评论 18 399
  • 本文依照 知识共享许可协议(署名-非商业性使用-禁止演绎) 发布。 编写HTTP 服务器与客户端 Vert.x让编...
    半枚荔枝阅读 3,988评论 0 5
  • 昨晚睡前没忍住看了S6E5的冰与火之歌,于是很晚才睡。 上午9点起床收拾下就去银行办事,银行通知要去更换公司的印鉴...
    ab3253a39004阅读 508评论 0 50
  • 每天早晨眼一睁 她就“咚咚咚”下楼 热开水泡杯破壁灵芝孢子粉 端至丈夫床头 “头仰起来喝,才能喝的干净” 她每天都...
    龙青阅读 412评论 2 1