Tworzenie przykładu WebSocket „Hello World”

85

Nie rozumiem, dlaczego nie mogę uruchomić następującego kodu. Chcę połączyć się za pomocą JavaScript z moją aplikacją konsoli serwera. A następnie wyślij dane na serwer.

Oto kod serwera:

    static void Main(string[] args)
    {            
        TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 9998);
        server.Start();
        var client = server.AcceptTcpClient();
        var stream = client.GetStream();

        while (true)
        {
            var buffer = new byte[1024]; 
            // wait for data to be received
            var bytesRead = stream.Read(buffer, 0, buffer.Length);                
            var r = System.Text.Encoding.UTF8.GetString(buffer);
            // write received data to the console
            Console.WriteLine(r.Substring(0, bytesRead));
        }
    }

a oto JavaScript:

        var ws = new WebSocket("ws://localhost:9998/service");
        ws.onopen = function () {
            ws.send("Hello World"); // I WANT TO SEND THIS MESSAGE TO THE SERVER!!!!!!!!
        };

        ws.onmessage = function (evt) {
            var received_msg = evt.data;
            alert("Message is received...");
        };
        ws.onclose = function () {
            // websocket is closed.
            alert("Connection is closed...");
        };

Kiedy uruchamiam ten kod, dzieje się tak:

Zauważ, że kiedy uruchamiam JavaScript, serwer akceptuje i pomyślnie nawiązuje połączenie. JavaScript nie jest jednak w stanie przesyłać danych. Za każdym razem, gdy umieszczam metodę wysyłania, nie będzie ona wysyłana, mimo że zostanie nawiązane połączenie. Jak mogę to zrobić?

