প্রতিক্রিয়াশীল এক্সটেনশনগুলি ব্যবহার করে অ্যাসিঙ্ক নেটওয়ার্ক প্রোগ্রামিং


25

socketবছর পূর্বে কিছু (কম-বেশি বা কম) "নিম্ন-স্তরের" অ্যাসিঙ্ক প্রোগ্রামিং করার পরে (ইভেন্ট-ভিত্তিক অ্যাসিনক্রোনাস প্যাটার্ন (ইএপি) ফ্যাশনে) এবং সম্প্রতি একটি " TcpListenerঅ্যাসিনক্রোনাস প্রোগ্রামিং মডেল (এপিএম) " তে সরানো এবং তারপরে async/await(টাস্ক-ভিত্তিক অ্যাসিনক্রোনাস প্যাটার্ন (টিএপি) ) এ যাওয়ার চেষ্টা করলাম আমি এই সমস্ত 'নিম্ন স্তরের নদীর গভীরতানির্ণয়' নিয়ে বিরক্ত থাকার মতো অনেক কিছুই করেছি। সুতরাং আমি অনুমান ছিল; কেন RXযেতে দেবেন না ( প্রতিক্রিয়াশীল এক্সটেনশানস ) যেহেতু এটি আমার সমস্যাযুক্ত ডোমেনে আরও বেশি ছড়িয়ে পড়ে।

আমার লিখিত প্রচুর কোডটি অনেক ক্লায়েন্টের সাথে আমার অ্যাপ্লিকেশনে টিসিপির সাথে সংযোগ স্থাপন করে যা এরপরে দ্বি-মুখী (অ্যাসিঙ্ক) যোগাযোগ শুরু করে। ক্লায়েন্ট বা সার্ভার যে কোনও মুহুর্তে কোনও বার্তা প্রেরণের প্রয়োজন এবং এটি করার সিদ্ধান্ত নিতে পারে, সুতরাং এটি আপনার ক্লাসিক request/responseসেটআপ নয় তবে উভয় পক্ষের কাছে যা খুশি তাই পাঠাতে রিয়েল-টাইম, দ্বিমুখী, "লাইন" খোলা রয়েছে যখনই তারা চায়। (কারও কাছে যদি এটি বর্ণনা করার জন্য একটি ভাল নাম থাকে তবে আমি এটি শুনে খুশি হব!)।

"প্রোটোকল" অ্যাপ্লিকেশন প্রতি পৃথক হয় (এবং আমার প্রশ্নের সাথে সত্যই প্রাসঙ্গিক নয়)। আমার অবশ্য প্রাথমিক প্রশ্ন আছে:

  1. প্রদত্ত যে কেবলমাত্র একটি "সার্ভার" চলছে, তবে এটির অভ্যন্তরীণ ট্র্যাক রাখতে তাদের "রাষ্ট্রীয় মেশিন" এর অনেকগুলি (সাধারণত হাজার হাজার) সংযোগের (যেমন ক্লায়েন্টদের) আরও ভাল বর্ণনার অভাব রয়েছে তাদের ট্র্যাক রাখতে হবে রাজ্য ইত্যাদি, আপনি কোন পদ্ধতির পছন্দ করবেন? ইএপি / টোকা / APM? আরএক্স এমনকি একটি বিকল্প হিসাবে বিবেচনা করা হবে? তা না হলে কেন?

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

আমার অ্যাপ্লিকেশনগুলির বেশিরভাগই ভিওআইপি সম্পর্কিত; এটি এসআইপি সেন্টারগুলির এসআইপি বার্তা বা ফ্রিসুইচ / ওপেনসিআইপি ইত্যাদির মতো পিবিএক্স (সম্পর্কিত) বার্তাগুলি হতে পারে তবে আপনি এটি সহজতম ফর্মের মধ্যে অনেক "চ্যাট" ক্লায়েন্টকে পরিচালনা করার জন্য একটি "চ্যাট" সার্ভার কল্পনা করার চেষ্টা করতে পারেন। বেশিরভাগ প্রোটোকল হ'ল পাঠ্য ভিত্তিক (এএসসিআইআই)।

