सिग्नल हब 2.0 .NET क्लाइंट को सर्वर हब में फिर से जोड़ने के लिए सबसे अच्छा अभ्यास


86

मैं एक मोबाइल एप्लिकेशन में .NET क्लाइंट के साथ सिग्नलआर 2.0 का उपयोग कर रहा हूं, जिसे विभिन्न प्रकार के डिस्कनेक्ट करने की आवश्यकता है। कभी-कभी सिग्नलआर क्लाइंट स्वचालित रूप से फिर से जुड़ जाता है - और कभी-कभी इसे HubConnection.Start()फिर से कॉल करके सीधे फिर से कनेक्ट करना पड़ता है।

चूंकि सिग्नलआर जादुई रूप से कुछ समय के लिए ऑटो-रिकंस्ट्रक्ट करता है, इसलिए मैं सोच रहा हूं कि क्या मैं एक सुविधा या कॉन्फ़िगरेशन सेटिंग को याद कर रहा हूं?

एक क्लाइंट सेट अप करने का सबसे अच्छा तरीका क्या है जो स्वचालित रूप से फिर से जुड़ता है?


मैंने जावास्क्रिप्ट उदाहरण देखे हैं जो Closed()ईवेंट को हैंडल करते हैं और फिर एन-सेकंड के बाद कनेक्ट करते हैं। क्या कोई अनुशंसित दृष्टिकोण है?

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

जवाबों:


71

मैं अंत में यह पता लगा। इस प्रश्न को शुरू करने के बाद से मैंने क्या सीखा है:

पृष्ठभूमि: हम Xamarin / Monotouch और .NET सिग्नलआर 2.0.3 क्लाइंट का उपयोग करके एक iOS ऐप बना रहे हैं। हम डिफ़ॉल्ट सिग्नलआर प्रोटोकॉल का उपयोग कर रहे हैं - और यह वेब सॉकेट के बजाय SSE का उपयोग करता प्रतीत होता है। मुझे अभी तक यकीन नहीं है कि Xamarin / Monotouch के साथ वेब सॉकेट का उपयोग करना संभव है। एज़्योर वेबसाइटों का उपयोग करके सब कुछ होस्ट किया जाता है।

हमें अपने सिग्नलआर सर्वर को जल्दी से फिर से कनेक्ट करने के लिए ऐप की आवश्यकता थी, लेकिन हमें ऐसी समस्याएं आ रही थीं, जहां कनेक्शन अपने आप ही पुन: कनेक्ट नहीं हुआ - या फिर से कनेक्ट होने में लगभग 30 सेकंड लगे (एक अंतर्निहित प्रोटोकॉल टाइमआउट के कारण)।

हमारे लिए परीक्षण समाप्त होने के तीन परिदृश्य थे:

परिदृश्य ए - पहली बार ऐप लोड होने पर कनेक्ट करना।यह पहले दिन से निर्दोष रूप से काम किया। 3 जी मोबाइल कनेक्शन पर भी यह कनेक्शन कम से कम .25 सेकंड में पूरा होता है। (यह मानते हुए कि रेडियो पहले से ही चालू है)

परिदृश्य बी - 30 सेकंड के लिए एप्लिकेशन निष्क्रिय / बंद होने के बाद सिग्नलआर सर्वर को फिर से कनेक्ट करना। इस परिदृश्य में, सिग्नलआर क्लाइंट अंततः बिना किसी विशेष कार्य के सर्वर पर अपने आप को फिर से कनेक्ट करेगा - लेकिन फिर से कनेक्ट करने के प्रयास से ठीक 30 सेकंड पहले प्रतीक्षा करना प्रतीत होता है। (हमारे ऐप के लिए बहुत धीमी गति से)

इस 30 सेकंड के वेटिंग पीरियड के दौरान हमने HubConnection.Start () कॉल करने की कोशिश की जिसका कोई असर नहीं हुआ। और HubConnection.Stop () को कॉल करने में भी 30 सेकंड लगते हैं। मुझे सिग्नलआर साइट पर एक संबंधित बग मिला जो हल किया गया प्रतीत होता है , लेकिन हमें अभी भी v2.0.3 में यही समस्या है।

