एक "हैलो वर्ल्ड" WebSocket उदाहरण बनाना


85

मुझे समझ नहीं आ रहा है कि मैं निम्नलिखित कोड काम क्यों नहीं कर पा रहा हूं। मैं अपने सर्वर कंसोल एप्लिकेशन से जावास्क्रिप्ट से जुड़ना चाहता हूं। और फिर सर्वर को डेटा भेजें।

यहाँ सर्वर कोड है:

    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));
        }
    }

और यहाँ जावास्क्रिप्ट है:

        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...");
        };

जब मैं उस कोड को चलाता हूं तो ऐसा होता है:

ध्यान दें कि जब मैं जावास्क्रिप्ट चलाता हूं तो सर्वर स्वीकार करता है और सफलतापूर्वक कनेक्शन स्थापित करता है। जावास्क्रिप्ट हालांकि डेटा भेजने में सक्षम नहीं है। जब भी मैं भेजने की विधि रखता हूँ, तो यह एक कनेक्शन स्थापित होने पर भी नहीं भेजेगा। मै इसे काम मे कैसे ले सकता हूँ?


9
यह "प्रश्न" किसी भी प्रश्न का प्रतीत नहीं होता है, और इस प्रकार वास्तव में StackOverflow के प्रारूप के अनुकूल नहीं है। Fwiw, ग्राहक के संदेश नहीं है एन्क्रिप्टेड यह है नकाबपोश एक यादृच्छिक मूल्य है कि फ्रेम के एक भाग के रूप में प्रसारित किया जाता है के खिलाफ XOR'ing द्वारा (अस्पष्ट)। यह प्रोटोकॉल विवरण प्रॉक्सी सर्वर के खिलाफ विषाक्तता के हमलों से बचने के लिए मौजूद है जो यातायात को गलत समझ सकता है।
एरिकाला

1
धन्यवाद, यह उत्तर बहुत उपयोगी है :) हे, सिर्फ एक चीज, क्या यह "स्थिर निजी स्ट्रिंग गाइड =" 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 ";" बात हमेशा स्थिर है? यदि नहीं, तो मुझे ये मूल्य कहां से मिल सकते हैं?
चार्मी

1
मुझे यह मिला: "एक सर्वर को ग्राहक को भेजे जाने वाले किसी भी फ्रेम को मास्क नहीं करना चाहिए"
चार्मी

5
आपको शायद मूल प्रश्न को बरकरार रखना चाहिए था। प्रश्नों का उद्देश्य मुद्दे को प्रस्तुत करना है, न कि समाधान। जवाब, जैसा कि आप अनुमान लगा सकते थे, समाधान के लिए हैं।
केहलान क्रुममे

