घर
Top.Mail.Ru Yandeks.Metrika
फोरम: "नेटवर्क";
वर्तमान संग्रह: 2003.09.01;
डाउनलोड करें: [xml.tar.bz2];

नीचे

Socket.OnWrite इसी तरह की शाखाएँ खोजें


Akni   (2003-06-17 14:40) [0]

दप। मास्टर्स, हेल्प, प्लीज, इवेंट ऑन वाइट क्लास TCustomWinSocket से निपटें।

उदाहरण के लिए, डेटा अगले प्रेषित होता है। निम्नलिखित तरीके से:
वर रेस: पूर्णांक; ... प्रक्रिया TForm1.Button1 क्लिक करें (प्रेषक: TObject); शुरू करना Res: = ClientSocket1.Socket.SendBuf (iBuffer, BufSize); अंत;
यदि SendBuf () रिटर्न -1, इसका मतलब है कि कोई डेटा स्थानांतरित नहीं किया गया था, क्योंकि WinSock बफर व्यस्त है। और, जैसा कि मैं इसे समझता हूं, थोड़ी देर के बाद, जब बफर में जगह खाली हो जाती है, तो ऑनराइट घटना घटित होनी चाहिए, जिसमें आप डेटा ट्रांसफर दोहरा सकते हैं:

प्रक्रिया TForm1.ClientSocket1Write (प्रेषक: Tobject; गर्तिका: TCustomWinSocket); शुरू करना अगर Res = -1 तो ClientSocket1.Socket.SendBuf (iBuffer, Buftize); अंत;
सॉकेट से गुजरते समय डेटा खोने से बचने के लिए क्या यह सही तरीका है?



Digitman   (2003-06-17 15:14) [1]

नहीं, बिल्कुल सही नहीं है।

प्रक्रिया TForm1.ClientSocket1Write (प्रेषक: Tobject;
गर्तिका: TCustomWinSocket);
शुरू करना
अगर Res = -1 तो
( iBuffer, BufSize) नहीं, बिल्कुल सही नहीं है।

प्रक्रिया TForm1.ClientSocket1Write (प्रेषक: Tobject;
गर्तिका: TCustomWinSocket);
शुरू करना
अगर Res = -1 तो
रेस: = सॉकेट.सेंडब्यूफ़ (आईब्रफर, बुफ़िज़); // यहाँ भी, आपको iBuffer के मामले में परिणाम रिकॉर्ड करने की आवश्यकता है, BufSize पैरामीटर लगातार दो घटनाओं के बीच बदल गए हैं (उदाहरण के लिए, आपने बफर को फिर से परिभाषित किया (इसे बढ़ाया और इसके अंत में संचरण के लिए आवश्यक डेटा के स्कोरिंग भाग को लिखा)
अंत;

आप SendBuf ()> = 0 कॉल के परिणाम को ध्यान में नहीं रखते हैं।
इस परिणाम के साथ, आपको या तो बफ़र का पता और आकार बदलना चाहिए या ओनराइट () घटना में बफर में प्रेषित "1 वें ऑफ़सेट XNUMX वें" की अवधारणा को ड्राइव करना चाहिए और डेटा का आकार अभी तक इस बफ़र में स्थानांतरित नहीं किया जाना चाहिए - यदि बफ़र ठीक किया गया है और आपके द्वारा ओवरराइड नहीं किया गया है।



Akni   (2003-06-17 16:23) [2]

धन्यवाद, मैं आगे सोचूंगा



Digitman   (2003-06-17 16:37) [3]

कई मामलों में यह SendStream () का उपयोग करने के लिए बेहतर है ताकि बफर के पुनर्वितरण के तर्क और उसमें प्रसारित डेटा की स्थिति की परवाह न करें।

किसी भी समय (OnWrite घटनाओं के बीच) धारा को नए दिखने वाले डेटा से भरा जा सकता है जिसमें ट्रांसमिशन की आवश्यकता होती है। और SendStream () पद्धति स्ट्रीम को स्थानांतरित करने और उसमें अपनी स्थिति को बढ़ावा देने का ध्यान रखेगी यदि यह एक कॉल में स्ट्रीम के सभी कंटेंट को इस विधि में स्थानांतरित करने में विफल रहता है। हालाँकि, यह विधि तब ही धारा को नष्ट कर देगी जब वह अपनी सभी सामग्री को पूरी तरह से स्थानांतरित कर देगी। केवल उस क्षण को पकड़ना महत्वपूर्ण है जब इस पद्धति ने धारा को नष्ट कर दिया है, और इसे फिर से बनाने के लिए, ताकि इसके अगले भरने के क्षण में एवी को हिला न सकें। लेकिन यह पहले से ही सबसे सरल तकनीक का मामला है)



Akni   (2003-06-17 18:04) [4]

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

सामान्य विचार है:
एक गैर-अवरुद्ध सॉकेट एक अलग थ्रेड में चलता है, डेटा प्राप्त करना और प्राप्त करना।
संदेश थ्रेड को भेजे जाते हैं (PostThreadMessage) यह दर्शाता है कि कुछ डेटा भेजने की आवश्यकता है।
यदि आप फ़ाइलों को स्थानांतरित नहीं करते हैं, तो सब कुछ स्पष्ट है: आप एक मेमस्ट्रीम में सभी डेटा लिख ​​सकते हैं, और फिर सॉकेट इसके साथ भेज देंगे।
और क्या करें यदि आपको अधिक फाइल भेजने की आवश्यकता है? आखिरकार, इस तरह के तर्क के साथ, एक फ़ाइल को उसके "साथ" जानकारी प्रसारित होने के बाद ही स्थानांतरित किया जा सकता है - आकार, नाम, आदि।
अभी के लिए, दो विकल्प संभव लगते हैं:
1। मेमस्ट्रीम में फ़ाइल को अधिलेखित करने के लिए, फिर भेजने के सही क्रम की गारंटी होगी (लेकिन बड़े फ़ाइल आकारों के लिए यह अच्छा नहीं है)
2। "साथ" जानकारी फ़ाइल को रिकॉर्ड करने के बाद मेमस्ट्र्रीम में कुछ भी न लिखें; जांचें कि क्या MemStream का सारा डेटा भेजा गया है और फिर फाइल को एक अलग स्ट्रीम सॉकेट के रूप में भेजें। SendStream (TFileStream.Create (फ़ाइल नाम))। लेकिन एक ही समय में, अन्य सभी डेटा जो एक सॉकेट के माध्यम से प्रसारित किए जाने चाहिए, जैसे कि "हवा में लटका हुआ है" जब तक मेमस्ट्र्रीम को मंजूरी नहीं दी जाती।