সুতরাং, পূর্বোক্ত কৌশলগুলির বিভিন্ন বিধি প্রয়োগ করার পরে আমি একটি বিষয় তৈরি করে আমার কাজটি সহজ করতে চাই যা আমি কেবল তাত্ক্ষণিকভাবে বলতে পারি, কোনটি IPEndpointশুনতে হবে তা বলুন এবং যখনই আগ্রহের কিছু চলছে তখন তা আমাকে বলতে হবে (যা আমি সাধারণত ইভেন্টগুলি ব্যবহার করুন, সুতরাং কিছু EAP সাধারণত অন্যান্য দুটি কৌশলগুলির সাথে মিশ্রিত হয়)। শ্রেণীর প্রোটোকলটি 'বোঝার' চেষ্টা করা বিরক্ত করা উচিত নয়; এটি কেবল ইনকামিং / আউটগোয়িং স্ট্রিংগুলি পরিচালনা করতে হবে। এবং এইভাবে, আরএক্সের প্রতি আমার নজর থাকায় আশা করা যায় যে (শেষ পর্যন্ত) কাজটি আরও সহজ করবে, আমি স্ক্র্যাচ থেকে একটি নতুন "ফ্রিডল" তৈরি করেছি:

using System;
using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;
using System.Reactive.Linq;
using System.Text;

class Program
{
    static void Main(string[] args)
    {
        var f = new FiddleServer(new IPEndPoint(IPAddress.Any, 8084));
        f.Start();
        Console.ReadKey();
        f.Stop();
        Console.ReadKey();
    }
}

public class FiddleServer
{
    private TcpListener _listener;
    private ConcurrentDictionary<ulong, FiddleClient> _clients;
    private ulong _currentid = 0;

    public IPEndPoint LocalEP { get; private set; }

    public FiddleServer(IPEndPoint localEP)
    {
        this.LocalEP = localEP;
        _clients = new ConcurrentDictionary<ulong, FiddleClient>();
    }

    public void Start()
    {
        _listener = new TcpListener(this.LocalEP);
        _listener.Start();
        Observable.While(() => true, Observable.FromAsync(_listener.AcceptTcpClientAsync)).Subscribe(
            //OnNext
            tcpclient =>
            {
                //Create new FSClient with unique ID
                var fsclient = new FiddleClient(_currentid++, tcpclient);
                //Keep track of clients
                _clients.TryAdd(fsclient.ClientId, fsclient);
                //Initialize connection
                fsclient.Send("connect\n\n");

                Console.WriteLine("Client {0} accepted", fsclient.ClientId);
            },
            //OnError
            ex =>
            {

            },
            //OnComplete
            () =>
            {
                Console.WriteLine("Client connection initialized");
                //Accept new connections
                _listener.AcceptTcpClientAsync();
            }
        );
        Console.WriteLine("Started");
    }

    public void Stop()
    {
        _listener.Stop();
        Console.WriteLine("Stopped");
    }

    public void Send(ulong clientid, string rawmessage)
    {
        FiddleClient fsclient;
        if (_clients.TryGetValue(clientid, out fsclient))
        {
            fsclient.Send(rawmessage);
        }
    }
}

public class FiddleClient
{
    private TcpClient _tcpclient;

    public ulong ClientId { get; private set; }

    public FiddleClient(ulong id, TcpClient tcpclient)
    {
        this.ClientId = id;
        _tcpclient = tcpclient;
    }

    public void Send(string rawmessage)
    {
        Console.WriteLine("Sending {0}", rawmessage);
        var data = Encoding.ASCII.GetBytes(rawmessage);
        _tcpclient.GetStream().WriteAsync(data, 0, data.Length);    //Write vs WriteAsync?
    }
}

আমি সচেতন যে, এই "ঝাঁকুনি" এ, কিছুটা বাস্তবায়নের সুনির্দিষ্ট বিশদ রয়েছে; এক্ষেত্রে আমি ফ্রিসুইচ ইএসএল নিয়ে কাজ করছি যাতে "connect\n\n"আরও বেশি জেনেরিক পদ্ধতির উপর রিফ্যাক্ট করার সময় ফিডলে থাকা অপসারণ করা উচিত।

