में नेटवर्कस्ट्रीम से पढ़ने का सही तरीका क्या है, मैं इसके साथ संघर्ष कर रहा हूं और मुझे कोई कारण नहीं मिला कि मेरा कोड एक टीसीपी सर्वर से ठीक से पढ़ने में असफल रहा है। मैं TcpClient
वर्ग और इसकी GetStream()
विधि का उपयोग कर रहा हूं लेकिन कुछ उम्मीद के अनुसार काम नहीं कर रहा है। या तो ऑपरेशन अनिश्चित काल तक ब्लॉक करता है (आखिरी पठन ऑपरेशन अपेक्षित समय सीमा नहीं देता है), या डेटा फसल हो जाता है (किसी कारण से रीड ऑपरेशन 0 देता है और लूप से बाहर निकलता है, शायद सर्वर पर्याप्त तेज़ी से प्रतिक्रिया नहीं दे रहा है)। ये इस समारोह को लागू करने पर तीन प्रयासों हैं:.NET
// this will break from the loop without getting the entire 4804 bytes from the server
string SendCmd(string cmd, string ip, int port)
{
var client = new TcpClient(ip, port);
var data = Encoding.GetEncoding(1252).GetBytes(cmd);
var stm = client.GetStream();
stm.Write(data, 0, data.Length);
byte[] resp = new byte[2048];
var memStream = new MemoryStream();
int bytes = stm.Read(resp, 0, resp.Length);
while (bytes > 0)
{
memStream.Write(resp, 0, bytes);
bytes = 0;
if (stm.DataAvailable)
bytes = stm.Read(resp, 0, resp.Length);
}
return Encoding.GetEncoding(1252).GetString(memStream.ToArray());
}
// this will block forever. It reads everything but freezes when data is exhausted
string SendCmd(string cmd, string ip, int port)
{
var client = new TcpClient(ip, port);
var data = Encoding.GetEncoding(1252).GetBytes(cmd);
var stm = client.GetStream();
stm.Write(data, 0, data.Length);
byte[] resp = new byte[2048];
var memStream = new MemoryStream();
int bytes = stm.Read(resp, 0, resp.Length);
while (bytes > 0)
{
memStream.Write(resp, 0, bytes);
bytes = stm.Read(resp, 0, resp.Length);
}
return Encoding.GetEncoding(1252).GetString(memStream.ToArray());
}
// inserting a sleep inside the loop will make everything work perfectly
string SendCmd(string cmd, string ip, int port)
{
var client = new TcpClient(ip, port);
var data = Encoding.GetEncoding(1252).GetBytes(cmd);
var stm = client.GetStream();
stm.Write(data, 0, data.Length);
byte[] resp = new byte[2048];
var memStream = new MemoryStream();
int bytes = stm.Read(resp, 0, resp.Length);
while (bytes > 0)
{
memStream.Write(resp, 0, bytes);
Thread.Sleep(20);
bytes = 0;
if (stm.DataAvailable)
bytes = stm.Read(resp, 0, resp.Length);
}
return Encoding.GetEncoding(1252).GetString(memStream.ToArray());
}
पिछले एक "काम करता है", लेकिन यह निश्चित पाश पर विचार सॉकेट पहले से ही समय समाप्ति पढ़ का समर्थन करने वाले के अंदर एक हार्ड-कोडेड नींद डाल करने के लिए बदसूरत लग रहा है! क्या मुझे NetworkStream
के TcpClient
पर कुछ संपत्ति (ies) सेट करने की आवश्यकता है? क्या समस्या सर्वर में रहती है? सर्वर कनेक्शन बंद नहीं करता है, ऐसा करने के लिए ग्राहक पर निर्भर करता है। उपरोक्त यूआई थ्रेड संदर्भ (टेस्ट प्रोग्राम) के अंदर भी चल रहा है, शायद इसके साथ कुछ करने के लिए ...
क्या कोई डेटा को पढ़ने के लिए NetworkStream.Read
का सही ढंग से उपयोग करने के बारे में जानता है, जब तक कोई डेटा उपलब्ध न हो जाए? मुझे लगता है कि मैं जो चाहता हूं वह पुरानी Win32 winsock टाइमआउट गुणों की तरह कुछ है ... ReadTimeout
, आदि। यह टाइमआउट तक पहुंचने तक पढ़ने की कोशिश करता है, और फिर 0 वापस लौटाता है ... लेकिन कभी-कभी यह डेटा वापस लौटने लगता है उपलब्ध होना चाहिए (या रास्ते में .. यदि उपलब्ध हो तो वापसी 0 पढ़ सकते हैं?) और फिर डेटा उपलब्ध नहीं होने पर अंतिम बार पढ़ने पर अनिश्चित काल तक अवरुद्ध हो जाता है ...
हाँ, मुझे नुकसान हो रहा है!
सावधान:
मैं ReceiveTimeout का उपयोग कर पाते हैं अतुल्यकालिक पढ़ने को लागू करने की तुलना में बहुत आसान है ... यहाँ काम कर कोड है। आपके प्रयास (और उत्तरों) में कोड क्लाइंट या स्ट्रीम को बंद नहीं करता है, जो बार-बार बुलाए जाने वाले बड़े परिणामों के साथ संसाधन रिसाव का कारण बनता है। आपको संभवत: 'var क्लाइंट = नया सिस्टम.Net.Sockets.TcpClient (ip, पोर्ट) का उपयोग करना चाहिए ( (var stm = client.GetStream()) का उपयोग करके' शेष बार्स में शेष विधि को संलग्न करें। यह गारंटी देगा कि विधि से बाहर निकलने पर, जो कुछ भी कारण है, कनेक्शन बंद हैं, संसाधनों को पुनः दावा किया जाता है। –
क्या आपने टीसीपी क्लाइंट क्लास के लिए कोड देखा है? मैं इसे देखने की सलाह देता हूं ...यदि आप अभी भी एंडपॉइंट पर जवाब देना चाहते हैं, तो आपको स्ट्रीम को बंद नहीं करना चाहिए और न ही टीसीपीक्लिएंट (जो स्ट्रीम को बंद कर देता है, अगर मुझे गलत नहीं लगता है)। लेकिन मैं जिस वास्तविक कोड का उपयोग कर रहा हूं वह अलग है, मैं इसे खोद दूंगा और यहां जवाब भी अपडेट करूंगा। – Loudenvier
सुझाव के लिए धन्यवाद। मैंने पाया [TCPClient.cs] (http://referencesource.microsoft.com/#system/net/System/Net/Sockets/TCPClient.cs)। वास्तव में 'टीसीपी क्लाइंट' को बंद या निपटाना धारा का निपटान करता है। मैंने वास्तव में कनेक्शन विफलताओं को देखा है जब एक कार्यक्रम ने बिना किसी देखभाल के हजारों कनेक्शन किए हैं (अन्य, बुरे, कारणों से)। यहां सामान्य आईडीस्पोजेबल पैटर्न से क्यों विचलित होना चाहिए? IDISposable कार्यान्वित करने में त्रुटि-प्रवण है, '() का उपयोग करना आसान और सुरक्षित है। –