क्या ऐसे कार्य को पूरा करने के लिए और अधिक सही तरीके हैं?



Digitman   (2003-06-18 09:30) [5]

आप यह कर सकते हैं:

एक संदेश परिवहन थ्रेड के लिए भेजा जाता है, उदाहरण के लिए, TM_SEND_DATABLOCK अगले के साथ। पैरामीटर:

wParam = फ़ाइल नाम के साथ संरचना में सूचक
lParam = ThreadId थ्रेड यह संदेश भेज रहा है

परिवहन धागा, TM_SEND_DATABLOCK संदेश प्राप्त करने के बाद, wParam में लिंक लेता है फ़ाइल नाम / पथ, अपने आप ही इसकी विशेषताओं को निर्धारित करता है, उन्हें MemStream में लिखता है, MemStream को स्थानांतरित करता है, फिर एक TFileStream बनाता है, इसे भेजता है (दोनों स्ट्रीम एक या कई तकनीकों का उपयोग करके ऑनसाइट में उपयोग किया जाता है)

यदि ट्रांसपोर्ट थ्रेड का सफल या असफल (डिसकनेक्शन, टाइमआउट, इत्यादि) ट्रांसफर हो, तो थ्रेडिंग ऑफ सेंडिंग थ्रेड (यदि इसे TM_SEND_DATABLOCK के साथ lParam में निर्दिष्ट किया गया था), उदाहरण के लिए, TM_DATABLOCK_SENT की मदद से पारेषण के परिणाम के बारे में सूचित करता है। और परिणामों को विस्तृत करने के लिए lParam (सफल या असफल, यदि असफल, तो कारण)

यदि थ्रेड प्रेषक ने TM_SEND_DATABLOCK के साथ lParam में अपने थ्रेडआईड को निर्दिष्ट किया है, तो उसने परिवहन को सूचित किया कि वह भेजने के परिणाम की प्रतीक्षा में रुचि रखता था। इसलिए, TM_SEND_DATABLOCK को सफलतापूर्वक भेजने के बाद, प्रेषक संदेश के लिए प्रतीक्षा / प्राप्त / प्रसंस्करण चक्र का आयोजन करता है, और परिवहन से TM_DATABLOCK_SENT संदेश प्राप्त करने पर चक्र से बाहर निकलता है।

संरचना के लिए मेमोरी, जिस लिंक को थ्रेड भेजने वाले ने पहले TM_SEND_DATABLOCK के साथ wParam को भेजा था, उसे थ्रेड प्रेषक द्वारा बिना शर्त के मुक्त कर दिया जाता है यदि lParam = ThreadId (थ्रेड भेजने वाले को परिणाम का इंतजार है), अन्यथा यह निश्चित रूप से ट्रैफ़िक स्ट्रीम (शर्त द्वारा प्राप्त की गई स्थिति) द्वारा जारी किया जाएगा एक सफल या असफल हस्तांतरण ऑपरेशन के बाद TM_SEND_DATABLOCK lParam = 0) में।



Akni   (2003-06-18 14:42) [6]


> इसलिए, सफलतापूर्वक TM_SEND_DATABLOCK भेजने के बाद, थ्रेड भेजने वाला
> एक प्रतीक्षा / प्राप्त / प्रक्रिया संदेश लूप का आयोजन करता है, बाहर निकलें
> लूप से - परिवहन से TM_DATABLOCK_SENT संदेश प्राप्त होने पर।
>


अगर मैं आपके विचार को सही ढंग से समझता हूं, तो इसका मतलब है कि थ्रेड भेजने वाले को ट्रांसपोर्ट थ्रेड में नया तत्परता संदेश नहीं भेजना चाहिए। डेटा के कुछ हिस्सों तक यह परिवहन धागे से पुष्टि प्राप्त करता है कि डेटा का अंतिम भाग भेजा गया है?



Digitman   (2003-06-18 14:55) [7]


> अक्नी © (18.06.03 14: 42)


अच्छा, क्यों? जरूरी नहीं है।


> थ्रेड भेजने वाला


एक थ्रेड भेजने वाला तुरंत कई ट्रांसपोर्ट को निर्देश दे सकता है कि वह इस तरह की फाइल्स को ट्रांसफर करने के निर्देश के साथ थ्रेड ट्रांसपोर्ट को कई संदेश भेज सकता है, और फिर इंतजार करें कि क्या लूप में TM_DATABLOCK_SENT मैसेज के लिए जरूरी है, फेल होने के प्रत्येक कारणों (यदि कोई हो) का विश्लेषण करें।

तथ्य यह है कि डेटा ट्रांसफर केवल तभी विफल हो सकता है जब ट्रांसपोर्ट चैनल स्वयं विफल हो जाता है (अनपेक्षित कारणों के लिए समय-समय पर वियोग, आदि) या दूरस्थ कनेक्शन पार्टनर की पहल पर डिस्कनेक्ट हो रहा है

इस स्थिति में, परिवहन थ्रेड या तो विशेष थ्रेड-प्रेषक को सूचित करना चाहिए कि ट्रांसपोर्ट चैनल तुरंत टूट गया है या समाप्त हो गया है (थ्रेड-प्रेषक को यातायात के पूरा होने के क्षण की निगरानी करनी चाहिए, परिवहन विफलता के तथ्य के रूप में व्याख्या करना)



Akni   (2003-06-18 15:40) [8]

कुछ मुझे अभी भी समझ नहीं आ रहा है ...