আমি এও সচেতন যে সার্ভার ক্লাসে আমার বেনাম পদ্ধতিগুলিকে ব্যক্তিগত উদাহরণ পদ্ধতিগুলির রিফ্যাক্টর করতে হবে; আমি ঠিক নিশ্চিত নই যে কোন পদ্ধতি (যেমন " OnSomething" উদাহরণস্বরূপ) তাদের পদ্ধতি-নামের জন্য ব্যবহার করবেন?

এটি আমার ভিত্তি / শুরুর পয়েন্ট / ভিত্তি (যার জন্য কিছু "টুইট" প্রয়োজন)। এ সম্পর্কে আমার কিছু প্রশ্ন রয়েছে:

  1. উপরের প্রশ্নটি দেখুন "1"
  2. আমি কি সঠিক পথে রয়েছি? নাকি আমার "ডিজাইনের" সিদ্ধান্তগুলি অন্যায়?
  3. সংক্ষিপ্ত-ভিত্তিক: এটি হাজার হাজার ক্লায়েন্টের সাথে মোকাবেলা করবে (প্রকৃত বার্তাগুলিকে পার্সিং / পরিচালনা করে)
  4. ব্যতিক্রমগুলিতে: সার্ভারের কাছে "আপ" ক্লায়েন্টগুলির মধ্যে কীভাবে ব্যতিক্রমগুলি নেওয়া যায় তা আমি নিশ্চিত নই ("আরএক্স-ওয়াইজ"); একটি ভাল উপায় কি হবে?
  5. আমি এখন আমার সার্ভার ক্লাস থেকে যে কোনও সংযুক্ত ক্লায়েন্ট পেতে পারি (এটি ব্যবহার করে ClientId), ধরে নিচ্ছি যে আমি ক্লায়েন্টগুলিকে এক উপায়ে বা অন্য কোনও উপায়ে প্রকাশ করেছি এবং সেগুলিতে সরাসরি পদ্ধতিগুলি কল করি। আমি সার্ভার ক্লাসের মাধ্যমেও পদ্ধতিগুলি কল করতে পারি (উদাহরণস্বরূপ, Send(clientId, rawmessage)পদ্ধতিটি (যেখানে পরবর্তী দিকটি দ্রুত অন্য দিকে কোনও বার্তা পাওয়ার জন্য "সুবিধা" পদ্ধতি হবে)।
  6. এখান থেকে কোথায় (এবং কীভাবে) যাব আমি নিশ্চিত নই:
    • ক) আমার আগত বার্তাগুলি পরিচালনা করতে হবে; আমি কিভাবে এটি সেট আপ করব? আমি অবশ্যই স্ট্রিম অফ কোর্স পেতে পারি তবে প্রাপ্ত বাইটগুলি পুনরুদ্ধার করতে আমি কোথায় পরিচালনা করব? আমি মনে করি আমার কোনও ধরণের "অবজার্ভ স্ট্রিম" দরকার যা আমি সাবস্ক্রাইব করতে পারি? আমি কি এটিতে রাখব FiddleClientনাকি FiddleServer?
    • খ) ধরে নিচ্ছি যে এই FiddleClient/ FiddleServerক্লাসগুলি আরও সুনির্দিষ্ট FooClient/ FooServerশ্রেণি ব্যবহার করে তাদের অ্যাপ্লিকেশন নির্দিষ্ট প্রোটোকল হ্যান্ডলিং ইত্যাদির জন্য নির্দিষ্টভাবে প্রয়োগ না করা পর্যন্ত আমি ইভেন্টটি ব্যবহার করা এড়াতে চাই : আমি কীভাবে তাদের অন্তর্নিহিত 'ফিডাল'-শ্রেণিতে ডেটা পেতে যাব? আরও নির্দিষ্ট অংশের?

নিবন্ধ / লিঙ্কগুলি আমি ইতিমধ্যে পড়তে / স্কিমড / রেফারেন্সের জন্য ব্যবহার করেছি:


