2009-08-10 11 views
6

मेरे पास एक ऐसा एप्लिकेशन है जिसे मैंने अपने विंडोज 2003 सर्वर (आईआईएस 6.0 चलाने) के माध्यम से मुझे डेटा भेजने के लिए कंपनी भर में वितरित मेरे आवेदन के लिए लिखा है। छोटे टेक्स्ट संदेश प्राप्त होते हैं, लेकिन अधिक डेटा वाले संदेश (लगभग 20 केबी) नहीं हो रहे हैं।टीसीपी क्लाइंट कनेक्शन

मैंने बाइट बफर को टीसीपी क्लाइंट के बफर आकार में सेट किया है। मैंने देखा कि सर्वर पर मेरा डेटा प्राप्त किया जा रहा था; हालांकि, यह केवल एक बार प्राप्त दिनचर्या के माध्यम से looped, और मेरी बड़ी फाइलें हमेशा बफर आकार का आकार, या हमारे सर्वर पर 8 केबी थे। दूसरे शब्दों में, सर्वर को सॉकेट कनेक्शन बंद करने से पहले ही मेरा कोड केवल एक लूप के माध्यम से बनाता है।

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

मैं सर्वर के त्रुटि संदेश को क्लाइंट को वापस भेजता हूं ताकि मैं इसे देख सकूं। विशिष्ट त्रुटि संदेश मैं ग्राहक से प्राप्त है: अंतर्निहित टीसीपी सॉकेट का प्रयोग करेंगे तो यह है कि

“Unable to write data to the transport connection: An established connection was aborted by the software in your host machine.”

मैं अपने सर्वर अनुप्रयोग अद्यतन इस लाइन के साथ "Alives रखने":

client.Client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, true); 

अब, जब भी मैं एक संदेश भेजने का प्रयास करते ग्राहक त्रुटि प्राप्त करता है:

“Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host.”

हमारे नेटवर्क व्यवस्थापक ने मुझे बताया है कि वह एक फ़ायरवॉल या हमारी आंतरिक सर्वर पर अवरुद्ध किसी भी बंदरगाहों जरूरत नहीं है।

त्रुटियों को गुगल करने के बाद, मुझे यह पता चला कि लोग सर्वर में टेलनेट करने का प्रयास करते हैं। मैंने सर्वर में टेलनेट के लिए अपनी दिशाओं का उपयोग किया, लेकिन मुझे यकीन नहीं है कि प्रतिक्रिया का क्या करना है:

C:> telnet Welcome to Microsoft Telnet Client

Escape Character is ‘CTRL+]’

Microsoft Telnet> open cpapp 500 Connecting To cpapp…

यह सब मुझे मिलता है। मुझे कभी भी कोई त्रुटि नहीं मिलती है, और माइक्रोसॉफ्ट की टेलनेट स्क्रीन अंततः "जारी रखने के लिए कोई भी कुंजी दबाएं" में बदल जाएगी ... - मुझे लगता है कि यह समय समाप्त हो गया है, लेकिन मेरा कोड किसी भी तरह से कनेक्ट करने में सक्षम है।

मैं 25, 80 सहित कोड में और Telnet के माध्यम से अन्य बंदरगाहों की कोशिश की है, और 8080 के टेलनेट पोर्ट 25 बाहर किक, लेकिन अपने आवेदन कोई बात नहीं क्या बंदरगाह मैं यह बताना होने वाली प्रथम पाश को पढ़ने के लिए लगता है।

SvrForm.Server = new TcpListener(IPAddress.Any, CpAppDatabase.ServerPortNumber); 