Tono Nam
źródło
9
To „pytanie” nie wydaje się już być pytaniem, a zatem nie pasuje do formatu StackOverflow. FWIW, wiadomość klienta nie jest szyfrowana , jest maskowana (zaciemniana) przez XOR względem losowej wartości, która jest przesyłana jako część ramki. Ten szczegół protokołu istnieje, aby uniknąć ataków zatrucia na serwery proxy, które mogą źle zrozumieć ruch.
EricLaw,
1
dzięki, ta odpowiedź jest bardzo pomocna :) hej, tylko jedno, to "statyczny prywatny ciąg znaków guid =" 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 ";" rzecz jest zawsze stała? jeśli nie, gdzie mogę uzyskać te wartości?
Charmie
1
Mam to: „Serwer nie może maskować żadnych ramek, które wysyła do klienta”
Charmie,
5
Prawdopodobnie powinieneś był pozostawić pierwotne pytanie nietknięte. Celem pytań jest przedstawienie problemu, a nie rozwiązania. Odpowiedzi, jak można się domyślić, dotyczą rozwiązań.
Kehlan Krumme
1
Dlaczego adres URL WebSocket kończy się na „/ service” (ws: // localhost: 8080 / service)? Dlaczego nie po prostu „ws: // localhost: 8080”?
andree

Odpowiedzi:

72

WebSockets to protokół oparty na połączeniu strumieniowym TCP. Chociaż WebSockets jest protokołem opartym na wiadomościach.

Jeśli chcesz zaimplementować własny protokół, to polecam korzystać z najnowszej i stabilnej specyfikacji (dla 18/04/12) RFC 6455 . Niniejsza specyfikacja zawiera wszystkie niezbędne informacje dotyczące uzgadniania i ramkowania. Jak również większość opisów scenariuszy zachowań od strony przeglądarki, a także po stronie serwera. Zdecydowanie zaleca się przestrzeganie zaleceń dotyczących strony serwera podczas implementacji kodu.

W kilku słowach opisałbym pracę z WebSockets w następujący sposób:

  1. Utwórz serwer Socket (System.Net.Sockets), powiąż go z określonym portem i kontynuuj nasłuchiwanie z asynchronicznym akceptowaniem połączeń. Coś w tym stylu:

    Socket serverSocket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
    serverSocket.Bind (nowy IPEndPoint (IPAddress.Any, 8080));
    serverSocket.Listen (128);
    serverSocket.BeginAccept (null, 0, OnAccept, null);
  2. Powinieneś mieć akceptację funkcji "OnAccept", która zaimplementuje handshake. W przyszłości musi znajdować się w innym wątku, jeśli system ma obsługiwać dużą liczbę połączeń na sekundę.

    private void OnAccept (wynik IAsyncResult) {
    próbować {
        Klient gniazda = null;
        if (serverSocket! = null && serverSocket.IsBound) {
            client = serverSocket.EndAccept (wynik);
        }
        if (client! = null) {
            / * Uzgadnianie i zarządzanie ClientSocket * /
        }
    } catch (wyjątek SocketException) {
    
    } Wreszcie {
        if (serverSocket! = null && serverSocket.IsBound) {
            serverSocket.BeginAccept (null, 0, OnAccept, null);
        }
    }
    }
  3. Po nawiązaniu połączenia musisz wykonać uścisk dłoni . W oparciu o specyfikację 1.3 Opening Handshake , po nawiązaniu połączenia otrzymasz podstawowe żądanie HTTP z pewnymi informacjami. Przykład:

    GET / chat HTTP / 1.1
    Host: serwer.example.com
    Aktualizacja: websocket
    Połączenie: uaktualnij
    Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ ==
    Pochodzenie: http://example.com
    Protokół Sec-WebSocket: chat, superchat
    Wersja Sec-WebSocket: 13

    Ten przykład jest oparty na wersji protokołu 13. Należy pamiętać, że starsze wersje mają pewne różnice, ale w większości najnowsze wersje są wzajemnie kompatybilne. Różne przeglądarki mogą przesyłać dodatkowe dane. Na przykład szczegóły przeglądarki i systemu operacyjnego, pamięć podręczna i inne.

    Na podstawie podanych szczegółów uzgadniania musisz wygenerować wiersze odpowiedzi, są one w większości takie same, ale będą zawierać klucz Accpet, który jest oparty na dostarczonym kluczu Sec-WebSocket-Key. W specyfikacji 1.3 jest jasno opisane, jak wygenerować klucz odpowiedzi. Oto moja funkcja, której używałem w V13:

    statyczny łańcuch prywatny guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
    private string AcceptKey (ref string key) {
        string longKey = klucz + identyfikator guid;
        SHA1 sha1 = SHA1CryptoServiceProvider.Create ();
        byte [] hashBytes = sha1.ComputeHash (System.Text.Encoding.ASCII.GetBytes (longKey));
        return Convert.ToBase64String (hashBytes);
    }
    

    Odpowiedź uścisk dłoni wygląda następująco:

    HTTP / 1.1 101 Przełączanie protokołów
    Aktualizacja: websocket
    Połączenie: uaktualnij
    Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK + xOo =

    Ale klucz akceptacji musi być wygenerowany na podstawie klucza dostarczonego przez klienta i metody AcceptKey, którą wcześniej podałem. Ponadto upewnij się, że po ostatnim znaku klawisza akceptacji umieściłeś dwie nowe linie "\ r \ n \ r \ n".

  4. Po wysłaniu odpowiedzi typu handshake z serwera klient powinien uruchomić funkcję „ onopen ”, co oznacza, że ​​możesz wysyłać wiadomości po.
  5. Wiadomości nie są wysyłane w formacie surowym, ale zawierają ramkę danych . Od klienta do serwera również implementuj maskowanie danych na podstawie dostarczonych 4 bajtów w nagłówku wiadomości. Chociaż od serwera do klienta nie musisz stosować maskowania danych. Przeczytaj rozdział 5. Ramki danych w specyfikacji. Oto kopiuj-wklej z mojej własnej implementacji. Nie jest to kod gotowy do użycia i musi zostać zmodyfikowany, zamieszczam go tylko po to, aby dać wyobrażenie i ogólną logikę odczytu / zapisu z ramkami WebSocket. Przejdź do tego linku .
  6. Po wdrożeniu ramkowania upewnij się, że otrzymujesz dane we właściwy sposób za pomocą gniazd. Na przykład, aby zapobiec scalaniu niektórych wiadomości w jeden, ponieważ TCP jest nadal protokołem opartym na strumieniu. Oznacza to, że musisz przeczytać TYLKO określoną ilość bajtów. Długość wiadomości jest zawsze oparta na nagłówku i podanych szczegółach długości danych w samym nagłówku. Więc kiedy odbierasz dane z Socket, najpierw odbierz 2 bajty, pobierz szczegóły z nagłówka na podstawie specyfikacji Framing, następnie jeśli maska ​​dostarczy kolejne 4 bajty, a następnie długość, która może wynosić 1, 4 lub 8 bajtów na podstawie długości danych. I po danych sobie. Po przeczytaniu zastosuj demasking, a dane wiadomości są gotowe do użycia.
  7. Możesz chcieć użyć protokołu danych , polecam użycie JSON ze względu na ekonomię ruchu i łatwość użycia po stronie klienta w JavaScript. Po stronie serwera możesz chcieć sprawdzić niektóre parsery. Jest ich dużo, Google może być naprawdę pomocne.

Implementacja własnego protokołu WebSockets z pewnością ma pewne zalety i wspaniałe doświadczenie, a także kontrolę nad samym protokołem. Ale musisz poświęcić na to trochę czasu i upewnić się, że implementacja jest wysoce niezawodna.

W tym samym czasie możesz zajrzeć do gotowych rozwiązań, których Google (znowu) ma dość.

moka
źródło
Chyba utknąłem na uścisku dłoni. kiedy otrzymuję nowe połączenie, muszę wysłać klientowi skrót sha1 długiego klucza i krótkiego klucza, prawda?
Tono Nam
Dodałem więcej informacji w sekcji 3. Opisuje więcej szczegółów dotyczących uzgadniania ze strony serwera.
moka
1
Upewnij się również, że jeśli w żądaniu są podane protokoły, użyj tego samego w odpowiedzi dla linii Sec-WebSocket-Protocol. Ale tylko wtedy, gdy jest to wymagane. Nie potrzebujesz też wersji do odpowiedzi. I na koniec dodaj kolejną nową linię. Jak dobrze wyślij cały ciąg odpowiedzi zakodowany przy użyciu UTF8: Encoding.UTF8.GetBytes (responseBytes)
moka Kwietnia
Jesteśmy blisko. Dziękuję bardzo za pomoc. Mogę teraz wysłać wiadomość, ale wydaje mi się, że jest ona zaszyfrowana. Spójrz na moją edycję, nad którą niedługo zacznę pracę ...
Tono Nam
Musisz zaimplementować ramkowanie danych, będzie to moim zdaniem najbardziej skomplikowany bit we wdrażaniu protokołu WebSockets. Dodam kod kopiuj-wklej z mojej implementacji do posta, ale pamiętaj, aby go edytować, ponieważ ma kilka rzeczy do zmiany, ale ogólnie daje pomysł i logikę pracy z ramką.
moka
9

(Wysłana odpowiedź w imieniu PO) .

Mogę teraz wysłać dane. To moja nowa wersja programu dzięki Twoim odpowiedziom i kodowi @Maksims Mihejevs.

serwer

using System;
using System.Net.Sockets;
using System.Net;
using System.Security.Cryptography;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static Socket serverSocket = new Socket(AddressFamily.InterNetwork, 
        SocketType.Stream, ProtocolType.IP);
        static private string guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

        static void Main(string[] args)
        {            
            serverSocket.Bind(new IPEndPoint(IPAddress.Any, 8080));
            serverSocket.Listen(128);
            serverSocket.BeginAccept(null, 0, OnAccept, null);            
            Console.Read();
        }

        private static void OnAccept(IAsyncResult result)
        {
            byte[] buffer = new byte[1024];
            try
            {
                Socket client = null;
                string headerResponse = "";
                if (serverSocket != null && serverSocket.IsBound)
                {
                    client = serverSocket.EndAccept(result);
                    var i = client.Receive(buffer);
                    headerResponse = (System.Text.Encoding.UTF8.GetString(buffer)).Substring(0,i);
                    // write received data to the console
                    Console.WriteLine(headerResponse);

                }
                if (client != null)
                {
                    /* Handshaking and managing ClientSocket */

                    var key = headerResponse.Replace("ey:", "`")
                              .Split('`')[1]                     // dGhlIHNhbXBsZSBub25jZQ== \r\n .......
                              .Replace("\r", "").Split('\n')[0]  // dGhlIHNhbXBsZSBub25jZQ==
                              .Trim();

                    // key should now equal dGhlIHNhbXBsZSBub25jZQ==
                    var test1 = AcceptKey(ref key);

                    var newLine = "\r\n";

                    var response = "HTTP/1.1 101 Switching Protocols" + newLine
                         + "Upgrade: websocket" + newLine
                         + "Connection: Upgrade" + newLine
                         + "Sec-WebSocket-Accept: " + test1 + newLine + newLine
                         //+ "Sec-WebSocket-Protocol: chat, superchat" + newLine
                         //+ "Sec-WebSocket-Version: 13" + newLine
                         ;

                    // which one should I use? none of them fires the onopen method
                    client.Send(System.Text.Encoding.UTF8.GetBytes(response));

                    var i = client.Receive(buffer); // wait for client to send a message

                    // once the message is received decode it in different formats
                    Console.WriteLine(Convert.ToBase64String(buffer).Substring(0, i));                    

                    Console.WriteLine("\n\nPress enter to send data to client");
                    Console.Read();

                    var subA = SubArray<byte>(buffer, 0, i);
                    client.Send(subA);
                    Thread.Sleep(10000);//wait for message to be send


                }
            }
            catch (SocketException exception)
            {
                throw exception;
            }
            finally
            {
                if (serverSocket != null && serverSocket.IsBound)
                {
                    serverSocket.BeginAccept(null, 0, OnAccept, null);
                }
            }
        }

        public static T[] SubArray<T>(T[] data, int index, int length)
        {
            T[] result = new T[length];
            Array.Copy(data, index, result, 0, length);
            return result;
        }

        private static string AcceptKey(ref string key)
        {
            string longKey = key + guid;
            byte[] hashBytes = ComputeHash(longKey);
            return Convert.ToBase64String(hashBytes);
        }

        static SHA1 sha1 = SHA1CryptoServiceProvider.Create();
        private static byte[] ComputeHash(string str)
        {
            return sha1.ComputeHash(System.Text.Encoding.ASCII.GetBytes(str));
        }
    }
}

