0

I have a server written in C# using Sockets:

/*
    Richard D. Grant
    R.grant.jr.122193@gmail.com
    -Contact for details-
*/
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.Threading;

namespace SERVER{
    static class Application{
        private static readonly List<Socket> _client_list = new List<Socket>();
        private const ushort _port = 8080, _buffer_len = 1024;
        private static byte[] _buf = new byte[_buffer_len];
        private static string key;
        static private string guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

        private static Boolean exiting = false;
        static int Main(){
            Console.Title = "Server Application";
            Socket server_socket = StartServer();
            while(!exiting){

            }
            return CloseServer(server_socket);
        }

        private static Socket StartServer(){
            IPEndPoint IPE = new IPEndPoint(IPAddress.Any, _port); // 192.168.0.14:80
            Socket server_socket = new Socket(IPE.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            server_socket.Bind(IPE);
            server_socket.Listen(128);
            server_socket.BeginAccept(AcceptCallback, server_socket);
            Console.WriteLine("Server Succeeded.");
            return server_socket;
        }
        private static void AcceptCallback(IAsyncResult AR){
            Console.WriteLine("accepting...");
            Socket server_socket = (Socket)AR.AsyncState;
            Socket client_socket = server_socket.EndAccept(AR);

            client_socket.BeginReceive(_buf, 0, _buffer_len, SocketFlags.None, RecCallback, client_socket);

            server_socket.BeginAccept(AcceptCallback, server_socket);
        }
        private static void RecCallback(IAsyncResult AR){
            Console.WriteLine("Recieving");
            Socket client_socket = (Socket)AR.AsyncState;

            int rec_len = client_socket.EndReceive(AR);

            byte[] rec_buf = new byte[rec_len];
            Array.Copy(_buf, rec_buf, rec_len);

            string rec_text = Encoding.UTF8.GetString(rec_buf);


                if(!_client_list.Contains(client_socket)){
                    _client_list.Add(client_socket);
                    key = rec_text.Replace("ey:", "`")
                    .Split('`')[1]                     // dGhlIHNhbXBsZSBub25jZQ== \r\n .......
                    .Replace("\r", "").Split('\n')[0]  // dGhlIHNhbXBsZSBub25jZQ==
                    .Trim();
                    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
                         ;
                    client_socket.Send(Encoding.UTF8.GetBytes(response));
                    client_socket.Send("server received");
                }else{
                    Console.WriteLine(rec_text);
                }
            _buf = new byte[_buffer_len];
            client_socket.BeginReceive(_buf, 0, _buffer_len, SocketFlags.None, RecCallback, client_socket);
        }

        private static void client_disconnect(Socket soc){
            soc.Shutdown(SocketShutdown.Both);
            soc.Close();
        }
        private static ushort CloseServer(Socket server_socket){
            foreach(Socket client in _client_list){
                client_disconnect(client);
            }
            server_socket.Close();
            return 0;
        }

        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(Encoding.UTF8.GetBytes(str));
        }
    }
}

And i have the HTML5 websocket client:

<!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 () {
                ws.send("Hello World"); // I WANT TO SEND THIS MESSAGE TO THE SERVER!!!!!!!!
                console.log("opened!");
            };

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


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

HTML5 websocket requires a handshake, and the server deals with that accordingly.

client_socket.send(Encoding.UTF8.GetBytes("send"));

Does not trigger html5 onmessage

ws.send("send");

returns scrambled text to the server, but it is sent successfully.

user3466723
  • 43
  • 1
  • 2
  • 7

2 Answers2

0

The server deals with the handshake, but it does not deal with the packet frame after that. The message is not sent back in plain text and requires some processing.

How can I send and receive WebSocket messages on the server side?

This details the frame specification. For example, the first byte is always 129, the seconds has to do with the length. There is an example C# method to decode the frame on the link provided.

Community
  • 1
  • 1
AlexH
  • 115
  • 13
0

I wanted to post the source code to my solution, though i would like to give credit to AlexH for pointing me in the correct location.

private static byte[] encode(string str){
     List<byte> lb = new List<byte>();
     lb.Add(0x81);//129 to represent text frame
     lb.Add((byte)str.Length);//2nd byte represents the length of the string
     lb.AddRange(System.Text.Encoding.UTF8.GetBytes(str));
     return lb.ToArray();
}

Frame:

+---------------------------------+
| FRAME TYPE | DATA LENGTH | DATA |
+---------------------------------+
user3466723
  • 43
  • 1
  • 2
  • 7