একটি "হ্যালো ওয়ার্ল্ড" ওয়েবস্কট উদাহরণ তৈরি করা


86

আমি নিম্নলিখিত কোডটি কেন কাজ করতে পারি না তা বুঝতে পারছি না। আমি আমার সার্ভার কনসোল অ্যাপ্লিকেশনটিতে জাভাস্ক্রিপ্টের সাথে সংযোগ করতে চাই। এবং তারপরে সার্ভারে ডেটা প্রেরণ করুন।

সার্ভার কোডটি এখানে:

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

যখন আমি সেই কোডটি চালাই তখন যা ঘটে তা ঘটে:

নোট করুন যে আমি যখন জাভাস্ক্রিপ্ট চালাচ্ছি তখন সার্ভার গ্রহণ করে এবং সফলভাবে একটি সংযোগ স্থাপন করে। যদিও জাভাস্ক্রিপ্ট ডেটা পাঠাতে সক্ষম নয়। আমি যখনই প্রেরণ পদ্ধতিটি রাখি তখন কোনও সংযোগ স্থাপন করা হলেও এটি প্রেরণ করবে না will আমি এই কাজটি কীভাবে করব?


10
এই "প্রশ্ন" আর কোনও প্রশ্ন বলে মনে হয় না এবং এটি স্ট্যাকওভারফ্লোর ফর্ম্যাটের সাথে সত্যিই উপযুক্ত নয়। FWIW, ক্লায়েন্ট বার্তা নয় এনক্রিপ্ট এটা হচ্ছে ছদ্মবেশী একটি র্যান্ডম মান ফ্রেম একটি অংশ হিসাবে প্রেরণ করা হয় বিরুদ্ধে XOR'ing দ্বারা (obfuscated)। এই প্রোটোকল বিশদটি প্রক্সি সার্ভারগুলির বিরুদ্ধে বিষক্রিয়াজনিত আক্রমণগুলি এড়ানোর জন্য উপস্থিত রয়েছে যা ট্র্যাফিককে ভুল বুঝে।
এরিকল

4
ধন্যবাদ, এই উত্তরটি খুব সহায়ক :) :) ওহে, কেবল একটি বিষয়, এটি "স্থির বেসরকারী স্ট্রিং গাইড =" 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 ";" জিনিস সবসময় ধ্রুব হয়? যদি না হয় তবে আমি এই মানগুলি কোথায় পাব?
চার্মি

4
আমি এটি পেয়েছি: "কোনও সার্ভার অবশ্যই ক্লায়েন্টকে
প্রেরণকারী

6
আপনার সম্ভবত আসল প্রশ্নটি অক্ষত থাকতে হবে। প্রশ্নের উদ্দেশ্য হ'ল সমস্যাটি সমাধান করা নয়, বিষয়টি উপস্থাপন করা। উত্তরগুলি, যেমন আপনি অনুমান করতে পারেন, সমাধানগুলির জন্য।
কেহলান ক্রুমমে