एक ऐसी स्थिति की कल्पना करें जहां आपको दो फ़ाइलों को एक पंक्ति में भेजने की आवश्यकता हो।
थ्रेड भेजने वाले ने एक ट्रांस भेजा। tredu एसीसी। पहली फ़ाइल भेजने के बारे में संदेश।
Transp। थ्रेड ने फ़ाइल डेटा को MemStream में लिखा और इस फाइल के लिए FileStream बनाया।
मेमेस्ट्रीम से फाइल की जानकारी भेजे जाने के बाद ही फाइलस्ट्रीम को स्थानांतरित किया जा सकता है।
लेकिन इस जानकारी को पूरी तरह से भेजें। WinSocket बफ़र व्यस्त होने के कारण थ्रेड नहीं हो सका।
इस समय, थ्रेड भेजने वाला स्थानांतरण भेजता है। थ्रेड एक अन्य संदेश दर्शाता है कि एक अन्य फ़ाइल भेजी जानी चाहिए (अच्छी तरह से, या अन्य डेटा)।
इस समय कुछ भी ट्रांस ट्रांस व्यस्त नहीं है। थ्रेड यह संदेश प्राप्त करता है। और अब क्या करें ट्रांस। ट्रेडों? इस संदेश की प्रतिक्रिया एक फ़ाइल रिकॉर्ड होनी चाहिए। मेमस्ट्रीम में .., आदि, उसी तरह जैसे पहली फाइल के साथ।
लेकिन आप MemStream को तब तक नहीं लिख सकते जब तक कि यह पूरी तरह से न भेजा जाए!



Digitman   (2003-06-18 16:21) [9]


> इस जानकारी को पूरी तरह से भेजें। धागा नहीं हो सकता
> व्यस्त WinSocket बफर के कारण।


और यह उसकी (trans.treda) समस्या है!

ड्रम पर थ्रेड प्रेषक गहरा। ट्रांसपोर्ट कैसे ट्रांसफर करता है)

लेकिन transp.tred, अगर यह एक गैर-ब्लॉक घोंसले के साथ काम करता है, तो, जैसा कि आप और मैंने कहा था कि थोड़ा अधिक होगा, ऑनवराइट () इवेंट की नियुक्ति और हैंडलिंग को व्यवस्थित करें



Akni   (2003-06-20 11:22) [10]

सिद्धांत के साथ, सब कुछ स्पष्ट है, लेकिन कार्यान्वयन, अफसोस, समस्याओं के साथ ...

मैं एक ट्रेस लिख रहा हूं। TM_SEND_DATABLOCK संदेश हैंडलर:

TISServerThread - TThread का वंशज
fSendStream - TMemoryStream का वंशज

प्रक्रिया TISServerThread.SendData (var Msg: TMessage);
var iCode: पूर्णांक;
iSize: पूर्णांक;
डेटब्लॉक: टीसडॉटब्लॉक;
CurPos: पूर्णांक;
शुरू करना
यदि नहीं दिया गया (fSendStream)
उसके बाद fSendStream: = TISMemoryStream.Create (नष्ट करें);
कोशिश
CurPos: = fSendStream.Position;
fSendStream.Position: = fSendStream.Size;

मामला msg.wParam का
सीडीआरईसी: // संरचना भेजें
शुरू करना
डेटब्लॉक: = टीआईएसडाटाब्लॉक। क्रिएट;
कोशिश
डेटब्लॉक: = SendQueue.Pop; // डेटाब्लॉक में डेटा प्रकार, आकार और डेटा स्वयं शामिल हैं।
fSendStream.WriteBuffer (DatBlock.Data ^, DatBlock.BlockSize);
आखिरकार
DatBlock.Free;
अंत;
अंत;

cdFILE: // फ़ाइल भेजें
शुरू करना
fFileStream: = TFileStream.Create (fFileDat.fFileName, fmOpenRead); // fileStream बनाएँ
fFileDat.fSize का प्रयास करें: = fFileStream.size; // फ़ाइल का आकार
// स्ट्रीम करने के लिए नाम और फ़ाइल आकार के साथ संरचना लिखें
iCode: = cdFILE_TOCLIENT;
fSendStream.WriteBuffer (iCode, SizeOf (पूर्णांक));
iSize: = SizeOf (ISFileDat);
fSendStream.WriteBuffer (iSize, SizeOf (पूर्णांक));
fSendStream.WriteBuffer (fFileDat, SizeOf (fFileDat));
// धारा को सूचित करें। कि फाइल को अब फॉलो करना चाहिए। आकार
iCode: = cdFILE;
fSendStream.WriteBuffer (iCode, SizeOf (पूर्णांक));
iSize: = fFileDat.fSize;
fSendStream.WriteBuffer (iSize, SizeOf (पूर्णांक));
सिवाय
उठाना
अंत;
अंत;
अंत;

fSendStream.Position: = करपोस;
// मेमोर्रीम भेजें
fServerSocket.Socket.Connections [0] .SendStream (fSendStream);
// मेमोर्रीम भेजने के बाद फाइल भेजें
यदि सौंपा (fFilestream) तो
यदि नहीं सौंपा गया है (fSendStream) तो
fServerSocket.Socket.Connections [0] .SendStream (fFileStream);

सिवाय
FreeAndNil (fSendStream);
अगर सौंपा (fFileStream) तो FreeAndNil (fFileStream);
पोस्टमेसेज (fOwnerForm.Handle, wm_RefreshClients, cdERROR, 0);
ESendError.CreateRes (@SSendError) बढ़ाएँ;
अंत;
अंत;

मैं ऑनराइट में निम्नलिखित लिखता हूं:

प्रक्रिया TISServerThread। सॉकेटवेयर (प्रेषक: TObject;
गर्तिका: TCustomWinSocket);
शुरू करना
सॉकेट.सेंडस्ट्रीम (fSendStream); // मेमस्ट्रीम भेजें
अगर सौंपा (fFileStream) तो // अगर भेजने के लिए कोई फाइल है, तो उसे ही भेजें
यदि सौंपे नहीं गए हैं (fSendStream) तो // के बाद memStream भेजा गया है
( fFileStream) सिद्धांत के साथ, सब कुछ स्पष्ट है, लेकिन कार्यान्वयन, अफसोस, समस्याओं के साथ ...

मैं एक ट्रेस लिख रहा हूं। TM_SEND_DATABLOCK संदेश हैंडलर:

TISServerThread - TThread का वंशज
fSendStream - TMemoryStream का वंशज

प्रक्रिया TISServerThread.SendData (var Msg: TMessage);
var iCode: पूर्णांक;
iSize: पूर्णांक;
डेटब्लॉक: टीसडॉटब्लॉक;
CurPos: पूर्णांक;
शुरू करना
यदि नहीं दिया गया (fSendStream)
उसके बाद fSendStream: = TISMemoryStream.Create (नष्ट करें);
कोशिश
CurPos: = fSendStream.Position;
fSendStream.Position: = fSendStream.Size;