परिदृश्य सी - 120 सेकंड या उससे अधिक समय तक ऐप के निष्क्रिय / बंद होने के बाद सिग्नलआर सर्वर से फिर से कनेक्ट करना। इस परिदृश्य में, सिग्नलआर ट्रांसपोर्ट प्रोटोकॉल पहले ही समाप्त हो चुका है, इसलिए क्लाइंट कभी भी स्वचालित रूप से पुन: कनेक्ट नहीं होता है। यह बताता है कि ग्राहक कभी-कभी क्यों होता था लेकिन हमेशा अपने आप को फिर से कनेक्ट नहीं कर रहा था। अच्छी खबर यह है कि हबकॉन्नेशन को कॉल करना। स्टार्ट () परिदृश्य ए की तरह लगभग तुरंत काम करता है।

इसलिए मुझे यह महसूस करने में थोड़ी देर लगी कि ऐप को 30 सेकंड बनाम 120+ सेकंड के लिए बंद करने के आधार पर पुन: कनेक्ट होने की स्थिति अलग-अलग थी। और हालांकि सिग्नलआर ट्रेसिंग लॉग्स रोशन करता है कि अंतर्निहित प्रोटोकॉल के साथ क्या हो रहा है, मुझे विश्वास नहीं है कि कोड में परिवहन स्तर की घटनाओं को संभालने का एक तरीका है। परिदृश्य बी में 30 सेकंड के बाद (बंद) घटना आग लग जाती है, तुरंत परिदृश्य सी में; राज्य संपत्ति का कहना है कि "कनेक्टेड" इन पुनरावर्ती प्रतीक्षा अवधि के दौरान; कोई अन्य प्रासंगिक घटना या विधियाँ नहीं;

समाधान: समाधान स्पष्ट है। हम इसके पुन: संयोजन जादू करने के लिए सिग्नलआर का इंतजार नहीं कर रहे हैं। इसके बजाय, जब ऐप सक्रिय होता है या जब फोन का नेटवर्क कनेक्शन बहाल हो जाता है, तो हम बस ईवेंट को साफ कर रहे हैं और हबकॉन्क्शन को डी-रेफर कर रहे हैं (इसे डिस्पोज नहीं कर सकते क्योंकि इसमें 30 सेकंड का समय लगता है, उम्मीद है कि कचरा संग्रह इसकी देखभाल करेगा ) और एक नया उदाहरण बना। अब सब कुछ बढ़िया काम कर रहा है। किसी कारण के लिए, मुझे लगा कि हमें एक नए कनेक्शन का उपयोग करने के बजाय एक निरंतर कनेक्शन का पुन: उपयोग करना चाहिए और फिर से कनेक्ट करना चाहिए।


5
क्या आप कुछ कोड पोस्ट करने के लिए तैयार होंगे? बस कैसे आप इसे संरचित पर उत्सुक हैं। मैं एक Xamarin एप्लिकेशन में एक PCL के भीतर से भी चैट ऐप में सिग्नल का उपयोग कर रहा हूं। यह वास्तव में बहुत अच्छा काम करता है सिवाय इसके कि मैं फोन को फिर से चालू करने के बाद फिर से काम करने के लिए पुन: संयोजन जादू प्राप्त नहीं कर सकता। मैं कसम खाता हूं कि आईटी क्राउड ने कहा कि मुझे बस इतना करना था।
टिमोथी ली रसेल

1
हाय एंडर 2050, मैंने देखा है कि एक बार एंड्रॉइड डिवाइस सर्वर से डिस्कनेक्ट हो जाता है तो फिर कभी दोबारा कनेक्ट नहीं होता है। इसलिए मैंने अलार्म को लागू किया था जो हर 5 मिनट चलता है और सर्वर हब के साथ सिग्नलआर कनेक्शन की जांच करता है। अलार्म टिक घटना मैं कनेक्शन ऑब्जेक्ट अशक्त है या नहीं है कनेक्शनआईड खाली है फिर कनेक्शन को फिर से स्थापित करें। लेकिन यह अच्छी तरह से काम नहीं करता है। उपयोगकर्ता को ऐप को मारने और इसे फिर से खोलने की आवश्यकता है। मैंने android और C # .net के लिए java-client का उपयोग सेवा केंद्र के लिए किया है। इस समस्या को हल करने के लिए आपकी मदद की तलाश है।
जिग्नेश