1
WebSocket url '/ सेवा' (ws: // localhost: 8080 / service) के साथ क्यों समाप्त होता है? सिर्फ 'ws: // localhost: 8080' ही क्यों?
और्री।

जवाबों:


72

WebSockets प्रोटोकॉल है जो टीसीपी स्ट्रीम किए गए कनेक्शन पर निर्भर करता है। हालांकि WebSockets संदेश आधारित प्रोटोकॉल है।

यदि आप अपने स्वयं के प्रोटोकॉल को लागू करना चाहते हैं तो मैं नवीनतम और स्थिर विनिर्देश (18/04/12 के लिए) RFC 6455 का उपयोग करने की सलाह देता हूं । इस विनिर्देशन में हैंडशेक और फ्रेमिंग के संबंध में सभी आवश्यक जानकारी शामिल है। साथ ही ब्राउज़र की ओर से और साथ ही सर्वर की ओर से व्यवहार करने के परिदृश्यों पर अधिकांश विवरण। यह अनुशंसा की जाती है कि आपके कोड को लागू करने के दौरान सर्वर पक्ष के बारे में क्या सिफारिशें बताई जाती हैं।

कुछ शब्दों में, मैं इस तरह से WebSockets के साथ काम करने का वर्णन करूंगा:

  1. सर्वर सॉकेट बनाएं (System.Net.Sockets) इसे विशिष्ट पोर्ट पर बांधें, और कनेक्शनों की अतुल्यकालिक स्वीकृति के साथ सुनते रहें। ऐसा कुछ:

    सॉकेट सर्वर सॉकेट = नया सॉकेट (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
    serverSocket.Bind (नया IPEndPoint (IPAddress.Any, 8080));
    serverSocket.Listen (128);
    serverSocket.BeginAccept (अशक्त, 0, OnAccept, null);
  2. आपके पास "OnAccept" फ़ंक्शन को स्वीकार करना चाहिए जो हैंडशेक को लागू करेगा। यदि सिस्टम प्रति सेकंड बड़ी मात्रा में कनेक्शन को संभालने के लिए है, तो भविष्य में इसे दूसरे धागे में होना चाहिए।

    निजी शून्य OnAccept (IAsyncResult परिणाम) {
    प्रयत्न {
        सॉकेट क्लाइंट = अशक्त;
        अगर (serverSocket! = null && serverSocket.IsBound) {
            ग्राहक = serverSocket.EndAccept (परिणाम);
        }
        अगर (ग्राहक! = अशक्त) {
            / * हैंडशेकिंग और मैनेजिंग क्लाइंटस्केट * /
        }
    } पकड़ (सॉकेटएक्स अपवाद अपवाद) {
    
    } आखिरकार {
        अगर (serverSocket! = null && serverSocket.IsBound) {
            serverSocket.BeginAccept (अशक्त, 0, OnAccept, null);
        }
    }
    }
  3. कनेक्शन स्थापित होने के बाद, आपको हैंडशेक करना होगा । विनिर्देशन के आधार पर 1.3 ओपनिंग हैंडशेक , कनेक्शन स्थापित होने के बाद आपको कुछ जानकारी के साथ बुनियादी HTTP अनुरोध प्राप्त होगा। उदाहरण:

    HTTP / 1.1 पर जाएं / चैट करें
    होस्ट: server.example.com
    अपग्रेड: वेबसोकेट
    कनेक्शन: अपग्रेड
    Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ ==
    मूल: http://example.com
    Sec-WebSocket-Protocol: चैट, सुपरचैट
    Sec-WebSocket-Version: 13

    यह उदाहरण प्रोटोकॉल के संस्करण पर आधारित है। 13. ध्यान रखें कि पुराने संस्करणों में कुछ अंतर हैं, लेकिन ज्यादातर नवीनतम संस्करण क्रॉस-संगत हैं। विभिन्न ब्राउज़र आपको कुछ अतिरिक्त डेटा भेज सकते हैं। उदाहरण के लिए ब्राउज़र और OS विवरण, कैश और अन्य।

    प्रदान किए गए हैंडशेक विवरण के आधार पर, आपको उत्तर रेखाएं बनानी होंगी, वे अधिकतर एक जैसे ही होंगे, लेकिन इसमें Accpet-Key होगी, जो कि Sec-WebSocket-Key पर आधारित है। विनिर्देशन 1.3 में यह स्पष्ट रूप से वर्णित है कि प्रतिक्रिया कुंजी कैसे उत्पन्न की जाए। यहाँ मेरा फ़ंक्शन है जो मैं V13 के लिए उपयोग कर रहा हूं:

    स्थिर निजी स्ट्रिंग गाइड = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
    निजी स्ट्रिंग AcceptKey (रेफ स्ट्रिंग कुंजी) {
        स्ट्रिंग longKey = कुंजी + गाइड;
        SHA1 sha1 = SHA1CryptoServiceProvider.Create ();
        बाइट [] हैशबाइट्स = sha1.ComputeHash (System.Text.Encoding.ASCII.GetBytes (longKey));
        Convert Convert .oBase64String (हैशबाइट्स);
    }
    

    हैंडशेक का उत्तर इस तरह दिखता है:

    HTTP / 1.1 101 स्विचिंग प्रोटोकॉल
    अपग्रेड: वेबसोकेट
    कनेक्शन: अपग्रेड
    Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK + AOL =

    लेकिन स्वीकार कुंजी ग्राहक और विधि से प्रदान की कुंजी के आधार पर एक उत्पन्न किया जाना है AcceptKey मैं पहले प्रदान की। साथ ही, स्वीकार की जाने वाली अंतिम कुंजी के बाद सुनिश्चित करें कि आपने दो नई लाइनें "\ r \ n \ r \ n" डालीं।

  4. हैंडशेक उत्तर सर्वर से भेजे जाने के बाद, क्लाइंट को " ओनोपेन " फ़ंक्शन को ट्रिगर करना चाहिए , इसका मतलब है कि आप संदेश भेज सकते हैं।
  5. संदेश कच्चे प्रारूप में नहीं भेजे जाते हैं, लेकिन उनके पास डेटा फ्रेमन है । और क्लाइंट से सर्वर तक संदेश हेडर में 4 बाइट्स के आधार पर डेटा के लिए मास्किंग लागू करते हैं। यद्यपि सर्वर से क्लाइंट तक आपको डेटा पर मास्किंग लगाने की आवश्यकता नहीं है। अनुभाग 5 पढ़ें । विनिर्देशन में डेटा निर्धारण । यहाँ मेरे अपने कार्यान्वयन से कॉपी-पेस्ट है। यह रेडी-टू-यूज़ कोड नहीं है, और इसे संशोधित किया जाना है, मैं इसे पोस्ट कर रहा हूं कि वेबसोकेट फ्रेमिंग के साथ पढ़ने / लिखने का एक विचार और समग्र तर्क देने के लिए। इस लिंक पर जाएं ।
  6. फ़्रेमिंग लागू होने के बाद, सुनिश्चित करें कि आपको सॉकेट्स का उपयोग करके डेटा सही तरीके से प्राप्त होता है। उदाहरण के लिए रोकने के लिए कि कुछ संदेश एक में विलय हो जाते हैं, क्योंकि टीसीपी अभी भी स्ट्रीम आधारित प्रोटोकॉल है। इसका मतलब है कि आपको बाइट्स की केवल विशिष्ट मात्रा को पढ़ना होगा। संदेश की लंबाई हमेशा हेडर पर आधारित होती है और हेडर में डेटा लंबाई का विवरण दिया जाता है। इसलिए जब आप सॉकेट से डेटा प्राप्त कर रहे हैं, तो पहले 2 बाइट्स प्राप्त करें, फ़्रेमिंग विनिर्देश के आधार पर हेडर से विवरण प्राप्त करें, फिर यदि मुखौटा एक और 4 बाइट्स प्रदान करता है, और फिर डेटा की लंबाई के आधार पर लंबाई 1, 4 या 8 बाइट्स हो सकती है। और डेटा के बाद यह स्व। आपके द्वारा इसे पढ़ने के बाद, डीमॉस्किंग लागू करें और आपका संदेश डेटा उपयोग करने के लिए तैयार है।
  7. आप कुछ डेटा प्रोटोकॉल का उपयोग करना चाह सकते हैं , मैं JSON का उपयोग ट्रैफ़िक अर्थव्यवस्था के कारण और जावास्क्रिप्ट में क्लाइंट की ओर से उपयोग करने में आसान बनाने की सलाह देता हूं। सर्वर साइड के लिए आप कुछ पार्सरों की जांच करना चाहते हैं। उनमें से बहुत सारे हैं, Google वास्तव में सहायक हो सकता है।

अपने स्वयं के WebSockets प्रोटोकॉल को लागू करने से निश्चित रूप से कुछ लाभ और महान अनुभव प्राप्त होते हैं और साथ ही प्रोटोकॉल पर नियंत्रण होता है। लेकिन आपको इसे करने में कुछ समय बिताना होगा, और यह सुनिश्चित करना होगा कि कार्यान्वयन अत्यधिक विश्वसनीय है।

उसी समय में आपके पास उन समाधानों का उपयोग करने के लिए तैयार हो सकता है जो Google (फिर से) के पास पर्याप्त हैं।


मुझे लगता है कि मैं हाथ मिलाने पर अड़ा हुआ हूं। जब एक नया कनेक्शन प्राप्त होता है, तो मुझे क्लाइंट को लंबी कुंजी के शॉर्ट 1 हैश के साथ-साथ शॉर्ट की राइट को भेजना पड़ता है?
टोनो नाम

मैंने खंड 3 में अधिक जानकारी जोड़ी है। यह सर्वर साइड से हैंडशेक पर अधिक विवरण का वर्णन करता है।
मोका

1
साथ ही यह सुनिश्चित करें कि यदि अनुरोध प्रोटोकॉल प्रदान किया जाता है, तो Sec-WebSocket-Protocol लाइन के जवाब में समान का उपयोग करें। लेकिन केवल अगर अनुरोध में प्रदान किया गया है। साथ ही आपको प्रतिक्रिया के लिए संस्करण की आवश्यकता नहीं है। और अंत में एक और NewLine जोड़ें। साथ ही UTF8 का उपयोग करके एन्कोडेड पूरी प्रतिक्रिया स्ट्रिंग भेजें: Encoding.UTF8.GetBytes (responseBytes)
मोका

हम करीब हैं। मदद के लिए बहुत बहुत धन्यवाद। मैं अब एक संदेश भेजने में सक्षम हूं, लेकिन संदेश एन्क्रिप्टेड है मुझे विश्वास है। मेरे संपादन पर एक नज़र डालें कि मैं जल्द ही काम करना शुरू कर दूंगा ...
टोनो नाम

आपको डेटा फ़्रेमिंग को लागू करना होगा, यह मैं मानता हूं कि WebSockets प्रोटोकॉल के कार्यान्वयन में सबसे जटिल बिट है। मैं अपने कार्यान्वयन से कॉपी-पेस्ट कोड को पोस्ट में जोड़ूंगा, लेकिन सुनिश्चित करें कि आप इसे संपादित करते हैं, क्योंकि इसमें कुछ चीजें बदलनी हैं, लेकिन कुल मिलाकर फ्रेम के साथ काम करने का एक विचार और तर्क देता है।
मोका

9

(ओपी की ओर से पोस्ट किया गया जवाब)

मैं अब डेटा भेजने में सक्षम हूं। यह आपके उत्तरों और @Maksims Mihejevs के कोड की बदौलत कार्यक्रम का मेरा नया संस्करण है।

सर्वर

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));
        }
    }
}