4
ওয়েবসকেট ইউআরএল কেন '/ পরিষেবা' দিয়ে শেষ হয় (ডাব্লুএস: // লোকালহোস্ট: 8080 / পরিষেবা)? শুধু 'ডাব্লুএস: // লোকালহোস্ট: 8080' কেন নয়?
এবং

উত্তর:


72

ওয়েবসকেটস এমন প্রোটোকল যা টিসিপি স্ট্রিমড সংযোগের উপর নির্ভর করে। যদিও ওয়েবসকেটগুলি বার্তা ভিত্তিক প্রোটোকল।

আপনি যদি নিজের প্রোটোকলটি প্রয়োগ করতে চান তবে আমি সর্বশেষ এবং স্থিতিশীল স্পেসিফিকেশন (18/04/12 এর জন্য) আরএফসি 6455 ব্যবহার করার পরামর্শ দিচ্ছি । এই স্পেসিফিকেশনটিতে হ্যান্ডশেক এবং ফ্রেমিং সম্পর্কিত সমস্ত প্রয়োজনীয় তথ্য রয়েছে। পাশাপাশি বেশিরভাগ বর্ণনার সাথে সাথে ব্রাউজারের পাশাপাশি সার্ভারের দিক থেকেও আচরণ করা যায়। আপনার কোডটি প্রয়োগের সময় সার্ভার দিক সম্পর্কে সুপারিশগুলি যা বলে তা অনুসরণ করার জন্য এটির সুপারিশ করা হয়।

কয়েকটি কথায়, আমি ওয়েবস্কোকেটগুলির সাথে এইভাবে কাজ করার বর্ণনা করব:

  1. সার্ভার সকেট তৈরি করুন (সিস্টেম.নেট.সকেটস) এটি নির্দিষ্ট পোর্টের সাথে আবদ্ধ করুন এবং সংযোগগুলির অ্যাসিনক্রোনাস গ্রহণের সাথে শুনতে থাকুন। এরকম কিছু:

    সকেট সার্ভারসকেট = নতুন সকেট (অ্যাড্রেসফ্যামিলি.আইন্টারনেটওয়ার্ক, সকেটটাইপ। স্ট্রিম, প্রোটোকল টাইপ.আইপি);
    সার্ভারসকেট.বাইন্ড (নতুন আইপিএন্ডপয়েন্ট) (আইপিএড্রেস.আনি, 8080));
    সার্ভারসকেট.লিস্টেন (128);
    সার্ভারসকেট.বেগিনঅ্যাকসেপ্ট (নাল, 0, অনঅ্যাকসেপ্ট, নাল);
  2. আপনার "অনঅসেপ্ট" ফাংশন গ্রহণ করা উচিত যা হ্যান্ডশেক বাস্তবায়ন করবে। ভবিষ্যতে এটি অন্য থ্রেডে থাকতে হবে যদি সিস্টেমটি প্রতি সেকেন্ডে বিপুল পরিমাণ সংযোগ পরিচালনা করে।

    প্রাইভেট শূন্য অনঅ্যাকসেপ্ট (আইএএনসিআরসিআউট ফলাফল) {
    চেষ্টা করুন
        সকেট ক্লায়েন্ট = নাল;
        যদি (সার্ভারসকেট! = নাল && সার্ভারসকেট.আইসবাউন্ড) {
            ক্লায়েন্ট = সার্ভারসকেট.এন্ডঅ্যাকসেপ্ট (ফলাফল);
        }
        যদি (ক্লায়েন্ট! = নাল) {
            / * ক্লায়েন্টসকেট হ্যান্ডশেকিং এবং পরিচালনা * /
        }
    } ধরা (সকেট এক্সসেপশন ব্যতিক্রম) {
    
    অবশেষে {
        যদি (সার্ভারসকেট! = নাল && সার্ভারসকেট.আইসবাউন্ড) {
            সার্ভারসকেট.বেগিনঅ্যাকসেপ্ট (নাল, 0, অনঅ্যাকসেপ্ট, নাল);
        }
    }
    }
  3. সংযোগ স্থাপনের পরে, আপনাকে হ্যান্ডশেক করতে হবে । স্পেসিফিকেশনটির ভিত্তিতে 1.3 খোলার হ্যান্ডশেক , সংযোগ স্থাপনের পরে আপনি কিছু তথ্যের সাথে বেসিক এইচটিটিপি অনুরোধ পাবেন। উদাহরণ:

    জিইটি / চ্যাট এইচটিটিপি / 1.1
    হোস্ট: server.example.com
    আপগ্রেড: ওয়েবসকেট
    সংযোগ: আপগ্রেড
    সেক-ওয়েবসকেট-কী: dGhlIHNhbXBsZSBub25jZQ ==
    উত্স: http://example.com
    সেক-ওয়েবসকেট-প্রোটোকল: চ্যাট, সুপারচ্যাট
    সেক-ওয়েবসকেট-সংস্করণ: 13

    এই উদাহরণটি প্রোটোকল 13 এর সংস্করণ ভিত্তিক। বিভিন্ন ব্রাউজার আপনাকে কিছু অতিরিক্ত ডেটা প্রেরণ করতে পারে। উদাহরণস্বরূপ ব্রাউজার এবং ওএসের বিশদ, ক্যাশে এবং অন্যান্য।

    প্রদত্ত হ্যান্ডশেক বিশদটির ভিত্তিতে, আপনাকে উত্তর রেখাগুলি তৈরি করতে হবে, সেগুলি বেশিরভাগই সমান, তবে এতে অ্যাক্পেট-কী থাকবে, যা প্রদত্ত সেক-ওয়েবস্কট-কী ভিত্তিক। স্পেসিফিকেশন 1.3 এ প্রতিক্রিয়া কী জেনারেট করা যায় তা স্পষ্টভাবে বর্ণিত হয়েছে। এখানে আমার ফাংশনটি আমি ভি 13 এর জন্য ব্যবহার করছি:

    স্ট্যাটিক প্রাইভেট স্ট্রিং গাইড = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
    ব্যক্তিগত স্ট্রিং AcceptKey (রেফ স্ট্রিং কী) {
        স্ট্রিং লংকি = কী + গাইড;
        SHA1 sha1 = SHA1CryptoServiceProvider.Create ();
        বাইট [] হ্যাশবাইটস = sha1.কম্পিউট হ্যাশ (সিস্টেম.টেক্সট। এনকোডিং.এএসসিআইআই.গেটবাইটস (লংকি));
        কনভার্ট করুন.টোবেস 64 স্ট্রিং (হ্যাশবাইটস);
    }
    

    হ্যান্ডশেকের উত্তরটি দেখতে এমন দেখাচ্ছে:

    HTTP / 1.1 101 সুইচিং প্রোটোকল
    আপগ্রেড: ওয়েবসকেট
    সংযোগ: আপগ্রেড
    সেক-ওয়েবসকেট-স্বীকার করুন: s3pPLMBiTxaQ9kYGzzhZRbK + xOo =

    তবে মেনে নেওয়া কীটি ক্লায়েন্টের সরবরাহিত কী এবং আমি পূর্বে সরবরাহকৃত পদ্ধতি অ্যাসিপটকে'র ভিত্তিতে উত্পন্ন একটি হতে হবে। পাশাপাশি, নিশ্চিত হয়ে নিন কী স্বীকারের শেষ চরিত্রের পরে আপনি দুটি নতুন লাইন "\ r \ n \ r \ n" রেখেছেন।

  4. সার্ভার থেকে হ্যান্ডশেক উত্তর প্রেরণের পরে, ক্লায়েন্টকে " অনোপেন " ফাংশনটি ট্রিগার করা উচিত , এর অর্থ আপনি পরে বার্তা প্রেরণ করতে পারেন।
  5. বার্তা কাঁচা বিন্যাসে পাঠানো হয় না, কিন্তু তারা আছে ডেটা সরবরাহ । এবং ক্লায়েন্ট থেকে সার্ভারের পাশাপাশি ম্যাসেজ শিরোনামে প্রদত্ত 4 বাইটের ভিত্তিতে ডেটা মাস্কিং প্রয়োগ করে implement যদিও সার্ভার থেকে ক্লায়েন্টে আপনাকে ডেটা দিয়ে মাস্কিং প্রয়োগ করতে হবে না। বিভাগ 5 পড়ুন । নির্দিষ্টকরণে ডেটা ফ্রেমিং । এখানে আমার নিজের প্রয়োগ থেকে কপি-পেস্ট করুন। এটি ব্যবহারের জন্য প্রস্তুত কোড নয়, এবং এটি সংশোধন করতে হবে, আমি কেবল ওয়েবস্কট ফ্রেমিংয়ের সাথে পড়ার / লেখার সামগ্রিক যুক্তি এবং ধারণা দেওয়ার জন্য এটি পোস্ট করছি। এই লিঙ্কে যান ।
  6. ফ্রেমিং কার্যকর হওয়ার পরে, সকেটগুলি ব্যবহার করে আপনি সঠিকভাবে ডেটা পেয়েছেন তা নিশ্চিত করুন। উদাহরণস্বরূপ, কিছু বার্তা একটিতে একত্রী হয়ে যায় তা রোধ করতে, কারণ টিসিপি এখনও স্ট্রিম ভিত্তিক প্রোটোকল। এর অর্থ আপনাকে কেবলমাত্র নির্দিষ্ট পরিমাণ বাইট পড়তে হবে। বার্তার দৈর্ঘ্য সর্বদা শিরোনামের উপর ভিত্তি করে থাকে এবং শিরোনামে এটি ডেটা দৈর্ঘ্যের বিবরণ দেয় self সুতরাং আপনি যখন সকেট থেকে ডেটা গ্রহণ করবেন, প্রথমে 2 বাইট পাবেন, ফ্রেমিং নির্দিষ্টকরণের ভিত্তিতে শিরোনামের থেকে বিশদটি পান, তারপরে যদি মুখোশ আরও 4 বাইট সরবরাহ করে এবং তারপরে দৈর্ঘ্যের উপর ভিত্তি করে দৈর্ঘ্য 1, 4 বা 8 বাইট হতে পারে। এবং ডেটা পরে এটি স্বয়ং। আপনি এটি পড়ার পরে, ডেমসিং প্রয়োগ করুন এবং আপনার বার্তার ডেটা ব্যবহারের জন্য প্রস্তুত।
  7. আপনি কিছু ডেটা প্রোটোকল ব্যবহার করতে চাইতে পারেন , আমি JSON কারণে ট্র্যাফিক অর্থনীতি এবং জাভাস্ক্রিপ্টে ক্লায়েন্টের পক্ষে ব্যবহার করা সহজ। সার্ভার সাইডের জন্য আপনি কিছু পার্সার পরীক্ষা করতে চাইতে পারেন। এগুলির মধ্যে অনেকগুলি রয়েছে, গুগল সত্যই সহায়ক হতে পারে।

