我正在尝试使用.net SslStream对tls隧道进行初始化,但在打开流之后我总是收到以下错误:
“无法从传输连接中读取数据:已建立的连接已被主机中的软件中止。”
建立tls连接后和发送第二条消息后。
过去四天我一直在寻找答案,但网上没有任何有用的信息!
编辑: 我正在尝试连接到talk.google.com
我正在使用MSDN的代码示例。唯一的区别是我在使用tls之前和之后发送数据我执行以下操作:
public void SecureStream()
{
netStream.Flush();
sslStream = new SslStream(netStream, false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
sslStream.AuthenticateAsClient("talk.google.com");}
编辑:我设法消除了第一个错误(关于我如何处理发送的小错误)现在我总是得到
“无法从传输连接中读取数据:已建立的连接已被主机中的软件中止。”
edit2:我没有发送任何空格我重写了消息传递部分,我仍然有同样的问题。
我从
开始 String streamInit = "<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='google.com' version='1.0'>";
client.Send(streamInit);
然后在接收时我有以下
static void client_MessageReceived(SyncronousClient source, string Result)
{
if (Regex.IsMatch(Result, "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"><required/></starttls>"))
{
String startTlS = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>";
source.Send(startTlS);
}
else if (Regex.IsMatch(Result, "<proceed xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>"))
{
//Do TLS Magic
source.SecureStream();
String streamReInit = "<stream:stream xmlns='jabber:client'xmlns:stream='http://etherx.jabber.org/streams'to='google.com'version='1.0'>";
source.Send(streamReInit);
}
else if (Regex.IsMatch(Result, "<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"))
{
//String AuthType = "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='X-GOOGLE-TOKEN'/>";
String AuthType = "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"PLAIN\"/>";
source.Send(AuthType);
}}
答案 0 :(得分:1)
这不太可能是您的问题(除非.Net已经开始在SNI下开展),但是当您调用AuthenticateAsClient时,请传入您在流中使用的相同域名(在这种情况下,{{1 }})。同样,您可能需要google.com
而不是gmail.com
:
google.com
正如csharptest.net所提到的,请确保您没有发送额外空格的keepalive计时器,或等待TLS工作之后启动计时器。唯一可以想象你得到错误的另一种方法是,如果你没有服务器实现的密码套件,但我知道.Net SslStream可以对抗GTalk。
最后,使用现有的.Net库之一进行XMPP( 5 列出here),您可以立即开始编写更多有趣的代码。您将要遇到.Net XML系统的不足之处,当您在单次读取中开始获取部分节或多个节时,基于正则表达式的方法将无法正常工作。
答案 1 :(得分:0)
这对我来说真的没有意义。服务器(如果使用SSL)要求客户端在连接时执行SSL握手。因此,我不确定你的意思是“我之前发送数据......”。听起来你没有立即调用AuthenticateAsClient。如果是这种情况,我怀疑这是你的问题。 AFAIK,您不能对SSL和非SSL通信使用相同的套接字/连接连接。服务器需要SSL,或者它不支持SSL,它不应该同时执行这两种操作。
我之前的回答是无知的。实际上,似乎标准确实要求在SSL握手初始化之前连接发送和接收数据。真奇怪他们会这样做......但无论如何。在简要阅读parts of the RFC之后,似乎您应该在结束'&gt;'后立即开始SSL客户端身份验证。没有允许的尾随空格可能是你的问题吗?