1
FYI करें, मोनो के पास वेब सॉकेट नहीं है। यही कारण है कि आपके Xamarin एप्लिकेशन हमेशा SSE का उपयोग करते हैं। आप एक कंसोल क्लाइंट लिख सकते हैं। यदि आप इसे मोनो पर चलाते हैं, तो यह SSE का उपयोग करेगा। यदि आप इसे विंडोज पर चलाते हैं (कम से कम विंडोज 8 क्योंकि 7 भी वेब सॉकेट का समर्थन नहीं करता है) तो यह वेब सॉकेट का उपयोग करेगा।
दारमासला

@ Ender2050 कृपया कुछ कोड उदाहरणों के साथ अपने समाधान पर विस्तार कर सकते हैं?
मैग्रेंस

हम एंड्रॉइड ऐप से सिग्नलआर हब (सिग्नलआर लाइब्रेरी संस्करण 2.2.2) के साथ फिर से कनेक्शन जारी कर रहे हैं जो "सिग्नलआर जावा क्लाइंट लाइब्रेरी" और आईओएस ऐप का उपयोग कर रहा है जो "सिग्नलआर ऑब्जेक्ट सी लाइब्रेरी" का उपयोग कर रहा है। दोनों प्लेटफ़ॉर्म पर क्लाइंट लाइब्रेरी को कुछ समय में अपडेट नहीं किया गया है। मुझे लगता है कि क्लाइंट और सर्वर के बीच सिग्नलआर प्रोटोकॉल असंगति के कारण समस्या है।
नादिम हुसैन सोनेट

44

स्वचालित रूप से पुन: कनेक्ट करने के लिए डिस्कनेक्ट की गई घटना पर टाइमर सेट करना एकमात्र तरीका है जिससे मैं परिचित हूं।

जावास्क्रिप्ट में ऐसा किया जाता है:

$.connection.hub.disconnected(function() {
   setTimeout(function() {
       $.connection.hub.start();
   }, 5000); // Restart connection after 5 seconds.
});

यह प्रलेखन में अनुशंसित दृष्टिकोण है:

http://www.asp.net/signalr/overview/signalr-20/hubs-api/handling-connection-lifetime-events#clientdisconnect


1
एक संकेत - सुनिश्चित करें कि आप किसी भी शुरुआत को पूर्ण कार्यक्षमता के रूप में शुरू करते हैं, अन्यथा आप हब को फिर से कनेक्ट करेंगे।
माइकबाज़ - MSFT

1
मैंने पाया कि .NET क्लाइंट के साथ, यदि आप हब कॉल करने से पहले बंद इवेंट की सदस्यता लेते हैं। , मूल हब के कारण। कार्ट () कभी पूरा न होने के लिए। मेरा समाधान केवल प्रारंभ () सफल होने के बाद बंद होने की सदस्यता लेना था, और कॉलबैक में तुरंत बंद कर दिया गया था।
ओरन डेनिसन

3
@MikeBaz मैं तुम्हें समूहों के लिए मतलब पुनः कनेक्ट लगता है
Simon_Weaver

1
@KingOfHypocrites मैंने reconnectingइवेंट के लिए सब्सक्राइब किया था, जिसे हब कनेक्शन खोने के बाद निकाल दिया जाता है और उस वेरिएबल (जैसे shouldReconnect) को सही पर सेट किया जाता है। इसलिए मैंने उस चर की जांच करने के लिए आपके उदाहरण को अनुकूलित किया। यह अच्छा लगता है।
Alisson

2
मैंने 10 और 60 सेकंड के बीच एक यादृच्छिक संख्या में किया। हमारे पास बहुत से ग्राहक हैं जो सिर्फ 5 सेकंड लगाते हैं, हम खुद को डीडीओ करेंगे। $ .connection.hub.disconnected (function () {setTimeout (function () {} .connection.hub.start ();};} (Math.floor (Math.random) (50) + 10) * 1000); });
14

17

चूंकि ओपी एक .NET क्लाइंट (नीचे विनर कार्यान्वयन) के लिए पूछ रहा है ,