JavaScript:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <script type="text/javascript">
        function connect() {
            var ws = new WebSocket("ws://localhost:8080/service");
            ws.onopen = function () {
                alert("About to send data");
                ws.send("Hello World"); // I WANT TO SEND THIS MESSAGE TO THE SERVER!!!!!!!!
                alert("Message sent!");
            };

            ws.onmessage = function (evt) {
                alert("About to receive data");
                var received_msg = evt.data;
                alert("Message received = "+received_msg);
            };
            ws.onclose = function () {
                // websocket is closed.
                alert("Connection is closed...");
            };
        };


    </script>
</head>
<body style="font-size:xx-large" >
    <div>
    <a href="#" onclick="connect()">Click here to start</a></div>
</body>
</html>

Po uruchomieniu tego kodu jestem w stanie wysyłać i odbierać dane zarówno od klienta, jak i serwera. Jedynym problemem jest to, że wiadomości są szyfrowane, gdy docierają do serwera. Oto kroki, jak działa program:

wprowadź opis obrazu tutaj

Zwróć uwagę, jak wiadomość od klienta jest szyfrowana.

halfer
źródło
2
Coś jest nie tak z twoim przykładem, kiedy naciskam Enter Połączenie przechodzi do zamknięcia.
Richard Aguirre
@RichardAguirre: Opublikowałem to w imieniu PO (patrz pierwsza linia odpowiedzi) - obecnie nie zostaną oni powiadomieni o Twojej wiadomości. Możesz spróbować pingować je pod pytaniem, ale prawdopodobnie będą potrzebować znacznie więcej szczegółów.
halfer
6