मामला msg.wParam का
सीडीआरईसी: // संरचना भेजें
शुरू करना
डेटब्लॉक: = टीआईएसडाटाब्लॉक। क्रिएट;
कोशिश
डेटब्लॉक: = SendQueue.Pop; // डेटाब्लॉक में डेटा प्रकार, आकार और डेटा स्वयं शामिल हैं।
fSendStream.WriteBuffer (DatBlock.Data ^, DatBlock.BlockSize);
आखिरकार
DatBlock.Free;
अंत;
अंत;

cdFILE: // फ़ाइल भेजें
शुरू करना
fFileStream: = TFileStream.Create (fFileDat.fFileName, fmOpenRead); // fileStream बनाएँ
fFileDat.fSize का प्रयास करें: = fFileStream.size; // फ़ाइल का आकार
// स्ट्रीम करने के लिए नाम और फ़ाइल आकार के साथ संरचना लिखें
iCode: = cdFILE_TOCLIENT;
fSendStream.WriteBuffer (iCode, SizeOf (पूर्णांक));
iSize: = SizeOf (ISFileDat);
fSendStream.WriteBuffer (iSize, SizeOf (पूर्णांक));
fSendStream.WriteBuffer (fFileDat, SizeOf (fFileDat));
// धारा को सूचित करें। कि फाइल को अब फॉलो करना चाहिए। आकार
iCode: = cdFILE;
fSendStream.WriteBuffer (iCode, SizeOf (पूर्णांक));
iSize: = fFileDat.fSize;
fSendStream.WriteBuffer (iSize, SizeOf (पूर्णांक));
सिवाय
उठाना
अंत;
अंत;
अंत;

fSendStream.Position: = करपोस;
// मेमोर्रीम भेजें
fServerSocket.Socket.Connections [0] .SendStream (fSendStream);
// मेमोर्रीम भेजने के बाद फाइल भेजें
यदि सौंपा (fFilestream) तो
यदि नहीं सौंपा गया है (fSendStream) तो
fServerSocket.Socket.Connections [0] .SendStream (fFileStream);

सिवाय
FreeAndNil (fSendStream);
अगर सौंपा (fFileStream) तो FreeAndNil (fFileStream);
पोस्टमेसेज (fOwnerForm.Handle, wm_RefreshClients, cdERROR, 0);
ESendError.CreateRes (@SSendError) बढ़ाएँ;
अंत;
अंत;

मैं ऑनराइट में निम्नलिखित लिखता हूं:

प्रक्रिया TISServerThread। सॉकेटवेयर (प्रेषक: TObject;
गर्तिका: TCustomWinSocket);
शुरू करना
सॉकेट.सेंडस्ट्रीम (fSendStream); // मेमस्ट्रीम भेजें
अगर सौंपा (fFileStream) तो // अगर भेजने के लिए कोई फाइल है, तो उसे ही भेजें
यदि सौंपे नहीं गए हैं (fSendStream) तो // के बाद memStream भेजा गया है
सॉकेट.सेंडस्ट्रीम (fFileStream);
अंत;

लेकिन आखिरकार, एक और संदेश TM_SEND_DATABLOCK दो ऑनराइट घटनाओं के बीच अच्छी तरह से आ सकता है। और मेरी पूरी समस्या यह है कि जब तक फ़ाइल नहीं भेजी जाए, तब तक मीम्सट्रीम पर डेटा लिखना कैसे स्थगित करें?



Digitman   (2003-06-20 14:01) [11]

ऐसा कुछ करने की कोशिश करें:

प्रक्रिया TISServerThread.SendData (var Msg: TMessage);
शुरू करना
// ट्रांसफर कतार में अगला तत्व डालें, वर्तमान संदेश अनुक्रम (wParam के विश्लेषण के अनुसार) के अनुसार प्रेषित करने की आवश्यकता के मापदंडों को दर्शाते हुए:
// यदि एक निश्चित डेटा ब्लॉक है, तो - इसके लिए एक सूचक
// यदि फ़ाइल है, तो फ़ाइल का नाम या TFileStream ऑब्जेक्ट वहीं बनाया गया है (कतार के नए ऑब्जेक्ट-तत्व के क्षेत्र के रूप में)

यदि असाइन नहीं किया गया है (fSendStream) तो
शुरू करना
// अतुल्यकालिक स्थानांतरण तंत्र आरंभ करें
सॉकेटवाइट (MySocketComp; MySocketComp। सॉकेट);
अंत;

प्रक्रिया TISServerThread। सॉकेटवेयर (प्रेषक: TObject;
गर्तिका: TCustomWinSocket);
शुरू करना
यदि असाइन नहीं किया गया है (fSendStream) तो
शुरू करना
fSendStream: = TISMemoryStream.Create (नष्ट करें);
समाप्त
कोशिश
CurPos: = fSendStream.Position;
fSendStream.Position: = fSendStream.Size;
fSendStream.Position: = करपोस;
// !!!!!!!!!!!!!

// (1) यहां, यदि वर्तमान फाइलस्ट्रीम को स्थानांतरित किया जाता है (जो लिंक कतार के ऑब्जेक्ट-तत्व के वर्तमान क्षेत्र से लिया गया है) और इसे पूरी तरह से स्कूप नहीं किया गया है, तो fendendream के अंत में लिखें 4 से अधिक नहीं इस फाइलस्ट्रीम में

// अगर यह ऊब गया है तो वर्तमान फिल्म्स को नष्ट कर दें
// और एक नया FileStream के निर्माण के साथ कतार के echel.el-t को पढ़ें, यदि कतार गैर-रिक्त है और जिसे कतार द्वारा (1) संक्रमण के साथ आवश्यक है।
// !!!!!!!!!!!!!

// यदि अन्य डेटा प्रेषित किया जा रहा है, जो वर्तमान कतार द्वारा इंगित किया गया है, तो गेरू लिखें। उनका भाग XSUMX से अधिक नहीं है fSendStream के अंत तक
// अन्यथा (1) के संक्रमण के साथ echelon.el-t कतार पढ़ें।

// यहां हम स्ट्रीम को ट्रांसफर करने की देरी के प्रयास को दोहराते हैं

( fSendStream) कुछ इस तरह से करने की कोशिश करें:

प्रक्रिया TISServerThread.SendData (var Msg: TMessage);
शुरू करना
// ट्रांसफर कतार में अगला तत्व डालें, वर्तमान संदेश अनुक्रम (wParam के विश्लेषण के अनुसार) के अनुसार प्रेषित करने की आवश्यकता के मापदंडों को दर्शाते हुए:
// यदि एक निश्चित डेटा ब्लॉक है, तो - इसके लिए एक सूचक
// यदि फ़ाइल है, तो फ़ाइल का नाम या TFileStream ऑब्जेक्ट वहीं बनाया गया है (कतार के नए ऑब्जेक्ट-तत्व के क्षेत्र के रूप में)

यदि असाइन नहीं किया गया है (fSendStream) तो
शुरू करना
// अतुल्यकालिक स्थानांतरण तंत्र आरंभ करें
सॉकेटवाइट (MySocketComp; MySocketComp। सॉकेट);
अंत;

प्रक्रिया TISServerThread। सॉकेटवेयर (प्रेषक: TObject;
गर्तिका: TCustomWinSocket);
शुरू करना
यदि असाइन नहीं किया गया है (fSendStream) तो
शुरू करना
fSendStream: = TISMemoryStream.Create (नष्ट करें);
समाप्त
कोशिश
CurPos: = fSendStream.Position;
fSendStream.Position: = fSendStream.Size;
fSendStream.Position: = करपोस;
// !!!!!!!!!!!!!

// (1) यहां, यदि वर्तमान फाइलस्ट्रीम को स्थानांतरित किया जाता है (जो लिंक कतार के ऑब्जेक्ट-तत्व के वर्तमान क्षेत्र से लिया गया है) और इसे पूरी तरह से स्कूप नहीं किया गया है, तो fendendream के अंत में लिखें 4 से अधिक नहीं इस फाइलस्ट्रीम में

// अगर यह ऊब गया है तो वर्तमान फिल्म्स को नष्ट कर दें
// और एक नया FileStream के निर्माण के साथ कतार के echel.el-t को पढ़ें, यदि कतार गैर-रिक्त है और जिसे कतार द्वारा (1) संक्रमण के साथ आवश्यक है।
// !!!!!!!!!!!!!

// यदि अन्य डेटा प्रेषित किया जा रहा है, जो वर्तमान कतार द्वारा इंगित किया गया है, तो गेरू लिखें। उनका भाग XSUMX से अधिक नहीं है fSendStream के अंत तक
// अन्यथा (1) के संक्रमण के साथ echelon.el-t कतार पढ़ें।

// यहां हम स्ट्रीम को ट्रांसफर करने की देरी के प्रयास को दोहराते हैं

सॉकेट.सेंडस्ट्रीम (fSendStream);

सिवाय
// महत्वपूर्ण परिवहन त्रुटि उत्पन्न हुई - यहाँ हम बिना शर्त स्पष्ट हैं (और, यदि आवश्यक हो, तो ट्रांसमिशन कतार)
fSendStream.Free; // और बफर ऑब्जेक्ट स्ट्रीम भी हैं
बढ़ा; // एक अपवाद है कि Execute () स्तर पर रोका जाएगा पुनर्जीवित
अंत;
अंत;




Akni   (2003-06-24 13:36) [12]

मुझे यह कोड मिला है:

प्रक्रिया TISServerThread.SendData (var Msg: TMessage); var डेटब्लॉक: TISDataBlock; // TISDataBlock = वर्ग (TMemoryStream) शुरू करना डेटब्लॉक: = टीआईएसडाटाब्लॉक। क्रिएट; कोशिश मामला msg.wParam का cdREC: DatBlock.Write ((Pointer (msg.lParam)) ^, DatBlock.BytesReserved + SizeOf (ISRecDat)); ... cdFILE_TOCLIENT: शुरू करना fFileDat: = FileData; DatBlock.WriteBlock (Ms.wParam, SizeOf (ISFileDat), fFileDat); अंत; अंत; fSendQueue.Push (DatBlock); यदि नहीं दिया गया (fSendStream) उसके बाद सॉकेटवाइट (fServerSocket, fServerSocket.Socket.Connections [0]); अंत में डेटब्लॉक: = नील; अंत; अंत;

प्रक्रिया TISServerThread.WriteBlockInStream; var sz: पूर्णांक; fDat: ISFileDat; Buf: सरणी [0..BufSize] बाइट; // BufSize = 4095 स्ट्रीमसाइज़: पूर्णांक; शुरू करना StreamSize: = fSendStream.Size; sz: = fSendDataBlock.Size-fSendDataBlock.Position; अगर sz <BufSize-StreamSize तो // स्ट्रीम में बाकी डेटा लिखें शुरू करना fSendDataBlock.ReadBuffer (Buf, sz); fSendStream.WriteBuffer (Buf, sz); मामला fSendDataBlock.Code // भेजा गया डेटा के आधार पर cdFILE_TOCLIENT: // - एक फाइल स्ट्रीम बनाएं, जिसमें से यह बाद में होगा शुरू // संचारित जानकारी fSendDataBlock.ReadData (fDat); fFileStream: = TFileStream.Create (fDat.fServerName, fmOpenRead या fmShareCompat); कोशिश FreeAndNil (fSendDataBlock); fSendDataBlock: = TISDataBlock.Create; // स्ट्रीम आईडी को लिखें। फ़ाइल fSendDataBlock.Code: = cdFILE; // और इसका आकार fSendDataBlock.DataSize: = fFileStream.Size; सिवाय बढ़ा; अंत; अंत; cdFILE: // फ़ाइल अपलोड ध्वज सेट करें शुरू करना fFileToSend: = true; FreeAndNil (fSendDataBlock); अंत; और // मुफ्त मेमोरी FreeAndNil (fSendDataBlock); अंत; अंत और // sz> BufSize-StreamSize - स्ट्रीम में डेटा का अगला टुकड़ा लिखें शुरू करना fSendDataBlock.ReadBuffer (Buf, BufSize-StreamSize); ( Buf, BufSize-StreamSize ) मुझे यह कोड मिला है: procedure TISServerThread.SendData(var Msg: TMessage); var DatBlock: TISDataBlock; // TISDataBlock = class (TMemoryStream) begin DatBlock:=TISDataBlock.Create; try case msg.wParam of cdREC: DatBlock.Write((Pointer(msg.lParam))^,DatBlock.BytesReserved +SizeOf(ISRecDat)); ... cdFILE_TOCLIENT: begin fFileDat:=FileData; DatBlock.WriteBlock(msg.wParam,SizeOf(ISFileDat),fFileDat); end; end; fSendQueue.Push(DatBlock); if not Assigned(fSendStream) then SocketWrite(fServerSocket, fServerSocket.Socket.Connections[0]); finally DatBlock:=nil; end; end;