जावास्क्रिप्ट:

<!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>

जब मैं उस कोड को चलाता हूं तो मैं क्लाइंट और सर्वर दोनों से डेटा भेजने और प्राप्त करने में सक्षम हूं। एकमात्र समस्या यह है कि सर्वर पर आने पर संदेशों को एन्क्रिप्ट किया जाता है। यहाँ कार्यक्रम कैसे चलता है के चरण हैं:

यहाँ छवि विवरण दर्ज करें

ध्यान दें कि क्लाइंट से संदेश कैसे एन्क्रिप्ट किया गया है।


2
आपके उदाहरण के साथ कुछ गलत है, जब मैं प्रेस दर्ज करता हूं तो कनेक्शन बंद हो जाता है।
रिचर्ड एगुइरे

@ रीचर्डअगिर्रे: मैंने इसे ओपी की ओर से पोस्ट किया (जवाब की पहली पंक्ति देखें) - वर्तमान में उन्हें आपके संदेश के बारे में सूचित नहीं किया जाएगा। आप उन्हें प्रश्न के तहत पिंग करने की कोशिश कर सकते हैं, लेकिन उन्हें इससे कहीं अधिक विस्तार की आवश्यकता है।
जूल

6

WebSockets एक प्रोटोकॉल के साथ कार्यान्वित किया जाता है जिसमें क्लाइंट और सर्वर के बीच हैंडशेक शामिल है । मुझे नहीं लगता कि वे सामान्य सॉकेट की तरह बहुत काम करते हैं। प्रोटोकॉल पर पढ़ें, और बात करने के लिए अपना आवेदन प्राप्त करें। वैकल्पिक रूप से, मौजूदा WebSocket लाइब्रेरी या .Net4.5beta का उपयोग करें, जिसमें एक WebSocket API है