void Worker_Engine(object sender, DoWorkEventArgs e) { 
    BackgroundWorker worker = sender as BackgroundWorker; 
    string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Application.CompanyName); 
    if (Directory.Exists(path) == false) Directory.CreateDirectory(path); 
    Thread.Sleep(0); 
    string eMsg = string.Empty; 
    try { 
    SvrForm.Server.Start(); 
    do { 
     using (TcpClient client = SvrForm.Server.AcceptTcpClient()) { // waits until data is avaiable 
     if (worker.CancellationPending == true) return; 
     client.Client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, true); 
     string location = Path.Combine(path, string.Format("Acp{0:yyyyMMddHHmmssff}.bin", DateTime.Now)); 
     byte[] buf = new byte[client.ReceiveBufferSize]; 
     try { 
      using (NetworkStream ns = client.GetStream()) { 
      if ((ns.CanRead == true) && (ns.CanWrite == true)) { 
       try { 
       int len; 
       byte[] AOK = Encoding.ASCII.GetBytes("AOK"); 
       using (FileStream fs = new FileStream(location, FileMode.Create, FileAccess.Write)) { 
        do { 
        len = ns.Read(buf, 0, client.ReceiveBufferSize); 
        fs.Write(buf, 0, len); 
        ns.Write(AOK, 0, AOK.Length); 
        } while ((0 < len) && (ns.DataAvailable == true)); 
       } 
       byte[] okBuf = Encoding.ASCII.GetBytes("Message Received on Server"); 
       ns.Write(okBuf, 0, okBuf.Length); 
       } catch (Exception err) { 
       Global.LogError("ServerForm.cs - Worker_Engine(DoWorkEvent)", err); 
       byte[] errBuf = Encoding.ASCII.GetBytes(err.Message); 
       ns.Write(errBuf, 0, errBuf.Length); 
       } 
      } 
      } 
     } 
     worker.ReportProgress(1, location); 
     } 
    } while (worker.CancellationPending == false); 
    } catch (SocketException) { 
    // See MSDN: Windows Sockets V2 API Error Code Documentation for detailed description of error code 
    e.Cancel = true; 
    } catch (Exception err) { 
    eMsg = "Worker General Error:\r\n" + err.Message; 
    e.Cancel = true; 
    e.Result = err; 
    } finally { 
    SvrForm.Server.Stop(); 
    } 
} 

क्यों अपने आवेदन टीसीपी क्लाइंट से पढ़ना जारी नहीं करता है:

int sendUsingTcp(string location) { 
    string result = string.Empty; 
    try { 
    using (FileStream fs = new FileStream(location, FileMode.Open, FileAccess.Read)) { 
     using (TcpClient client = new TcpClient(GetHostIP, CpAppDatabase.ServerPortNumber)) { 
     byte[] riteBuf = new byte[client.SendBufferSize]; 
     byte[] readBuf = new byte[client.ReceiveBufferSize]; 
     using (NetworkStream ns = client.GetStream()) { 
      if ((ns.CanRead == true) && (ns.CanWrite == true)) { 
      int len; 
      string AOK = string.Empty; 
      do { 
       len = fs.Read(riteBuf, 0, riteBuf.Length); 
       ns.Write(riteBuf, 0, len); 
       int nsRsvp = ns.Read(readBuf, 0, readBuf.Length); 
       AOK = Encoding.ASCII.GetString(readBuf, 0, nsRsvp); 
      } while ((len == riteBuf.Length) && (-1 < AOK.IndexOf("AOK"))); 
      result = AOK; 
      return 1; 
      } 
      return 0; 
     } 
     } 
    } 
    } catch (Exception err) { 
    Logger.LogError("Send()", err); 
    MessageBox.Show(err.Message, "Message Failed", MessageBoxButtons.OK, MessageBoxIcon.Hand, 0); 
    return -1; 
    } 
} 

यहाँ मेरी कोड है कि सर्वर पर चलाता है:

यहाँ मेरी कोड है कि ग्राहकों पर चलता है ? क्या मैंने ऐसा कुछ सेट करने के लिए उपेक्षित किया है जो सॉकेट को तब तक खुला रहता है जब तक कि मैं समाप्त नहीं कर लेता? सर्वर कोड कभी अपवाद नहीं देखता क्योंकि टीसीपी क्लाइंट कभी नहीं रोका जाता है, इसलिए मुझे पता है कि कोई त्रुटि नहीं है।

हमारे नेटवर्क प्रशासक को अभी तक अपनी एसोसिएट्स डिग्री प्राप्त नहीं हुई है, इसलिए यदि यह सर्वर के साथ कोई समस्या हो, तो कृपया इसे हल करने के तरीके के बारे में विस्तृत विवरण दें, क्योंकि हम समझ नहीं सकते कि आप क्या कह रहे हैं ।

मैं इस लंबे समय तक माफ़ी मांगता हूं, लेकिन मैं यह सुनिश्चित करना चाहता हूं कि आप जानते हैं कि मैं क्या कर रहा हूं - और शायद मेरी तकनीक से कुछ जानकारी भी प्राप्त कर सकता हूं!

मदद के लिए धन्यवाद! ~ जो

उत्तर

6