प्रक्रिया TISServerThread.WriteBlockInStream; var sz: पूर्णांक; fDat: ISFileDat; Buf: सरणी [0..BufSize] बाइट; // BufSize = 4095 स्ट्रीमसाइज़: पूर्णांक; शुरू करना StreamSize: = fSendStream.Size; sz: = fSendDataBlock.Size-fSendDataBlock.Position; अगर sz <BufSize-StreamSize तो // स्ट्रीम में बाकी डेटा लिखें शुरू करना fSendDataBlock.ReadBuffer (Buf, sz); fSendStream.WriteBuffer (Buf, sz); मामला fSendDataBlock.Code // भेजा गया डेटा के आधार पर cdFILE_TOCLIENT: // - एक फाइल स्ट्रीम बनाएं, जिसमें से यह बाद में होगा शुरू // संचारित जानकारी fSendDataBlock.ReadData (fDat); fFileStream: = TFileStream.Create (fDat.fServerName, fmOpenRead या fmShareCompat); कोशिश FreeAndNil (fSendDataBlock); fSendDataBlock: = TISDataBlock.Create; // स्ट्रीम आईडी को लिखें। फ़ाइल fSendDataBlock.Code: = cdFILE; // और इसका आकार fSendDataBlock.DataSize: = fFileStream.Size; सिवाय बढ़ा; अंत; अंत; cdFILE: // फ़ाइल अपलोड ध्वज सेट करें शुरू करना fFileToSend: = true; FreeAndNil (fSendDataBlock); अंत; और // मुफ्त मेमोरी FreeAndNil (fSendDataBlock); अंत; अंत और // sz> BufSize-StreamSize - स्ट्रीम में डेटा का अगला टुकड़ा लिखें शुरू करना fSendDataBlock.ReadBuffer (Buf, BufSize-StreamSize); fSendStream.WriteBuffer (Buf, BufSize-StreamSize); अंत; अंत;



Akni   (2003-06-24 13:37) [13]

प्रक्रिया TISServerThread। सॉकेटवेयर (प्रेषक: TObject;
गर्तिका: TCustomWinSocket);
var बूल: बूलियन;
Buf: सरणी [0..BufSize] बाइट;
एसजे: पूर्णांक;
CurPos: पूर्णांक;
स्ट्रीमसाइज़: पूर्णांक;
bRes: बूलियन;
एररकोड: पूर्णांक;

शुरू करना
यदि नहीं दिया गया (fSendStream)
उसके बाद fSendStream: = TISMemoryStream.Create (नष्ट करें);

कोशिश
बूल: = सच;
जबकि बूल करते हैं
शुरू करना
यदि नहीं दिया गया (fSendStream)
उसके बाद fSendStream: = TISMemoryStream.Create (नष्ट करें);

StreamSize: = fSendStream.Size;
CurPos: = fSendStream.Position;
fSendStream.Position: = fSendStream.Size;

यदि असाइन किया गया (fFileStream) और (fFileToSend) तो // फाइल को भेजना होगा
शुरू करना
sz: = fFileStream.Size-fFileStream.Position;
fLogStr: = "FileStream.Size =" + IntToStr (sz);
सिंक्रनाइज़ (wrLog);
अगर sz <BufSize-StreamSize तो
शुरू करना
fFileStream.ReadBuffer (Buf, sz);
fSendStream.WriteBuffer (Buf, sz);
FreeAndNil (fFileStream);
fFileToSend: = false;
समाप्त
और // sz> BufSize-StreamSize
शुरू करना
fFileStream.ReadBuffer (Buf, BufSize-StreamSize);
fSendStream.WriteBuffer (Buf, BufSize-StreamSize);
अंत;
समाप्त

अन्य
अगर सौंपा (fSendDataBlock) // डेटा भेजने के लिए
उसके बाद WriteBlockInStream
अन्य
अगर fSendQueue.Count> 0 // अगर कतार में अधिक डेटा है, तो इसे पढ़ें
तो // fSendDataBlock में और भेजें
शुरू करना
fSendDataBlock: = TISDataBlock.Create;
fSendDataBlock: = fSendQueue.Pop;
fSendDataBlock.Position: = 0;
WriteBlockInStream;
समाप्त
// // भेजने के लिए और कोई डेटा नहीं है, एक लूप से बाहर निकलें
शुरू करना
बूल: = झूठी;
FreeAndNil (fSendStream);
अंत;

यदि असाइन किया गया (fSendStream) तो // स्ट्रीम भेजें
शुरू करना
fSendStream.Position: = करपोस;
bRes: = सॉकेट.सेंडस्ट्रीम (fSendStream);
यदि नहीं तो bRes
शुरू करना
ErrCode: = WSAGetLastError;
fLogStr: = "ErrorCode =" + IntToStr (ErrCode);
सिंक्रनाइज़ (Wrogog);
यदि इरोडकोड <> WSAEWOULDBLOCK है तो ESendError.CreateRes (@SSendError) बढ़ाएँ;
अंत;
अंत;
अंत;
सिवाय
fSendQueue.Free;
fSendStream.Free;
( @SSendError) कार्यविधि TISServerThread। सॉकेटवेयर (प्रेषक: TObject;
गर्तिका: TCustomWinSocket);
var बूल: बूलियन;
Buf: सरणी [0..BufSize] बाइट;
एसजे: पूर्णांक;
CurPos: पूर्णांक;
स्ट्रीमसाइज़: पूर्णांक;
bRes: बूलियन;
एररकोड: पूर्णांक;

शुरू करना
यदि नहीं दिया गया (fSendStream)
उसके बाद fSendStream: = TISMemoryStream.Create (नष्ट करें);

कोशिश
बूल: = सच;
जबकि बूल करते हैं
शुरू करना
यदि नहीं दिया गया (fSendStream)
उसके बाद fSendStream: = TISMemoryStream.Create (नष्ट करें);

