0

Perhaps I badly need a hand now.

I am currently having a problem regarding websocket server using c# and HTML5. It is not firing my onmessage() event in html5. It opens the socket connection and triggers the onopen() event. But, once a connection is established, it continues to close the connection. Here's my simple code:

SERVER (c#):

using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Security.Cryptography;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        public Socket ListenerSocker { get; private set; }
        static IPEndPoint ipLocal;
        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.Listen(200);
            serverSocket.BeginAccept(null, 0, OnAccept, null);

            Console.Read();
        }


        private static void OnClientConnect()
        {

            serverSocket.BeginAccept(null, 0, OnAccept, null);
        }







        private static void OnAccept(IAsyncResult result)
        {
            byte[] buffer = new byte[1024];

            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-Key: " + test1 + newLine + newLine
                     + "Sec-WebSocket-Key: " + 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);
                Console.WriteLine("***SUBA****:"+subA);
                Console.WriteLine("TEST");
                client.Send(subA);

                // Thread.Sleep(10000);//wait for message to be send

                // OnClientConnect();
            }
        }

        public static T[] SubArray<T>(T[] data, int index, int length)
        {
            T[] result = new T[length];
            Array.Copy(data, index, result, 0, length);
            Console.WriteLine(result);
            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));
        }
    }
}

CLIENT (HTML5):

<!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");
            console.log(ws);
            ws.onopen = function () {
                alert("About to send data");
                ws.send("test"); // 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...");
            };
        };

        function send(){
        }


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

</body>
</html>

I can get this:

 alert("About to send data");

and this:

alert("Message sent!");

but after that, the connection closes. I could also check that the server receives data from client. The thing is, once I send data from server to client, for me to be able to return what the client has given me, the connection suddenly closes. What could possibly be the problem?

Charmie
  • 2,468
  • 7
  • 33
  • 47

1 Answers1

0

Websocket messages are not plain text; they need to have a simple framing protocol applied

Framing rules differ slightly for client->server and server->client messages. I imagine the client is closing its connection when you try to echo its message without applying the different framing.

See the data framing section of RFC6455 for how to decode/encode messages. Or, if you're using .NET4.5, you could consider using System.Net.WebSockets instead of writing your own server.

Community
  • 1
  • 1
simonc
  • 41,632
  • 12
  • 85
  • 103
  • yeah i believe i have data framing – Charmie Mar 27 '13 at 05:15
  • I can't see it in your sample code. Each incoming message would need some leading bytes stripped then the remaining bytes converted. Each outgoing message would need to have some leading bytes added. – simonc Mar 27 '13 at 07:42
  • do you have any actual sample codes there where i can refer to? im having a hard time understanding this data framing – Charmie Mar 27 '13 at 08:45
  • See http://stackoverflow.com/a/8125509/311966 for some pseudo code. If you can't understand the spec however, I'd strongly recommend you either use the .NET4.5 classes or look for an existing third party server instead. Searching for "open source websocket server c#" will give you plenty of liberally licensed options. – simonc Mar 27 '13 at 09:01