নিজস্ব ওয়েবসকেট প্রোটোকল বাস্তবায়নের অবশ্যই কিছু সুবিধা এবং দুর্দান্ত অভিজ্ঞতা রয়েছে যা আপনি নিজেরাই প্রোটোকলের উপর নিয়ন্ত্রণ রাখেন। তবে আপনাকে এটি করার জন্য কিছুটা সময় ব্যয় করতে হবে, এবং নিশ্চিত হওয়া উচিত যে বাস্তবায়ন অত্যন্ত নির্ভরযোগ্য।

একই সময়ে আপনার কাছে গুগল (আবার) পর্যাপ্ত পরিমাণে সমাধানগুলি ব্যবহার করতে প্রস্তুত থাকতে পারে।


আমার ধারণা আমি হাতের মুঠোয় আটকে আছি নতুন সংযোগ পেলে আমাকে ক্লায়েন্টের কাছে লম্বা কী এর শ 1 হ্যাশ প্লাস শর্ট কী ডান পাঠাতে হবে?
টোনো নাম

আমি বিভাগে 3 আরও তথ্য যুক্ত করেছি। এটি সার্ভার পাশ থেকে হ্যান্ডশেক আরও বিশদ বর্ণনা করে।
মোক

4
পাশাপাশি নিশ্চিত হয়ে নিন যে যদি অনুরোধ প্রোটোকল সরবরাহ করা থাকে তবে সেক-ওয়েবস্কট-প্রোটোকল লাইনের প্রতিক্রিয়াতে একই ব্যবহার করুন। তবে কেবল সেখানে যদি অনুরোধে সরবরাহ করা হয়। পাশাপাশি আপনার প্রতিক্রিয়াটির জন্য সংস্করণ দরকার নেই। এবং শেষ পর্যন্ত আরও একটি নিউলাইন যুক্ত করুন। পাশাপাশি ইউটিএফ 8 ব্যবহার করে এনকোড করা পুরো প্রতিক্রিয়াটির স্ট্রিং প্রেরণ করুন: এনকোডিং
UTআউটএফ 8. গেটবাইটস

