SSL_shutdown 关闭连接

当我们完成响应的传送,我们需要发送一个close_notify。如前所述,这是通过SSL_shutdown()完成的。不幸的是,当server先关闭时事情会有一些麻烦,我们第一次调用SSL_shutdown()时发送了close_notify但是另一端却没有处理它。因此,它会立刻返回一个0,表明关闭动作并没有完成。这样的话,程序就必须再次调用SSL_shutdown()。

这里可能会有两种看法:

1. 我们已经得到了我们关心的所有HTTP请求。我们不在关心其他的任何事情。因此,我们不关心client是否发送了close_notify。

2. 我们严格遵守协议,并且希望其他人也如此。所以,我们需要一个close_notify。

如果我们拥有第一种态度,那么就简单多了:我们调用SSL_shutdown()发送close_notify然后立刻退出,不管client是否发送了close_notify。如果我们抱着第二种态度,那么事情就会变得复杂得多,因为client经常表现的不正常。

我们面对的第一个问题是通常client不发送close_notify。事实上,一些client在他们读取了整个HTTP回应后立刻关闭连接(一些版本的IE正是如此)。当我们发送close_notify,另一端会发送一个TCP_RST字段,这时程序会捕捉到SIGPIPE。我们在initialize_ctx()中安装一个假的SIGPIPE句柄来避免这种情况的发生。

我们面对的第二个问题是client可能不会立刻发送close_notify以回应我们发出的close_notify。一些版本的Netscape要求你先发送一个TCP FIN。因此,我们在第二次调用SSL_shutdown()之前调用shutdown(s,1)。当把“how”这个参数设置为1后,shutdown()会发送FIN并且不关闭socket。server端的shutdown如下:

r=SSL_shutdown(ssl);
if(!r){
/* If we called SSL_shutdown() first then
we always get return value of ’0’. In
this case, try again, but first send a
TCP FIN to trigger the other side’s
close_notify*/
shutdown(s,1);
r=SSL_shutdown(ssl);
}

switch(r){
case 1:
break; /* Success */
case 0:
case -1:
default:
berr_exit("Shutdown failed");
}

你可能感兴趣的:(网络杂谈)