WebSockets są implementowane za pomocą protokołu, który obejmuje uzgadnianie między klientem a serwerem . Nie wyobrażam sobie, żeby działały jak zwykłe gniazdka. Zapoznaj się z protokołem i poproś swoją aplikację o jej omówienie. Alternatywnie, użyj istniejącej biblioteki WebSocket lub .Net4.5beta z interfejsem API WebSocket .

wydający
źródło
Oczywiście działają bardzo podobnie do zwykłych gniazd. Gniazdo jest na niższym poziomie niż protokół aplikacji i jako takie nie jest od niego zależne. Oznacza to, że możesz uruchomić FTP, SMTP, HTTP, WebSockets, itp ... na gnieździe. Do implementatora należy upewnienie się, że postępuje zgodnie z protokołem, w przeciwnym razie nikt nie będzie mógł rozmawiać z serwerem.
SRM
4

Nigdzie nie mogłem znaleźć prostego działającego przykładu (stan na 19 stycznia), więc oto zaktualizowana wersja. Mam Chrome w wersji 71.0.3578.98.

Serwer C # Websocket:

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;

namespace WebSocketServer
{
    class Program
    {
    static Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
    static private string guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

    static void Main(string[] args)
    {
        serverSocket.Bind(new IPEndPoint(IPAddress.Any, 8080));
        serverSocket.Listen(1); //just one socket
        serverSocket.BeginAccept(null, 0, OnAccept, null);
        Console.Read();
    }