आपको उस सामग्री की लंबाई के साथ भेजे गए सामग्री से पहले होना चाहिए। आपका पाश मानता है कि लूप निष्पादित होने से पहले सभी डेटा भेजा जाता है, जब वास्तविकता में आपका लूप निष्पादित होता है क्योंकि डेटा भेजा जाता है।ऐसे समय होंगे जब तार पर कोई डेटा इंतजार नहीं होता है, इसलिए लूप समाप्त हो जाता है; इस बीच, तार अभी भी तार भर में भेजा जा रहा है। यही कारण है कि आपका लूप केवल एक बार चल रहा है।

+0

कोई मजाक नहीं? मुझे लगता है कि अब समझ में आता है। मैंने सर्वर पर सेटअप करने के लिए कुछ आवश्यक सोच रखा। यह * बहुत * मदद करता है! धन्यवाद! – jp2code

+0

मैं यह कैसे करूँगा? "उस सामग्री की लंबाई के साथ भेजे गए सामग्री से पहले" मेरे पास प्रेषित सामग्री की लंबाई नहीं है? –

+0

यदि आपको लंबाई नहीं पता है, तो जाहिर है कि आप तार पर लंबाई नहीं भेजते हैं। – Amy

1

तो मैंने पढ़ा अपना कोड सही है, तो आप मूल रूप से मिल गया है (ग शैली के लिए खेद है - मैं सी # के साथ अच्छा नहीं कर रहा हूँ:

 
do 
{ 
    socket = accept(); 
    read(socket, buffer); 
}while(not_done); 

अगर मैं सही हूँ, तो यह । आप की जरूरत का मतलब है ... एक छोटे से वहाँ में और अधिक आप इसे धारावाहिक जा चाहते हैं, क्रम में प्रत्येक अपलोड पढ़ने, आप एक दूसरे पाश चाहता हूँ:

 
do 
{ 
    socket = accept(); 
    do { read(socket, buffer); not_done_reading=...; } while (not_done_reading); 
}while(not_done); 

आप simultaniously कई अपलोड पढ़ने के लिए चाहते हैं, आपको कुछ और चाहिए:

 
do 
{ 
    socket = accept(); 
    if(!fork()) 
    { 
    do { read(socket, buffer); not_done_reading=...; } while (not_done_reading); 
    } 
}while(not_done); 
1
आपका टेलनेट उदाहरण

कुछ हद तक कोड के व्यवहार है कि आप का वर्णन करने के विरोधाभासी है - अगर तुम कभी सर्वर, "टेलनेट < होस्ट नाम > <portnumber>" पर कुछ भी प्राप्त कर सकते हैं यदि आप एक खाली करने के लिए मिलना चाहिए स्क्रीन बहुत तेज़ी से (सीएमडी प्रॉम्प्ट में विंडोज मशीन पर है)। तो, यह पहली अजीब बात है - wireshark, though के साथ सबसे अच्छा डीबग किया गया।

कोड के लिहाज से, मैं इसे सर्वर पर इस आंतरिक लाइन के साथ समस्या हो सकती है लगता है:

... जबकि ((0 < लेन) & & (ns.DataAvailable == सच));

आप कहते हैं कि आप कुछ पढ़ना चाहते हैं और कुछ डेटा उपलब्ध होने पर आप लूप करना चाहते हैं।

हालांकि, यह हो सकता है कि दूसरे खंड ने इसे अभी तक सर्वर पर नहीं बनाया है, इसलिए अभी तक कोई डेटा उपलब्ध नहीं है, इसलिए आप इस लूप से बाहर निकल रहे हैं।

आपको कुछ पढ़ने के दौरान डेटा प्राप्त करना चाहिए और जबकि कोई भी त्रुटि नहीं हुई है - यह गारंटी देता है कि धीमे लिंक पर भी आप विश्वसनीय रूप से डेटा प्राप्त करेंगे।

एक ओर ध्यान दें:

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

(अस्वीकरण: मैंने सी # में बहुत कुछ कोड नहीं किया है, इसलिए "डेटा उपलब्ध()" विधि की व्याख्या में गलत हो सकता है, यह FWIW लें)।

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

उस ने कहा, टीसीपी के साथ किसी को कभी भी प्रेषक पक्ष पर लिखने की संख्या() संचालन की संख्या को रिसीवर पक्ष पर पढ़ने() संचालन की संख्या के समान नहीं होना चाहिए - कुछ मामलों में यह मामला हो सकता है (कोई पैकेट नहीं नुकसान, कोई नागल नहीं) - लेकिन सामान्य मामले में यह सच नहीं होगा।

संबंधित मुद्दे