private async Task<bool> ConnectToSignalRServer()
{
    bool connected = false;
    try
    {
        Connection = new HubConnection("server url");
        Hub = Connection.CreateHubProxy("MyHub");
        await Connection.Start();

        //See @Oran Dennison's comment on @KingOfHypocrites's answer
        if (Connection.State == ConnectionState.Connected)
        {
            connected = true;
            Connection.Closed += Connection_Closed;
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error: {ex.Message}");
    }
    return connected;
}

private async void Connection_Closed()
{   // A global variable being set in "Form_closing" event 
    // of Form, check if form not closed explicitly to prevent a possible deadlock.
    if(!IsFormClosed) 
    {
        // specify a retry duration
        TimeSpan retryDuration = TimeSpan.FromSeconds(30);
        DateTime retryTill = DateTime.UtcNow.Add(retryDuration);

        while (DateTime.UtcNow < retryTill)
        {
            bool connected = await ConnectToSignalRServer();
            if (connected)
                return;
        }
        Console.WriteLine("Connection closed")
    }
}

मैंने सिग्नलआर 2.3.0 में पाया कि यदि मैं बंद () घटना में कनेक्ट होने का इंतजार करता तो वह कभी-कभी कनेक्ट नहीं होता। हालाँकि, अगर मैं 10 सेकंड जैसे टाइमआउट के साथ घटना पर मैन्युअल प्रतीक्षा () कहता हूं, तो यह हर 10 सेकंड में स्वचालित रूप से बार-बार बंद () और फिर पुन: कनेक्ट काम करेगा।
ब्रेन २००

0

मैं ibubi उत्तर के लिए कुछ अपडेट जोड़ता हूं । हो सकता है किसी को इसकी जरूरत हो। मैंने पाया कि कुछ मामलों में सिग्नल को फिर से जोड़ने के बाद "बंद" घटना नहीं बढ़ती है। मैंने इसे "StateChanged" इवेंट का उपयोग करके हल किया। सिग्नलआर सर्वर से जुड़ने की विधि:

private async Task<bool> ConnectToSignalRServer()
        {
            bool connected = false;
            try
            {
                var connection = new HubConnection(ConnectionUrl);
                var proxy = connection.CreateHubProxy("CurrentData");
                await connection.Start();

                if (connection.State == ConnectionState.Connected)
                {
                    await proxy.Invoke("ConnectStation");

                    connection.Error += (ex) =>
                    {
                        Console.WriteLine("Connection error: " + ex.ToString());
                    };
                    connection.Closed += () =>
                    {
                        Console.WriteLine("Connection closed");
                    };
                    connection.StateChanged += Connection_StateChanged;
                    Console.WriteLine("Server for Current is started.");
                    connected = true;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
            }
            return connected;
        }

फिर से जोड़ने की विधि:

private async void Connection_StateChanged(StateChange obj)
        {
            if (obj.NewState == ConnectionState.Disconnected)
            {
                await RestartConnection();
            }
        }

सर्वर से कनेक्ट करने के लिए अंतहीन प्रयासों की विधि (इसके अलावा मैं मुट्ठी कनेक्शन बनाने के लिए इस पद्धति का उपयोग करता हूं):

public async Task RestartConnection()
        {
            while (!ApplicationClosed)
            {
                bool connected = await ConnectToSignalRServer();
                if (connected)
                    return;
            }
        }

-3

मैजिक पुन: कनेक्ट करने की समस्या को रोकने के लिए स्टेट्स को फिर से कनेक्ट करने से पहले आप अपने एंड्रॉइड से सर्वर विधि को लागू करने का प्रयास कर सकते हैं।

सिग्नलआर हब सी #

 public class MyHub : Hub
    {
        public void Ping()
        {
            //ping for android long polling
        }
 }

Android में

private final int PING_INTERVAL = 10 * 1000;

private boolean isConnected = false;
private HubConnection connection;
private ClientTransport transport;
private HubProxy hubProxy;

private Handler handler = new Handler();
private Runnable ping = new Runnable() {
    @Override
    public void run() {
        if (isConnected) {
            hubProxy.invoke("ping");
            handler.postDelayed(ping, PING_INTERVAL);
        }
    }
};

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    System.setProperty("http.keepAlive", "false");

    .....
    .....

    connection.connected(new Runnable() {
        @Override
        public void run() {
            System.out.println("Connected");
            handler.postDelayed(ping, PING_INTERVAL);
    });
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.