kostenloser Webspace werbefrei: lima-city


WebSockets

lima-cityForumDie eigene HomepageHTML, CSS & Javascript

  1. Autor dieses Themas

    web-tester

    web-tester hat kostenlosen Webspace.

    Hallo zusammen

    Ich habe mich in letzter Zeit etwas mit websockets beschäftigt. Mein Ziel ist es eigentlich einen kleinen Web-Chat zu machen.

    Als Test hab ich mir einen kleinen J-Script erstellt
    function connect() {
                var ws = new WebSocket("ws://localhost:100");
                ws.onopen = function () {
                    alert("Open!");
                }
                ws.onmessage = function (evt) {
                    alert("About to receive data");
                    var received_msg = evt.data;
                    alert("Message received = "+received_msg);
                }
                ws.onclose = function () {
                    alert("Connection is closed...");
                }
            }


    Auf VS hab ich mir dann einen "Server" gemacht
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Sockets;
    using System.Security.Cryptography;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace test_server
    {
        class Program
        {
            private static byte[] _buffer = new byte[2048];
            private static Socket _serverSocket = new Socket
                (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    
            static void Main(string[] args)
            {
                Console.Title = "Server";
                SetupServer();
                Console.ReadLine();
            }
            private static void SetupServer()
            {
                Console.WriteLine("Setting up server...");
                _serverSocket.Bind(new IPEndPoint(IPAddress.Any, 100));
                _serverSocket.Listen(5);
                _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), true);
            }
    
            private static void AcceptCallback(IAsyncResult AR)
            {
    
                Socket socket = _serverSocket.EndAccept(AR);
                Console.WriteLine("Client connected");
                socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
                _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), true);
            }
    
            private static void ReceiveCallback(IAsyncResult AR)
            {
                try
                {
                    Console.ForegroundColor = ConsoleColor.White;
                    Console.WriteLine(Environment.NewLine);
                    Socket socket = (Socket)AR.AsyncState;
                    int received = socket.EndReceive(AR);
                    byte[] dataBuf = new byte[received];
                    Array.Copy(_buffer, dataBuf, received);
                    string text = Encoding.ASCII.GetString(dataBuf);
                    Console.WriteLine("Text received: " + Environment.NewLine + text);
                    string responseKey = "";
                    string keyRaw = text.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)[11].Split(new string[] { " " }, StringSplitOptions.None)[1] + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
                    using (SHA1 sha1 = SHA1.Create())
                    {
                        byte[] hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(keyRaw));
                        responseKey = Convert.ToBase64String(hash);
                    }
                    String response = "HTTP/1.1 101 Switching Protocols" + Environment.NewLine
                        + "Upgrade: websocket" + Environment.NewLine
                        + "Connection: Upgrade" + Environment.NewLine
                        + "Sec-WebSocket-Accept: " + responseKey + Environment.NewLine + Environment.NewLine
                        + "Sec-WebSocket-Protocol: chat" + Environment.NewLine;
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("KEY: " + responseKey);
                    Console.ForegroundColor = ConsoleColor.White;
                    socket.BeginSend(System.Text.Encoding.UTF8.GetBytes(response), 0, System.Text.Encoding.UTF8.GetBytes(response).Length, SocketFlags.None, new AsyncCallback(SendCallback), socket);
    
                    socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
    
                }
                catch (Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Error: " + e.Message); }
            }
            private static void SendCallback(IAsyncResult AR)
            {
                Socket socket = (Socket)AR.AsyncState;
                socket.EndSend(AR);
            }
        }
    }



    Wenn ich nun den Java-Script ausführe, erhalte ich folgendes:
    http://i.imgur.com/xPQAGCR.png


    und als rückgabe vom js erhalte ich
    - Open!
    - Connection is closed...

    index.php:9 ----> ws.send("text");
    Auch wenn ich zu onopen ws.send("Hey"); hinzufüge, bekomme ich immer gleich danach onclose als Rückgabe.


    Und in der Chrome-Console folgenden Error:
    WebSocket is already in CLOSING or CLOSED state.ws.onopen @ index.php:9


    Weiss jemand vielleicht was ich falsch mache? Oder was ich anders machen muss?

    Wäre echt dankbar

    mfG
    Web-Tester


    Beitrag zuletzt geändert: 6.7.2015 7:04:29 von web-tester
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. Wenn du diese Zeile im Serverprogramm entfernst:
    Console.WriteLine("Text received: " + Environment.NewLine + text);

    Bekommst du dann immernoch diesen Fehler in der Serverkonsole?
    Error: Der Index war außerhalb des Arraybereichs.


    Fall der Fehler immernoch kommt, dann versuche herauszufinden wo genau er entsteht.
    (Es muss ja im try-Block von
    ReceiveCallback
    passieren.
    Fülle diesen Block also mit ganz vielen Ausgaben, um zu sehen, wie weit das Programm kommt.
  4. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    0) JScript ist eine Microsoft-Eigenheit, die du hier sicher nicht meinst. Also: JavaScript ;-)

    1) Für HTTP ist ganz klar definiert, was ein Zeilenumbruch ist, und was nicht. Ein
    Environment.NewLine
    hat beim Zusammensetzen des Headers also nichts verloren.

    2) Fix die Position eines Headers anzugeben verstößt gegen die Protokoll-Spezifikation. Ein anderer Browser könnte das somit sehr einfach durcheinanderbringen.

    3)
    + "Sec-WebSocket-Accept: " + responseKey + Environment.NewLine + Environment.NewLine
    ist falsch, denn 2 Zeilenumbrüche beenden den Header, du schickst aber nachher noch etwas.

    4) Es gibt ein definiertes Frame-Format, an das du dich halten musst, wenn du etwas schicken willst. Siehe RFC.
  5. Autor dieses Themas

    web-tester

    web-tester hat kostenlosen Webspace.

    Danke für die schnellen Antworten

    ****EDIT***
    So

    Ich hab jetzt alle meine Fragen Antworten etc. gelöscht, nur zur Übersichtlichkeit.

    Ich konnte alle meine Probleme lösen es funktioniert bis jetzt alles perfekt! Ein grosses Danke von mir ;)

    Nur etwas wollte ich noch fragen:

    Das ganze war nur möglich, da ich zufälligerweise auf einen Script gestossen bin:
    public static byte[] getBytes(String mess)
            {
                byte[] rawData = Encoding.UTF8.GetBytes(mess);
    
                int frameCount = 0
                byte[] frame = new byte[10]
    
                frame[0] = (byte)129
    
                if (rawData.Length <= 125)
                {
                    frame[1] = (byte)rawData.Length
                    frameCount = 2
                }
                else if (rawData.Length >= 126 && rawData.Length <= 65535)
                {
                    frame[1] = (byte)126;
                    int len = rawData.Length
                    frame[2] = (byte)((len >?> 8) & (byte)255)
                    frame[3] = (byte)(len & (byte)255)
                    frameCount = 4
                }
                else
                {
                    frame[1] = (byte)127
                    int len = rawData.Length
                    frame[2] = (byte)((len >> 56) & (byte)255)
                    frame[3] = (byte)((len >> 48) & (byte)255)
                    frame[4] = (byte)((len >> 40) & (byte)255)
                    frame[5] = (byte)((len >> 32) & (byte)255)
                    frame[6] = (byte)((len >> 24) & (byte)255)
                    frame[7] = (byte)((len >> 16) & (byte)255)
                    frame[8] = (byte)((len >> 8) & (byte)255)
                    frame[9] = (byte)(len & (byte)255)
                    frameCount = 10
                }
    
                int bLength = frameCount + rawData.Length
    
                byte[] reply = new byte[bLength]
    
                int bLim = 0
                for (int i = 0 i < frameCount; i++)
                {
                    reply[bLim] = frame[i]
                    bLim++
                }
                for (int i = 0; i < rawData.Length; i++)
                {
                    reply[bLim] = rawData[i]
                    bLim++
                }
                return reply
            }

    Jetzt meine Frage, als ich eine Nachricht an den Client senden wollte, benutzte ich wie beim handshake System.Text.Encoding.UTF8.GetBytes(response). Wieso muss ich das jetzt hier mit einer solch komplizierten Funktion machen? Was macht sie anders?

    Und geht es gut mit WebSockets aufwendigere Sachen, wie z.B. über 1000 Leute über den Server zu verbinden und dann jedem eine Nachricht schreiben? Oder sollte man da auf etwas anderes umsteigen?


    Danke

    web-tester

    Beitrag zuletzt geändert: 7.7.2015 20:32:54 von web-tester
  6. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!