【问题标题】:Listen for additional requests on the same stream (TCPClient/SSLStream)?监听同一流(TCPClient/SSLStream)上的其他请求?
【发布时间】:2015-05-19 16:59:07
【问题描述】:

所以我有一个客户端服务器模型,它基于使用 TCPClient 的流并将其转换为 SSLStream 以用于安全目的,但每次客户端想要向服务器发送新内容时,它都会打开与服务器的新 TCP 连接当服务器结束连接时。我将如何监听来自同一流的其他请求?不知道如何,这就是为什么我要在最后杀死流。很抱歉,如果它令人困惑,如果不能理解,我可以修改。谢谢!

public void ServerListen()
{
TCPListener Server = new TCPListener(IPAddress.Any, 8001);
while (true)
{
Server.Start();
TCPClient TempClient = Server.AcceptTCPClient();
HandleRequest NewRequest = new HandleRequest(TempClient); // Send to a data handler class and open a separate thread to allow for additional clients to connect
}
}


public class HandleRequest
{

TCPClient WorkingClient;
public HandleRequest(TCPClient TempClient)
{
WorkingClient = TempClient;
(new Thread(new ThreadStart(DoWork))).Start();
}

public static void DoWork()
{
// Do Something Here With Data From Client
ProvideResponse(SomeData);
}

public static void ProvideResponse(object Data)
{
SSLStream SecureStream = new SSLStream(WorkingClient, false); // Kill inner stream after creating a secure connection
SecureStream.AuthenticateAsServer(MyCertificate, false, SslProtocols.Tls, true);
XmlSerializer XS = new XMLSerializer(typeof(someclass));
someclass TempObject = new someclass(){ InnerData = Data};
if (SecureStream.CanWrite)
{
XS.Serialize(SecureStream, TempObject);
}
SecureStream.Close();
}

}

【问题讨论】:

    标签: c# tcpclient sslstream


    【解决方案1】:

    SslStream 简单地环绕另一个 Stream。如果你打电话给AuthenticateAsServer(),另一方应该AuthenticateAsClient(),从那时起你就可以通过SSL进行通信了。如果任一方调用此方法失败,SslStream 将抛出异常。

    如果您关闭使用 leaveInnerStreamOpen 参数设置为 true 构造的 SslStream,然后您可以直接通过底层流进行通信,就好像从来没有 SslStream 一样(您甚至可以直接发送和接收到/来自底层流SslStream 仍然打开)。

    在 HTTPS 等典型场景中,客户端和服务器会在连接建立后立即启用 SSL,并在连接期间继续使用 SSL。没有什么能阻止您在请求/响应后关闭双方的SslStream,并为下一条消息重新创建一个 - 您只需要保持客户端和服务器之间的“ssl 状态”同步。

    至于你的评论:

    一旦建立 TCP 连接,只要双方保持连接,您就可以发送和接收数据。例如:

    TcpClient client = TcpListener.AcceptTcpClient();
    NetworkStream stream = client.GetStream();
    while (true)
    {
        int bytes = stream.Read(...);
        if (bytes == 0) 
        {
            // other side has disconnected
            stream.Close();
            break;
        }
    
        // add incoming data to buffer, process messages
        ...
    }
    

    这就像通过在一张纸上写文字来与某人交谈——你只需继续在同一张纸上写字,另一面可以在你写字的同时阅读。

    如果您在请求/响应后关闭 TcpClient 并使用 TcpListener.AcceptXxx() 打开一个新的,那么您在收到每条消息后都会丢弃每张纸。

    如果我是你,我会使用这些概念(使用 NetworkStream 类)没有 SslStream 包装器,直到你觉得你做对了。无需对使用NetworkStream 的代码进行任何重大更改即可添加SslStream 层。

    【讨论】:

    • 我确实觉得这很有帮助。因此,一旦我设置 SSLStream 并进行身份验证,保持内部流打开,TCPClient 就会使用底层 SSL 连接?如果是这种情况,一旦“ProvideResponse”方法完成,我将如何监听来自 TCPClient 的其他请求?
    • 您将使用NetworkStream stream = myTCPClient.GetStream(),并通过未加密的流进行通信,并从中创建SslStream
    • 对不起,也许我说错了。我可以创建 SSLStream(请参阅提供响应),但是一旦我这样做了,并完成了我需要的工作(发送响应),我如何通过 TCPClient 接受进一步的请求?会不会是类似于 TCPListener While (WorkingClient.Connect) { // do work } 的东西?
    • 给我留下了一些关于使用 XMLSerializer 的问题,但这可能是一个完全不同的问题,我认为你已经恰当地回答了我实际提出的问题,或者至少给了我一些好的方向和见解。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2019-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-11
    • 2020-09-22
    • 1970-01-01
    相关资源
    最近更新 更多