আমরা বন্ধ. সাহায্যের জন্য অনেক ধন্যবাদ। আমি এখনই একটি বার্তা পাঠাতে সক্ষম হয়েছি তবে বার্তাটি এনক্রিপ্ট করা আছে বিশ্বাস করি। আমার সম্পাদনাটি একবার দেখুন যে আমি শীঘ্রই কাজ শুরু করব ...
টোনো নাম

আপনাকে ডেটা ফ্রেমিং বাস্তবায়ন করতে হবে, এটিই আমি বিশ্বাস করব যে ওয়েবসকেটস প্রোটোকল বাস্তবায়নের ক্ষেত্রে সবচেয়ে জটিল বিট। আমি আমার প্রয়োগ থেকে কপি-পেস্ট কোডটি পোস্টে যুক্ত করব, তবে নিশ্চিত হয়ে নিন যে আপনি এটি সম্পাদনা করেছেন, কারণ এটিতে কিছু পরিবর্তন করার আছে তবে সামগ্রিকভাবে ফ্রেমের সাথে কাজ করার ধারণা এবং যুক্তি দেয়।
মোক

10

(ওপির পক্ষে উত্তর পোস্ট করেছেন)

আমি এখন তথ্য প্রেরণ করতে সক্ষম। এটি আপনার উত্তর এবং @ ম্যাক্সিমস মিহেজেভসের কোডকে ধন্যবাদ প্রোগ্রামটির আমার নতুন সংস্করণ।

সার্ভার

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>

আমি যখন এই কোডটি চালনা করি তখন আমি ক্লায়েন্ট এবং সার্ভার উভয়ের কাছ থেকে ডেটা প্রেরণ এবং গ্রহণ করতে সক্ষম হয়েছি। একমাত্র সমস্যাটি হ'ল বার্তাগুলি সার্ভারে পৌঁছালে এনক্রিপ্ট করা হয়। প্রোগ্রামটি কীভাবে চালিত হয় তার পদক্ষেপগুলি এখানে:

এখানে চিত্র বর্ণনা লিখুন

ক্লায়েন্টের বার্তাটি কীভাবে এনক্রিপ্ট করা হয়েছে তা নোট করুন।


5