    private static void OnAccept(IAsyncResult result)
    {
        byte[] buffer = new byte[1024];
        try
        {
            Socket client = null;
            string headerResponse = "";
            if (serverSocket != null && serverSocket.IsBound)
            {
                client = serverSocket.EndAccept(result);
                var i = client.Receive(buffer);
                headerResponse = (System.Text.Encoding.UTF8.GetString(buffer)).Substring(0, i);
                // write received data to the console
                Console.WriteLine(headerResponse);
                Console.WriteLine("=====================");
            }
            if (client != null)
            {
                /* Handshaking and managing ClientSocket */
                var key = headerResponse.Replace("ey:", "`")
                          .Split('`')[1]                     // dGhlIHNhbXBsZSBub25jZQ== \r\n .......
                          .Replace("\r", "").Split('\n')[0]  // dGhlIHNhbXBsZSBub25jZQ==
                          .Trim();

                // key should now equal dGhlIHNhbXBsZSBub25jZQ==
                var test1 = AcceptKey(ref key);

                var newLine = "\r\n";

                var response = "HTTP/1.1 101 Switching Protocols" + newLine
                     + "Upgrade: websocket" + newLine
                     + "Connection: Upgrade" + newLine
                     + "Sec-WebSocket-Accept: " + test1 + newLine + newLine
                     //+ "Sec-WebSocket-Protocol: chat, superchat" + newLine
                     //+ "Sec-WebSocket-Version: 13" + newLine
                     ;

                client.Send(System.Text.Encoding.UTF8.GetBytes(response));
                var i = client.Receive(buffer); // wait for client to send a message
                string browserSent = GetDecodedData(buffer, i);
                Console.WriteLine("BrowserSent: " + browserSent);

                Console.WriteLine("=====================");
                //now send message to client
                client.Send(GetFrameFromString("This is message from server to client."));
                System.Threading.Thread.Sleep(10000);//wait for message to be sent
            }
        }
        catch (SocketException exception)
        {
            throw exception;
        }
        finally
        {
            if (serverSocket != null && serverSocket.IsBound)
            {
                serverSocket.BeginAccept(null, 0, OnAccept, null);
            }
        }
    }

    public static T[] SubArray<T>(T[] data, int index, int length)
    {
        T[] result = new T[length];
        Array.Copy(data, index, result, 0, length);
        return result;
    }

    private static string AcceptKey(ref string key)
    {
        string longKey = key + guid;
        byte[] hashBytes = ComputeHash(longKey);
        return Convert.ToBase64String(hashBytes);
    }

    static SHA1 sha1 = SHA1CryptoServiceProvider.Create();
    private static byte[] ComputeHash(string str)
    {
        return sha1.ComputeHash(System.Text.Encoding.ASCII.GetBytes(str));
    }

    //Needed to decode frame
    public static string GetDecodedData(byte[] buffer, int length)
    {
        byte b = buffer[1];
        int dataLength = 0;
        int totalLength = 0;
        int keyIndex = 0;

        if (b - 128 <= 125)
        {
            dataLength = b - 128;
            keyIndex = 2;
            totalLength = dataLength + 6;
        }

        if (b - 128 == 126)
        {
            dataLength = BitConverter.ToInt16(new byte[] { buffer[3], buffer[2] }, 0);
            keyIndex = 4;
            totalLength = dataLength + 8;
        }

        if (b - 128 == 127)
        {
            dataLength = (int)BitConverter.ToInt64(new byte[] { buffer[9], buffer[8], buffer[7], buffer[6], buffer[5], buffer[4], buffer[3], buffer[2] }, 0);
            keyIndex = 10;
            totalLength = dataLength + 14;
        }

        if (totalLength > length)
            throw new Exception("The buffer length is small than the data length");

        byte[] key = new byte[] { buffer[keyIndex], buffer[keyIndex + 1], buffer[keyIndex + 2], buffer[keyIndex + 3] };

        int dataIndex = keyIndex + 4;
        int count = 0;
        for (int i = dataIndex; i < totalLength; i++)
        {
            buffer[i] = (byte)(buffer[i] ^ key[count % 4]);
            count++;
        }

        return Encoding.ASCII.GetString(buffer, dataIndex, dataLength);
    }

    //function to create  frames to send to client 
    /// <summary>
    /// Enum for opcode types
    /// </summary>
    public enum EOpcodeType
    {
        /* Denotes a continuation code */
        Fragment = 0,

        /* Denotes a text code */
        Text = 1,