StreamSize: = fSendStream.Size;
CurPos: = fSendStream.Position;
fSendStream.Position: = fSendStream.Size;

यदि असाइन किया गया (fFileStream) और (fFileToSend) तो // फाइल को भेजना होगा
शुरू करना
sz: = fFileStream.Size-fFileStream.Position;
fLogStr: = "FileStream.Size =" + IntToStr (sz);
सिंक्रनाइज़ (wrLog);
अगर sz <BufSize-StreamSize तो
शुरू करना
fFileStream.ReadBuffer (Buf, sz);
fSendStream.WriteBuffer (Buf, sz);
FreeAndNil (fFileStream);
fFileToSend: = false;
समाप्त
और // sz> BufSize-StreamSize
शुरू करना
fFileStream.ReadBuffer (Buf, BufSize-StreamSize);
fSendStream.WriteBuffer (Buf, BufSize-StreamSize);
अंत;
समाप्त

अन्य
अगर सौंपा (fSendDataBlock) // डेटा भेजने के लिए
उसके बाद WriteBlockInStream
अन्य
अगर fSendQueue.Count> 0 // अगर कतार में अधिक डेटा है, तो इसे पढ़ें
तो // fSendDataBlock में और भेजें
शुरू करना
fSendDataBlock: = TISDataBlock.Create;
fSendDataBlock: = fSendQueue.Pop;
fSendDataBlock.Position: = 0;
WriteBlockInStream;
समाप्त
// // भेजने के लिए और कोई डेटा नहीं है, एक लूप से बाहर निकलें
शुरू करना
बूल: = झूठी;
FreeAndNil (fSendStream);
अंत;

यदि असाइन किया गया (fSendStream) तो // स्ट्रीम भेजें
शुरू करना
fSendStream.Position: = करपोस;
bRes: = सॉकेट.सेंडस्ट्रीम (fSendStream);
यदि नहीं तो bRes
शुरू करना
ErrCode: = WSAGetLastError;
fLogStr: = "ErrorCode =" + IntToStr (ErrCode);
सिंक्रनाइज़ (Wrogog);
यदि इरोडकोड <> WSAEWOULDBLOCK है तो ESendError.CreateRes (@SSendError) बढ़ाएँ;
अंत;
अंत;
अंत;
सिवाय
fSendQueue.Free;
fSendStream.Free;
ESendError.CreateRes (@SSendError) बढ़ाएँ;
अंत;
अंत;
उपरोक्त कोड सर्वर साइड कोड है। क्लाइंट साइड पर कोड लगभग पूरी तरह से समान है।

इसलिए, जब कम से कम कई सौ Kb और अधिक (उदाहरण के लिए, एक ही फाइल), डेटा का हिस्सा सफलतापूर्वक भेजा जा रहा है, और तब एक स्ट्रीम भेजने के लिए सभी प्रयास WSAEWOULDBLOCK (ErrCode = XNXX) दे

ऐसा क्यों हो रहा है? डेटा एक्सचेंज का परीक्षण या तो एक कंप्यूटर पर, या दो लैन पर किया जाता है, ताकि कनेक्शन की अनुपलब्धता / अस्थिरता की संभावना कम हो।

विशेष रूप से पहले से ही S सॉकेट-हेडस्ट्रीम (TFileStream.Create (fDat.fServerName, fmOpenRead या fmShareCompat) को सफलतापूर्वक भेजने के बाद से)



Digitman   (2003-06-24 15:09) [14]

...
यदि असाइन किया गया (fSendStream) तो // स्ट्रीम भेजें
शुरू करना
fSendStream.Position: = करपोस;
( fSendStream) ...
यदि असाइन किया गया (fSendStream) तो // स्ट्रीम भेजें
शुरू करना
fSendStream.Position: = करपोस;
सॉकेट.सेंडस्ट्रीम (fSendStream);
अंत;
अंत;
...

इसलिए यह अधिक सटीक होगा।

fSendStream ऑब्जेक्ट ही, जैसा कि आप पहले से ही जानते हैं, ऑटो-की द्वारा नष्ट कर दिया जाएगा, अगर इससे प्राप्त सभी डेटा सफलतापूर्वक ट्रांसफर के लिए भेजे जाते हैं

अन्यथा, OnWrite ईवेंट बाद में फिर से दिखाई देगा।



Akni   (2003-06-25 11:33) [15]


> fSendStream ऑब्जेक्ट ही, जैसा कि आप पहले से ही जानते हैं, नष्ट हो जाएगा
> ऑटोमैटिक-की, अगर इससे प्राप्त सभी डेटा सफलतापूर्वक भेजे जाते हैं
> स्थानांतरण


लेकिन आपको अभी भी स्ट्रीम भेजने के लिए कुछ प्रकार की जांच करने की आवश्यकता है और, अगर यह पूरी तरह से नहीं भेजा गया है (नष्ट नहीं हुआ), तो ऑनराइट संचालक को छोड़ दें?




Digitman   (2003-06-25 14:45) [16]

क्यों ?? किसी सत्यापन की आवश्यकता नहीं है !!

विधि को बुलाओ SendWream (fSendStream) OnWrite () - और सभी व्यवसाय!) में भी विधि को कॉल करने के परिणाम का विश्लेषण किए बिना!
यदि पूरी तरह से स्ट्रीम ट्रांसफर बफर में "चला जाता है", तो FSendStream इसे ऑटो-नष्ट कर देगा, अन्यथा OnWrite () थोड़ी देर बाद फिर से दिखाई देगा

मैं अब भी आपको SendStream () और SendStreamPhew () विधियों के सोर्स कोड की सावधानीपूर्वक जाँच करने की सलाह देता हूँ - एक बार सब कुछ स्पष्ट हो जाएगा कि वहाँ क्या चल रहा है और किन शर्तों के तहत



Akni   (2003-06-25 15:02) [17]


> मैं अभी भी आपको स्रोत की सावधानीपूर्वक जांच करने की सलाह देता हूं
> तरीके SendStream () और SendStreamPhew ()
- हाँ, मैं उन्हें दिल से जानता हूँ :)

अब जो होता है वह निम्नलिखित है:

स्ट्रीम भेजने के बाद

यदि असाइन किया गया (fSendStream) तो // स्ट्रीम भेजें
शुरू करना
fSendStream.Position: = करपोस;
सॉकेट.सेंडस्ट्रीम (fSendStream);
अंत;
अंत;