ওয়েবসকেটগুলি এমন একটি প্রোটোকল দিয়ে প্রয়োগ করা হয় যা ক্লায়েন্ট এবং সার্ভারের মধ্যে হ্যান্ডশেক জড়িত । তারা সাধারণ সকেটের মতো খুব বেশি কাজ করে তা আমি কল্পনা করি না। প্রোটোকলটি পড়ুন এবং এটির সাথে কথা বলার জন্য আপনার অ্যাপ্লিকেশনটি পান। বিকল্পভাবে, একটি বিদ্যমান ওয়েবসকেট লাইব্রেরি, অথবা। নেট 4.5 বেটা ব্যবহার করুন যা একটি ওয়েবসকেট API রয়েছে


অবশ্যই তারা সাধারণ সকেটের মতো খুব বেশি কাজ করে। সকেটটি অ্যাপ্লিকেশন প্রোটোকলের চেয়ে নিম্ন স্তরে এবং যেমন এর উপর নির্ভর করে না। এর অর্থ আপনি কোনও সকেটে এফটিপি, এসএমটিপি, এইচটিটিপি, ওয়েবসকেটস, ইত্যাদি চালাতে পারেন। তিনি প্রোটোকলটি সঠিকভাবে অনুসরণ করেছেন বা সার্ভারের সাথে কেউ কথা বলতে সক্ষম হবে না তা নিশ্চিত করার জন্য এটি প্রয়োগকারীের উপর নির্ভর করে।
এসআরএম

5

আমি যে কোনও জায়গায় একটি সাধারণ কাজের উদাহরণ খুঁজে পাইনি (জানুয়ারী 19 হিসাবে), তাই এখানে একটি আপডেট সংস্করণ রয়েছে। আমার কাছে ক্রোম সংস্করণ 71.0.3578.98 রয়েছে।

সি # ওয়েবসকেট সার্ভার:

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

ক্লায়েন্ট এইচটিএমএল এবং জাভাস্ক্রিপ্ট:

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

সমস্যা

আপনি যেহেতু ওয়েবস্কট ব্যবহার করছেন তাই ব্যয়কারী সঠিক। ওয়েবসকেট থেকে প্রাথমিক তথ্য পুনরুদ্ধারের পরে, আরও কোনও তথ্য প্রবাহিত হওয়ার আগে আপনাকে সি # সার্ভার থেকে হ্যান্ডশেক বার্তা পাঠাতে হবে।

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

এই লাইন বরাবর কিছু।

ওয়েবস্কট কীভাবে ডাব্লু 3 বা গুগলে কাজ করে সে সম্পর্কে আপনি আরও কিছু গবেষণা করতে পারেন।

লিঙ্ক এবং সংস্থান

এখানে একটি প্রোটোকল specifcation হল: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76#section-1.3

কাজের উদাহরণগুলির তালিকা:


এছাড়াও আমি ইউটিএফ 8 এনকোডিং ব্যবহার করছি। আমার কি এসএসআইআই এর মতো আলাদা কোনও ব্যবহার করা উচিত?
টোনো নাম

@ টোননাম: আমি যতদূর জানি ইউটিএফ 8 এনকোডিং সঠিক - যদিও আমি কোনও HTML5 বিশেষজ্ঞ নই, তাই আমি নিশ্চিতভাবে জানি না।
সিএসে

আমি সাফারি দিয়ে কাজ করেছি !!! যদিও এটি গুগল ক্রোম দিয়ে কাজ করা আমার প্রয়োজন। সমস্ত উদাহরণ সংযোগ করে তবে তাদের কোনওটিই সাফল্যের সাথে ডেটা প্রেরণ করে না। আমি চেষ্টা চালিয়ে যাব। সহযোগিতার জন্য অসংখ্য ধন্যবাদ!
টোনো নাম

অবশ্যই .... যদি আমি এখনও এটি কাজ না করে আমি এই প্রশ্নটিকে অনুগ্রহ করে দেব! আমি এই কাজ দেখতে সত্যিই আগ্রহী। সহায়তার জন্য ধন্যবাদ
টোনো নাম

আপনার প্রোটোকল নির্দিষ্ট লিঙ্কটি পুরানো। সাফারি এখনও এটি ব্যবহার করে তবে অন্যান্য ব্রাউজারগুলি বেমানান আরএফসি 6455 এ চলে গেছে । এছাড়াও, আপনি যখন সঠিক হয়েছিলেন যে প্রাথমিক সংযোগের জন্য কিছু আলোচনার প্রয়োজন হয়, পরবর্তী বার্তা দেয় না।
সিমোনক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.