        /* Denotes a binary code */
        Binary = 2,

        /* Denotes a closed connection */
        ClosedConnection = 8,

        /* Denotes a ping*/
        Ping = 9,

        /* Denotes a pong */
        Pong = 10
    }

    /// <summary>Gets an encoded websocket frame to send to a client from a string</summary>
    /// <param name="Message">The message to encode into the frame</param>
    /// <param name="Opcode">The opcode of the frame</param>
    /// <returns>Byte array in form of a websocket frame</returns>
    public static byte[] GetFrameFromString(string Message, EOpcodeType Opcode = EOpcodeType.Text)
    {
        byte[] response;
        byte[] bytesRaw = Encoding.Default.GetBytes(Message);
        byte[] frame = new byte[10];

        int indexStartRawData = -1;
        int length = bytesRaw.Length;

        frame[0] = (byte)(128 + (int)Opcode);
        if (length <= 125)
        {
            frame[1] = (byte)length;
            indexStartRawData = 2;
        }
        else if (length >= 126 && length <= 65535)
        {
            frame[1] = (byte)126;
            frame[2] = (byte)((length >> 8) & 255);
            frame[3] = (byte)(length & 255);
            indexStartRawData = 4;
        }
        else
        {
            frame[1] = (byte)127;
            frame[2] = (byte)((length >> 56) & 255);
            frame[3] = (byte)((length >> 48) & 255);
            frame[4] = (byte)((length >> 40) & 255);
            frame[5] = (byte)((length >> 32) & 255);
            frame[6] = (byte)((length >> 24) & 255);
            frame[7] = (byte)((length >> 16) & 255);
            frame[8] = (byte)((length >> 8) & 255);
            frame[9] = (byte)(length & 255);

            indexStartRawData = 10;
        }

        response = new byte[indexStartRawData + length];

        int i, reponseIdx = 0;

        //Add the frame bytes to the reponse
        for (i = 0; i < indexStartRawData; i++)
        {
            response[reponseIdx] = frame[i];
            reponseIdx++;
        }

        //Add the data bytes to the response
        for (i = 0; i < length; i++)
        {
            response[reponseIdx] = bytesRaw[i];
            reponseIdx++;
        }

        return response;
    }
}
}

Klient html i javascript:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <script type="text/javascript">
        var socket = new WebSocket('ws://localhost:8080/websession');
        socket.onopen = function() {
           // alert('handshake successfully established. May send data now...');
		   socket.send("Hi there from browser.");
        };
		socket.onmessage = function (evt) {
                //alert("About to receive data");
                var received_msg = evt.data;
                alert("Message received = "+received_msg);
            };
        socket.onclose = function() {
            alert('connection closed');
        };
    </script>
</head>
<body>
</body>
</html>

Deepak Garud
źródło
3

Kwestia

Ponieważ używasz WebSocket, wydatki są poprawne. Po otrzymaniu początkowych danych z WebSocket, musisz wysłać komunikat uzgadniania z serwera C #, zanim dalsze informacje będą mogły przepłynąć.

HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: websocket
Connection: Upgrade
WebSocket-Origin: example
WebSocket-Location: something.here
WebSocket-Protocol: 13

Coś w tym stylu.

Możesz zrobić więcej badań, jak działa WebSocket w W3 lub Google.

Linki i zasoby

Oto specyfikacja protokołu: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76#section-1.3

Lista przykładów roboczych:

Caesay
źródło
Również używam kodowania UTF8. Czy powinienem użyć innego, takiego jak ASCII?
Tono Nam
@TonoNam: O ile wiem, kodowanie UTF8 jest poprawne - chociaż nie jestem ekspertem od HTML5, więc nie wiem na pewno.
caesay
Zrobiłem to z safari !!! Potrzebuję go jednak, aby działał z Google Chrome. Wszystkie przykłady łączą się, ale żaden z nich nie wysyła danych. Będę próbował dalej. Wielkie dzięki za pomoc!
Tono Nam
Oczywiście ... Jeśli nadal nie będę działał, sprawię, że to pytanie będzie nagrodą! Jestem naprawdę ciekawy, jak to działa. Dzięki za pomoc
Tono Nam
Link do specyfikacji protokołu jest nieaktualny. Safari nadal tego używa, ale inne przeglądarki przeszły na niezgodną wersję RFC 6455 . Ponadto, chociaż masz rację, że początkowe połączenie wymaga negocjacji, dalsze komunikaty nie wymagają.
simonc