如何检测通过TLS安全套接字发送数据的尝试失败?
本文关键字:数据 套接字 失败 安全套 安全 何检测 检测 TLS | 更新日期: 2023-09-27 18:09:41
这个示例应用程序通过TLS安全套接字创建一个客户端-服务器连接,并通过它发送一些数据:
static void Main(string[] args)
{
try
{
var listenerThread = new Thread(ListenerThreadEntry);
listenerThread.Start();
Thread.Sleep(TimeSpan.FromSeconds(1));
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
socket.Connect("localhost", Port);
var rawStream = new NetworkStream(socket);
using (var sslStream = new SslStream(rawStream, false, VerifyServerCertificate))
{
var certificate = new X509Certificate(CertsPath + @"test.cer");
var certificates = new X509CertificateCollection(new[] { certificate });
sslStream.AuthenticateAsClient("localhost", certificates, SslProtocols.Tls, false);
using (var writer = new StreamWriter(sslStream))
{
writer.WriteLine("TEST");
writer.Flush();
Thread.Sleep(TimeSpan.FromSeconds(10));
}
}
socket.Shutdown(SocketShutdown.Both);
socket.Disconnect(false);
Console.WriteLine("Success! Well, not really.");
}
catch (Exception exc)
{
Console.WriteLine(exc);
}
}
private static bool VerifyServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}
static void ListenerThreadEntry()
{
try
{
var listener = new TcpListener(IPAddress.Any, Port);
listener.Start();
var client = listener.AcceptTcpClient();
var serverCertificate = new X509Certificate2(CertsPath + @"'test.pfx");
var sslStream = new SslStream(client.GetStream(), false);
sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Tls, false);
client.Close(); // terminate the connection
using (var reader = new StreamReader(sslStream))
{
var line = reader.ReadLine();
Console.WriteLine("> " + line);
}
}
catch (Exception exc)
{
Console.WriteLine(exc);
}
}
诀窍是在握手后立即从服务器端终止连接。问题是客户端对此一无所知;我希望客户端在试图通过关闭的连接发送数据时引发异常,但它没有。
因此,问题是:当连接中断并且数据没有真正到达服务器时,我如何检测这种情况?
不可能知道在TCP模型下哪些数据包已经到达。TCP是一个面向流的协议,而不是面向包的协议;也就是说,它的行为就像一个双向管道。如果你写7个字节,然后写5个字节,有可能另一端一次只得到12个字节。更糟糕的是,TCP的可靠交付只保证如果数据到达,它将以正确的顺序进行,而不会重复或重新排列,如果数据没有到达,则将重新发送。
如果连接意外断开,TCP不能保证您确切地知道丢失了哪些数据,也不能合理地提供该信息。客户端唯一知道的是"我从来没有收到字节数N的确认[大概也没有收到前N个字节的确认],尽管它们被重发了很多次。"这些信息不足以确定字节N(以及其他丢失的字节)是否到达服务器。有可能它们确实到达了,但在服务器能够确认它们之前,连接就断开了。也有可能他们根本就没有到达。TCP不能向您提供此信息,因为只有服务器知道它,而您已不再连接到服务器。
现在,如果您正确关闭套接字,使用shutdown(2)
或. net等效,则飞行中的数据将尽可能通过,并且另一端将及时出错。一般来说,我们尝试确保双方都同意何时关闭连接。在HTTP中,使用Connection: Close
头,在FTP中使用BYE
命令,依此类推。如果一方意外关闭,它仍然可能导致数据丢失,因为关闭通常不会等待确认。