最近测试广州电信的电话会议平台,该平台接入采用HTTPS协议,于是有了本文。09年培训时写过一个简单的TLS C/S结构交互,采用openssl的ssl相关接口,但与生产相去胜远。本文采用openssl提供的BIO。

长链接还是短链接?

测试过程中发现长连接在一段时间内没有数据交互会被服务方释放,无法重新连接。根据自身业务选择。

BIO设置为阻塞还是非阻塞?

本场景下都为http同步请求,故设置为阻塞。代码实现时必须考虑阻塞的等待时间(测试结果是默认阻塞BIO为60s超时)对性能和业务的影响。

读写出错控制

如果写出错,需要校验BIO_should_retry,如果为true,需等待片刻后重新写,阻塞的BIO一般不会出现;

如果读出错,同样要校验BIO_should_retry,非阻塞的BIO可能会影响性能。

相关头文件:

#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
/* Initializing OpenSSL */
SSL_library_init();
SSL_load_error_strings();
ERR_load_BIO_strings();
OpenSSL_add_all_algorithms(); SSL_CTX *m_ctx =SSL_CTX_new(SSLv23_client_method());
if (m_ctx == NULL)
{
exit(1);
}
//加载pem 该pem是openssl源码库里自带的
if(! SSL_CTX_load_verify_locations(m_ctx, "./certs/demo/ca-cert.pem", NULL))
{
exit(1);
}

下面四个函数封装了BIO的创建、释放、读和写,可以满足基本的需求了。


BIO *
bio_new ()
{
  SSL *ssl;
  BIO *bio = BIO_new_ssl_connect (m_ctx);
  BIO_get_ssl (bio, &amp;
           ssl);
  if (!ssl)
    {
      BIO_free_all (bio);
      return NULL;
    }
  SSL_set_mode (ssl, SSL_MODE_AUTO_RETRY);    //自动重试
  BIO_set_conn_hostname (bio, "xxx.com:443");
  if (BIO_do_connect (bio) & lt; = 0)
    {
      BIO_free_all (bio);
      return NULL;
    } //校验失败是非致命的
  if (SSL_get_verify_result (ssl) != X509_V_OK)
    {
      /* Handle the failed verification */
    }   if (BIO_do_handshake (bio) & lt; = 0)
    {                //ssl握手
      BIO_free_all (bio);
      return NULL;
    }
  return bio;
} int
bio_write (BIO * bio, const char *buf, int len)
{
  if (buf == NULL)
    {
      return PROC_FAILED;
    }
  if (BIO_write (bio, buf, len) & lt; = 0)
    {
      if (!BIO_should_retry (bio))
    {
/* Handle failed write here */
      return PROC_FAILED;
    }
/* Do something to handle the retry */
      return PROC_FAILED;
    }
  return PROC_SUCCESS;
} int
bio_read (BIO * bio, char *buf, int len)
{
  if (buf == NULL)
    {
      return PROC_FAILED;
    }
  int x = BIO_read (bio, buf, len);
  if (x == 0)
    {
/* Handle closed connection */
      return PROC_FAILED;
    }
  else if (x & lt; 0)
    {
      if (!BIO_should_retry (bio))
    {
/* Handle failed read here */
      return PROC_FAILED;
    }
/* Do something to handle the retry */
      return PROC_FAILED;
    }
  return x;
} int
bio_close (BIO * bio)
{
  if (bio != NULL)
    BIO_free_all (bio);
  return PROC_SUCCESS;
} BIO * bio = bio_new ();
if (bio == NULL)
  {
    return PROC_FAILED;
  } //发送数据
if (bio_write (bio, buff, strlen (buff)) == PROC_FAILED)
  {
    bio_close (bio);
    return PROC_FAILED;
  } char response[8192] = { 0x00 }; int len = 0; //接收数据 if ((len = bio_read (bio, response, 8192)) == PROC_FAILED)
  {
    bio_close (bio);
    return PROC_FAILED;
  }
bio_close (bio);

参考资料:

https://www.openssl.org/docs/crypto/BIO_f_ssl.html

https://www.openssl.org/docs/crypto/BIO_should_retry.html

另:BIO也很多种类型,感觉功能很强大,本人c++菜鸟,没仔细研究...

最新文章

  1. ZooKeeper1 利用虚拟机搭建自己的ZooKeeper集群
  2. iOS NSArray数组过滤
  3. AspNet MVC中各种上下文理解
  4. PHP开发网站之微信登录、绑定
  5. java中的transient关键词
  6. mysql批量更新
  7. git push origin master、git pull出现如下错误
  8. ajax全局函数运用
  9. 在CentOS 7 / Gnome 3 双屏时设置主屏
  10. [原创]安全系列之端口敲门服务(Port Knocking for Ubuntu 14.04 Server)
  11. AC 自动机 模板
  12. 通用的C#导出Excel 支持2003及2007以上版本
  13. Hack Programming
  14. Flask 中关于‘蓝图’ 的使用-------------------
  15. 【C/C++】实现数据结构广义表
  16. Sitecore标准模板字段
  17. Linux QtCreator 编译报错:No rule to make target &#39;.../***&#39; needed by &#39;***.o&#39;.stop
  18. 修改Eclipse主题与Eclipse中使用SVN
  19. Springboot 编码规范
  20. shell获取函数的返回值

热门文章

  1. linux常用文本编缉命令(strings/sed/awk/cut)
  2. Kali配置教程
  3. python列表反转函数
  4. android apk瘦身
  5. vs2015 出现Lc.exe 已退出,代码为-1的问题,如何解决
  6. MySQL(二) MySQL基本操作
  7. Win10系列:UWP界面布局基础6
  8. DFS----Lake Counting (poj 2386)
  9. 怎样在Ubuntu 14.04中安装Java(转)
  10. SQLServer查询当前数据库所有索引及统计,并使用游标批量删除