Сервер WebSocket просто получает "G" из заголовка рукопожатия, используя ssl - PullRequest
0 голосов
/ 02 февраля 2019

Я только начинаю понимать, как заставить сервер WebSocket (C #) использовать SSL.Я уже написал сервер, но без SSL с NetworkStream вместо SslStream и прочего.

Я скопировал этот сервер из интернета и переписал что-то:

class Program
{
    static X509Certificate2 serverCertificate = null;

    public static void RunServer(string certificate)
    {
        serverCertificate = new X509Certificate2();
        serverCertificate.Import(certificate, "password", X509KeyStorageFlags.DefaultKeySet | X509KeyStorageFlags.Exportable);

        TcpListener listener = new TcpListener(IPAddress.Any, 1111);
        listener.Start();
        while (true)
        {
            Console.WriteLine("Waiting for a client to connect...");

            TcpClient client = listener.AcceptTcpClient();
            ProcessClient(client);
        }
    }
    static void ProcessClient(TcpClient client)
    {
        SslStream sslStream = new SslStream(
            client.GetStream(), false);
        try
        {
            sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Default, true);

            sslStream.ReadTimeout = 5000;
            sslStream.WriteTimeout = 5000;

            Console.WriteLine("Waiting for client message...");
            string messageData = ReadMessage(sslStream);
            Console.WriteLine("Received: {0}", messageData);
        }
        catch (AuthenticationException e)
        {
            Console.WriteLine("Exception: {0}", e.Message);
            if (e.InnerException != null)
            {
                Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
            }
            Console.WriteLine("Authentication failed - closing the connection.");
            sslStream.Close();
            client.Close();
            return;
        }
        finally
        {
            sslStream.Close();
            client.Close();
        }
    }
    static string ReadMessage(SslStream sslStream)
    {
        byte[] buffer = new byte[570];
        StringBuilder messageData = new StringBuilder();
        int bytes = -1;

        bytes = sslStream.Read(buffer, 0, buffer.Length);

        Decoder decoder = Encoding.UTF8.GetDecoder();
        char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
        decoder.GetChars(buffer, 0, bytes, chars, 0);
        messageData.Append(chars);

        return messageData.ToString();
    }
    public static int Main(string[] args)
    {
        RunServer("server.pfx");
        return 0;
    }
}

И это мой клиент(HTML):

<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Websocket</title>
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    <script>
        var ws = new WebSocket("wss://localhost:1111");

        ws.onopen = function() {
            console.log("Connected!");
        };

        ws.onmessage = function (evt) {

        };

        ws.onclose = function() {

        };
    </script>
</head>
<body></body>
</html>

Проблема заключается в следующем: сервер не получает полный заголовок HTTP.Единственное, что в messageData в методе ReadMessage - это «G» (без кавычек).Я не получаю сообщение об ошибке или что-то еще, кроме того, что рукопожатие не удалось (Google Chrome).Также буфер [0] имеет значение 71 (ASCII для G), остальные 569 имеют значение 0. Кстати, длина буфера равна 570, потому что client.Available в цикле while выдает 570 повсюду.)

Я использую тот же клиент на сервере без SSL, единственное отличие: вместо wss: // Я использую ws: //

Может кто-нибудь помочь мне с этой проблемой?Я не совсем понимаю.

Кстати, я создал сертификат через PowerShell:

New-SelfSignedCertificate -CertStoreLocation Cert:\LocalMachine\My -DnsName "localhost" -FriendlyName "WebSocketCert" -NotAfter (Get-Date).AddYears(10)

1 Ответ

0 голосов
/ 02 февраля 2019

Решено!

Просто измените строку в ProcessClient с: sslStream.AuthenticateAsServer (serverCertificate, false, SslProtocols.Default, true);to: sslStream.AuthenticateAsServer (serverCertificate, false, SslProtocols.Tls12, true);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...