बेशक वे सामान्य सॉकेट की तरह बहुत काम करते हैं। सॉकेट अनुप्रयोग प्रोटोकॉल की तुलना में निचले स्तर पर है और, जैसे कि, इस पर निर्भर नहीं है। इसका मतलब है कि आप सॉकेट पर एफ़टीपी, एसएमटीपी, एचटीटीपी, वेबसॉकेट्स आदि चला सकते हैं। यह लागू करने वाले पर निर्भर है कि वह प्रोटोकॉल का सही ढंग से पालन करता है या कोई भी सर्वर से बात नहीं कर पाएगा।
एसआरएम

4

मैं कहीं भी (19 जनवरी के रूप में) एक सरल काम कर उदाहरण मिल सकता है, तो यहाँ एक अद्यतन संस्करण है। मेरे पास क्रोम संस्करण 71.0.3578.98 है।

C # वेबसोकेट सर्वर:

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;
    }
}
}

क्लाइंट html और जावास्क्रिप्ट:

<!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>


3

मुद्दा

जब से आप WebSocket का उपयोग कर रहे हैं, स्पेंडर सही है। WebSocket से प्रारंभिक डेटा को प्राप्त करने के बाद, आपको आगे की जानकारी प्रवाहित करने से पहले C # सर्वर से हैंडशेक संदेश भेजने की आवश्यकता है।

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

