OpenSSL SSL_read non-blocking 非阻塞编程问题
clq
浏览(632) -
2018-02-08 16:05:05 发表
编辑
关键字: openssl
[2024-07-18 23:41:32 最后更新]
OpenSSL SSL_read non-blocking 非阻塞编程问题 2008-02-26 16:26:40
http://blog.chinaunix.net/uid-29846-id-2133948.html
分类:
因为在用SSL_read()的时候碰到过一些问题,现在总结一下。
环境:wince5.0 evc++4.0 OpenSSL0.9.8g CDMA连接
问题:CDMA连接建立后空闲一段时间后(一般4-5分钟),该连接就不能用了。要重新建立连接收发数据。
但SSL_read()是阻塞方式,所以要等很长时间才返回(大概10分钟),用网线连接没有问题,用CDMA\GPRS连接才会有这个问题。
解决办法:
虽然不知道引起这个问题的原因,还是找到一个办法让SSL_read()能快点返回。直到超时。
在OpenSSL的帮助文档中查看关于SSL_read()的使用上提到了,可以用非阻赛方式来解决。
1、用ioctlsocket设置socket为非阻塞方式。注意,OpenSSL握手之前不能设置为非阻塞方式。否则握手失败。
注意,sockfd是普通的socket句柄。不是SSL socket句柄。
int CTermSocket::SetSocketOpt(int sockfd, BOOL bBlock)
{
unsigned long ul = bBlock ? 0 : 1;
int nRenCtl = ioctlsocket(sockfd, FIONBIO, (unsigned long*)&ul);
if (nRenCtl)
{
nRenCtl = WSAGetLastError();
return nRenCtl;
}
return nRenCtl;
}
2、接收数据:
接收数据的函数中,因为socket是非阻塞的方式,所以SSL_read()会立即返回,注意要判断错误码。
如果是SSL_ERROR_WANT_READ,则要重新接收数据。
OpenSSL文档中提到了要使用Select,我试过了,用Select来,前几次接收数据可以成功,但几次后就失败了,Select一直返回零,不知道是什么原因。
虽然用非阻塞方式可以解决SSL_read()返回时间长的问题,但还是不知道socket连接为什么不能用。
int CTermSocket::ssl_recv(char *buf, int len, int flags)
{
int res, count = 0;
DWORD dwTick = ::GetTickCount();
if(!m_sslSock)
{
return SOCKET_ERROR;
}
while(count < len)
{
if(::GetTickCount() - dwTick > (DWORD)m_timeout)
{
m_strErr.LoadString(IDS_ERR_RECV_TIMEOUT);
return SOCKET_ERROR;
}
::Sleep(10);
DoEvents();
res = SSL_read(m_sslSock, buf, len - count);
int nRes = SSL_get_error(m_sslSock, res);
if(nRes == SSL_ERROR_NONE)
{
if(res > 0)
{
count += res;
dwTick = ::GetTickCount();
}
}
else if (nRes == SSL_ERROR_WANT_READ)
{
continue;
}
else
{
m_strErr.Format(IDS_ERR_RECIEVE_FAILED, nRes);
count = SOCKET_ERROR;
break;
}
}
return count;
}
3、发送数据:
发送数据可接收数据查不多
int CTermSocket::ssl_send(const char *buf, int len, int flags)
{
int res, count = 0;
DWORD dwTick = ::GetTickCount();
if(!m_sslSock)
{
return SOCKET_ERROR;
}
while(count < len)
{
if(::GetTickCount() - dwTick > (DWORD)m_timeout)
{
m_strErr.LoadString(IDS_ERR_SEND_TIMEOUT);
return SOCKET_ERROR;
}
::Sleep(10);
DoEvents();
res = SSL_write(m_sslSock, buf, len - count);
int nRes = SSL_get_error(m_sslSock, res);
if(nRes == SSL_ERROR_NONE)
{
if(res > 0)
{
count += res;
dwTick = ::GetTickCount();
}
}
else if (nRes == SSL_ERROR_WANT_WRITE)
{
continue;
}
else
{
m_strErr.Format(IDS_ERR_SEND_FAILED, nRes);
count = SOCKET_ERROR;
break;
}
}
return count;
}
希望有哪位知道连接失效问题的请告诉我一声,谢谢
阅读(23152) | 评论(3) | 转发(0) |
1
上一篇:asdm的安装和配置
下一篇:经典网络词典
给主人留下些什么吧!~~
hljwsf2014-11-20 11:22:28
调用ssl_connect之前,可以把socket设置成非阻塞的。
while(1)
{
error = SSL_connect (ssl);
if(error > 0)
{
std::cout<<"SSL_Connect success\n";
return error;
}
std::cout<<"SSL_Connect fail\n";
select(0,NULL,NULL,NULL,&tv);
{
ret = SSL_get_error(ssl,error);
switch(ret)
&
回复 | 举报
chinaunix网友2008-08-07 16:58:03
POST表单以后,服务器肯定要你保存COOKIE来保存登录状态的,你必须把上一次的COOKIE信息在HTTP头部再发回去
回复 | 举报
nkloverene2008-03-20 13:48:56
不知道您的连接失效问题解决了么 我刚开始看openssl,在win32下模拟登陆https服务器,然后post一个表单,但是我登陆服务器成功后,再post表单,返回的是session过期的提示页面。 不知道这个是怎么回事呢,望不吝赐教~
NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.