यह (धारा) तुरंत जारी नहीं किया जाता है (अधिक सटीक, हमेशा तुरंत नहीं)। और इस मामले में, ऑनराइट विधि मेरे लिए निश्चित रूप से तय है :(

यह डालने के बाद मदद करता है
सॉकेट.सेंडस्ट्रीम (fSendStream);

नींद की रेखाएं (10)

फिर धागा सफलतापूर्वक जारी किया जाता है और फिर सब कुछ ठीक हो जाता है।
लेकिन यह, IMHO, एक बहुत बुरा निर्णय है ...



Digitman   (2003-06-25 15:31) [18]

सही ढंग से!)

आपके पास वही है जबकि बूल करते हैं! "
और उसे इसकी बिल्कुल भी ज़रूरत नहीं है)

जब से यह घटना घटी, यह कहता है कि SendStream (fSendStream) (जहाँ भी इसे बनाया गया था - इस हैंडलर में या इसके बाहर) के लिए पिछला कॉल WSAEWOULDBLOCK के साथ समाप्त हुआ (स्थानांतरण बफर उस समय व्यस्त था ... जबकि (देखें) विधि के स्रोत) विधि सही है। इस सत्य के द्वारा, धारा हस्तांतरण की वर्तमान स्थिति का न्याय करना असंभव है, और यह आवश्यक नहीं है - अगला ऑनराइट () घटना विलंबित हस्तांतरण तथ्य के बारे में ही बताएगा।


इस प्रकार, आप सभी को इस घटना की आवश्यकता है:
- अगर fSendStream = nil है, तो इसे बनाएं (यदि हस्तांतरण कतार गैर-रिक्त है)
- fSendStream की पूंछ के लिए एक और डेटा ब्लॉक लिखें (फ़ाइल या किसी अन्य चीज़ के टुकड़े को मिटा दें - इससे कोई फर्क नहीं पड़ता) यदि हस्तांतरण कतार में एक या दूसरे की आवश्यकता होती है, और प्रसंस्करण के अंत में SendStream (fSendStream) को फिर से निष्पादित करें;



Akni   (2003-06-25 17:13) [19]

कहीं मैं शायद बहुत धीमा कर रहा हूँ ...

1 विकल्प।
1.1 fSendStream को लिखिए 4 kb जानकारी (से, कहिए, 25kb)
1.2 SendStream (fSendStream) संपूर्ण स्ट्रीम नहीं भेज सकता है और WSAEWOULDBLOCK के साथ समाप्त होता है
1.3 OnWrite को पुन: दोहराते हुए पी। 1.1 कहा जाता है। और इसी तरह।

2 विकल्प।
2.1 fSendStream को लिखिए 4 kb जानकारी (से, कहिए, 25kb)
2.2 SendStream (fSendStream) पूरी स्ट्रीम (4 kb) को सुरक्षित रूप से भेजता है। OnWrite घटना अपूर्ण हस्तांतरण की प्रतिक्रिया के रूप में नहीं होती है।
2.3 शेष 19 KB "हवा में लटका"



Digitman   (2003-06-26 08:25) [20]

विकल्प 2 देखें

लेकिन आपने अपने ऑब्जेक्ट को इसके विनाश के बारे में सूचित करने के लिए fSendStream "सिखाया" ... जो इसकी सभी सामग्री के सफल हस्तांतरण के मामले में SendStreamPhew () में होता है ... इसलिए इस तथ्य का उपयोग विश्लेषण करने के लिए करें कि क्या यह आपके स्वयं में है हस्तांतरण कतार डेटा हस्तांतरण करने के लिए आवश्यक!



Akni   (2003-06-26 11:14) [21]

डिजिटमैन, सलाह और धैर्य के लिए बहुत बहुत धन्यवाद :)!
सब कुछ बदल गया।



Digitman   (2003-06-26 11:35) [22]


> अकनी


शाबाश!
आप को सफलता!



पन्ने: 1 पूरी शाखा

फोरम: "नेटवर्क";
वर्तमान संग्रह: 2003.09.01;
डाउनलोड करें: [xml.tar.bz2];

ऊपर





मेमोरी: 0.73 एमबी
समय: 0.067 c
1-1496
निर्माता
2003-08-18 03:31
2003.09.01
TXMLDocument और लाइन ब्रेक


14-1585
फेलिक्स
2003-08-13 22:24
2003.09.01
क्या आप जानते हैं कि आज और कल यिंग में न जाना बेहतर है?


14-1617
हड्डियों
2003-08-13 14:58
2003.09.01
धन्यवाद यूरी फेडोरोव और अन्य मास्टर।


1-1501
विक्टर कुशनिर
2003-08-17 15:45
2003.09.01
पाठ प्राप्त करें


14-1639
पाक अधिकृत कश्मीर
2003-08-12 15:28
2003.09.01
एक इच्छा पर DBLookUpComboBox!





अफ्रीकी अल्बानियन अरबी भाषा अर्मेनियाई आज़रबाइजानी बस्क बेलारूसी बल्गेरियाई कैटलन सरलीकृत चीनी) चीनी पारंपरिक) क्रोएशियाई चेक डेनिश डच अंग्रेज़ी एस्तोनियावासी फिलिपिनो फिनिश फ्रेंच
गैलिशियन् जॉर्जियाई जर्मन यूनानी हाईटियन यहूदी हिंदी हंगरी आइसलैंड का इन्डोनेशियाई आयरिश इतालवी जापानी कोरियाई लात्वीयावासी लिथुआनियाई मेसीडोनियन मलायी मोलतिज़ नार्वेजियन
फ़ारसी पोलिश पुर्तगाली रोमानियाई रूसी सर्बियाई स्लोवाक स्लोवेनियाई स्पेनिश स्वाहिली स्वीडिश थाई तुर्की यूक्रेनी उर्दू वियतनामी वेल्श यहूदी बंगाली बोस्नियाई
सिबुआनो एस्पेरांतो गुजराती हौसा हमोंग ईग्बो जावानीस कन्नड़ खमेर लाओ लैटिन माओरी मराठी मंगोलियन नेपाली पंजाबी सोमाली तामिल तेलुगु योरूबा
ज़ुलु
Английский Французский Немецкий Итальянский Португальский Русский Испанский