বিদ্যমান রিএ্যাকটিভসকেটস লাইব্রেরিটি একবার দেখুন
ফ্ল্যাগব্যাগ

2
আমি গ্রন্থাগার বা লিঙ্কগুলি খুঁজছি না (যদিও রেফারেন্সের জন্য তারা প্রশংসা করা হয়) তবে আমার প্রশ্ন এবং সাধারণ সেটআপে ইনপুট / পরামর্শ / সহায়তার জন্য। আমি আমার নিজের কোডটি উন্নত করতে শিখতে চাই এবং এটিকে কী দিকটি গ্রহণ করা উচিত, তার দিকনির্দেশনা এবং কনস ইত্যাদি বিবেচনা করতে হবে ইত্যাদি বিষয়ে নিজের মন তৈরি করতে আরও সক্ষম হতে চাই some কিছু লাইব্রেরির উল্লেখ না করে, এটিকে ছেড়ে দিন এবং এগিয়ে যান। আমি এই অভিজ্ঞতা থেকে শিখতে এবং আরএক্স / নেটওয়ার্ক প্রোগ্রামিংয়ের সাথে আরও অভিজ্ঞ হতে চাই।
রবিআইআই

অবশ্যই, তবে গ্রন্থাগারটি ওপেন উত্স হওয়ায় আপনি দেখতে পাচ্ছেন যে এটি কীভাবে কার্যকর করা হয়েছে
ফ্ল্যাশব্যাগ

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

আমি মনে করি হ্যান্ডশেকের সক্রিয় সদস্য হিসাবে সার্ভারটির পুনর্বিবেচনা করা ভাল হবে, সুতরাং, সেই সার্ভার সংযোগগুলির কথা শোনার পরিবর্তে সংযোগটি সূচনা করে। উদাহরণস্বরূপ, এখানে: কোডেপ্রজেক্ট

উত্তর:


1

... আমি একটি কাজ তৈরি করে আমার কাজটি সহজ করতে চাই যা আমি কেবল তাত্ক্ষণিকভাবে বলতে পারি, কোন আইপিএন্ডপয়েন্টটি শুনতে হবে এবং যখনই আগ্রহের কিছু চলছে তখন তা আমাকে জানিয়ে দিতে হবে ...

সেই বিবৃতিটি পড়ার পরে আমি অবিলম্বে "অভিনেতা" ভেবেছিলাম thought অভিনেতারা অবজেক্টগুলির সাথে খুব সমান, কেবলমাত্র তাদের কাছে কেবলমাত্র একটি ইনপুট থাকে যেখানে আপনি এটি বার্তাটি পাস করেন (সরাসরি বস্তুর পদ্ধতিগুলিকে কল করার পরিবর্তে) এবং তারা অবিচ্ছিন্নভাবে পরিচালনা করে। খুব সরল উদাহরণে ... আপনি অভিনেতা তৈরি করবেন এবং ফলাফল পাঠাতে আইপিএন্ডপয়েন্ট এবং অভিনেতার ঠিকানা দিয়ে একটি বার্তা পাঠিয়েছেন। এটি বন্ধ হয়ে যায় এবং এটি ব্যাকগ্রাউন্ডে কাজ করে। "আগ্রহের কিছু" ঘটে গেলে আপনি কেবল তা থেকে ফিরে শুনবেন। লোড হ্যান্ডেল করার জন্য আপনি যতগুলি অভিনেতাকে তত্ক্ষণাত্ করে দিতে পারেন ate

আমি। নেট এর কোনও অভিনেতার লাইব্রেরির সাথে পরিচিত নই যদিও আমি জানি যে এখানে কয়েকটি রয়েছে। আমি টিপিএল ডেটাফ্লো লাইব্রেরিটির সাথে পরিচিত (আমার বই http://DataflowBook.com এ এটির একটি বিভাগ থাকবে ) এবং এটি লাইব্রেরির সাথে একটি সাধারণ অভিনেতার মডেলটি প্রয়োগ করা সহজ হওয়া উচিত।


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