उन पंक्तियों के साथ कुछ।

आप कुछ और शोध कर सकते हैं कि कैसे वेब 3 कार्ड w3 या google पर काम करता है।

लिंक और संसाधन

यहां एक प्रोटोकॉल विवरण दिया गया है: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76#section-1.3

काम करने के उदाहरणों की सूची:


इसके अलावा, मैं UTF8 एन्कोडिंग का उपयोग कर रहा हूं। क्या मुझे ASCII जैसे किसी अन्य का उपयोग करना चाहिए?
टोनो नाम

@TonoNam: जहां तक ​​मुझे पता है, UTF8 एन्कोडिंग सही है - हालांकि मैं एचटीएमएल 5 विशेषज्ञ नहीं हूं, इसलिए मुझे यकीन नहीं है।
caesay

मैंने इसे सफारी के साथ काम किया !!! मैं इसे गूगल क्रोम के साथ काम करने की जरूरत है, हालांकि। सभी उदाहरण कनेक्ट होते हैं लेकिन उनमें से कोई भी सफलतापूर्वक डेटा नहीं भेजता है। मैं कोशिश करता रहूँगा। सहायता के लिए बहुत - बहुत धन्यवाद!
टोनो नाम

Ofcourse .... अगर मैं अभी भी इसे काम नहीं कर रहा हूँ तो मैं इस सवाल का जवाब दूंगा! मैं इस काम को देखने के लिए उत्सुक हूं। मदद के लिए धन्यवाद
टोनो नाम

आपका प्रोटोकॉल युक्ति लिंक पुराना है। सफारी अभी भी इसका उपयोग करता है लेकिन अन्य ब्राउज़र असंगत RFC 6455 पर चले गए हैं । इसके अलावा, जब आप सही होते हैं कि प्रारंभिक कनेक्शन के लिए कुछ बातचीत की आवश्यकता होती है, तो आगे के संदेश नहीं आते हैं।
सिमोनक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.