डेल्फीमधील क्लायंट सॉकेटसह काम करण्याची उदाहरणे. डेल्फी मध्ये प्रोग्रामिंग सॉकेट-आधारित सर्व्हर. सॉकेट सर्व्हर ऑपरेशन अल्गोरिदम

बातम्या 02.07.2020
बातम्या

हा लेख डेल्फी घटकांचे मूलभूत गुणधर्म आणि कार्ये यावर चर्चा करेल: TClientSocket आणि TServerSocket - TCP\IP प्रोटोकॉल वापरून नेटवर्कसह कार्य करण्यासाठी वापरले जाते.

लक्ष द्या!जर तुम्ही डेल्फीची 6.0 पेक्षा जास्त आवृत्ती वापरत असाल, तर तुम्हाला प्रथम डेल्फीच्या सर्व आवृत्त्यांमध्ये सॉकेट्सचे घटक स्थापित करणे आवश्यक आहे:

  • Install Packages वर जा... डायलॉग: (मुख्य मेनू) घटक -> पॅकेजेस स्थापित करा;
  • Add… बटणावर क्लिक करा, त्यानंतर आम्हाला तुमच्या डेल्फीचे बिन फोल्डर सापडेल (उदाहरणार्थ: C:\Program Files\Borland\Delphi 7\bin, किंवा C:\Program Files\Embarcadero\RAD Studio\7.0\Bin) ;
  • सापडलेल्या बिन फोल्डरमध्ये आम्ही आधीच फाइल शोधत आहोत dclsockets [येथे संख्या आहेत].bpl, ओके क्लिक करा;
  • आम्ही आनंदी आहोत कारण आता आमच्याकडे घटक पॅनेलच्या इंटरनेट टॅबवर TServerSocket आणि TClientSocket हे दोन अद्भुत घटक आहेत.

कोणतेही नेटवर्क ऍप्लिकेशन विकसित करताना, सामान्यतः विकास नेहमी सर्व्हरने सुरू होतो (अर्थातच, जर तुमच्याकडे एक कार्यसंघ असेल, तर इंटरफेस डिझाइनर क्लायंटवर कार्य करण्यास प्रारंभ करू शकतात). सर्व्हरची अंमलबजावणी करण्यासाठी, आश्चर्याची गोष्ट म्हणजे, आपल्याला TServerSocket वापरण्याची आवश्यकता आहे.

मूलभूत गुणधर्म:

  • सक्रिय– एक बुलियन फील्ड, सत्य वर सेट केल्यावर – सर्व्हर सुरू होतो, तुम्ही विशिष्ट मूल्ये नियुक्त करून किंवा ServerSocket1.Open (... Active:=true;) किंवा ServerSocket1.Close (..) फंक्शन कॉल करून वापरू शकता. सक्रिय:=असत्य).
  • बंदर- पोर्ट ज्यावर सर्व्हर ऐकेल (क्लायंट प्राप्त करेल), श्रेणीतील कोणतेही मूल्य जे सिस्टममधील इतर सर्व्हरद्वारे व्यापलेले नाही. पूर्णांक.

मुख्य कार्यक्रम:

  • ऐका- जेव्हा सर्व्हर ऐकण्याच्या मोडवर सेट केला जातो तेव्हा कॉल केला जातो, जेव्हा आम्हाला सर्व्हरच्या वास्तविक प्रारंभाची वेळ निर्धारित करण्याची आवश्यकता असते तेव्हा वापरली जाऊ शकते.
  • OnClientRead- क्लायंटकडून डेटा प्राप्त झाल्यावर कॉल केला जातो.
  • OnClientError
  • OnClientConnect- जेव्हा नवीन क्लायंट सर्व्हरमध्ये सामील होतो तेव्हा कॉल केला जातो.
  • OnClientDisconnect- इव्हेंट इव्हेंटवर उलटा, OnClientConnect

प्रत्येक इव्हेंट फंक्शनमध्ये एक विशेषता असते सॉकेट: TCustomWinSocket, ज्या सॉकेट ऑब्जेक्टसह आपण सध्या काम करत आहोत त्याकडे एक पॉइंटर पास केला जातो, जर आम्हाला क्लायंटला इव्हेंट कारणीभूत असलेल्या क्लायंटला प्रतिसाद देण्याची किंवा काहीतरी करण्याची आवश्यकता असल्यास, आम्हाला या विशिष्ट ऑब्जेक्टचा वापर करणे आवश्यक आहे, इतर सर्व प्रकरणांमध्ये आम्ही वापरतो सर्व्हरसॉकेट1.सॉकेट, क्लायंट घटकाची परिस्थिती समान आहे.

केवळ वाचनीय गुणधर्म आणि कार्ये:

  • - सक्रिय कनेक्शनची संख्या परत करते.
  • ServerSocket1.Socket.Connections– TCustomWinSocket प्रकारातील ऑब्जेक्ट्सचा ॲरे, क्लायंटशी संबंधित सर्व ऑब्जेक्ट्सचा ॲरे, इंडेक्स मोजणी 0 पासून सुरू होते, ॲरेची लांबी आहे ServerSocket1.Socket.ActiveConnections.
  • ServerSocket1.Socket.Connections ॲरे आणि सर्व्हर इव्हेंट फंक्शनला पास केलेल्या सॉकेट विशेषताच्या घटकांवर लागू होणारी कार्ये आणि गुणधर्म:
  • Socket.LocalHost
  • Socket.LocalAddress- सर्व्हर आयपी परत करते.
  • सॉकेट.रिमोटहोस्ट
  • सॉकेट.रिमोट ॲड्रेस- क्लायंट आयपी परत करते.
  • Socket.ReceiveText- क्लायंटकडून प्राप्त केलेला मजकूर संदेश परत करतो, ज्यानंतर तो बफर साफ करतो, प्रति 1 रिसेप्शन फक्त 1 वेळा वापरला जाऊ शकतो.
  • Socket.SendText(मजकूर)- क्लायंटला टेक्स्ट प्रकाराचा मजकूर संदेश पाठवते स्ट्रिंग.

TClientSocket घटकासाठी, सर्वकाही व्यावहारिकदृष्ट्या समान आहे, फक्त उलट + सर्व्हर आणि क्लायंटमधील मुख्य दृश्य फरक म्हणजे सिस्टममधील सर्व्हर 1 बाय 1 पोर्ट मूल्याने लॉन्च केला जाऊ शकतो, क्लायंटची संख्या केवळ RAM द्वारे मर्यादित आहे. .

मूलभूत गुणधर्म:

  • सक्रिय– एक बुलियन फील्ड, सत्य वर सेट केल्यावर – क्लायंट सर्व्हरशी कनेक्ट करण्याचा प्रयत्न करत आहे, एकतर विशिष्ट मूल्ये नियुक्त करून किंवा ClientSocket1.Open (... Active:=true;) किंवा ClientSocket1 फंक्शन कॉल करून वापरले जाऊ शकते. .बंद करा (... सक्रिय:=असत्य) .
  • बंदर- पोर्ट ज्याद्वारे क्लायंट सर्व्हरशी कनेक्ट करू शकतो, श्रेणीतील कोणतेही मूल्य पूर्णांक.
  • पत्ता- सर्व्हर प्रकाराचा IPv4 पत्ता स्ट्रिंगनमुना 255.255.255.255 नुसार, ज्यासह क्लायंट कनेक्ट करेल.

मुख्य कार्यक्रम:

  • ऑनरीड- जेव्हा उत्तरेकडून डेटा प्राप्त होतो तेव्हा कॉल केला जातो.
  • ऑन एरर- जेव्हा डेटा ट्रान्समिशनमध्ये एरर येते तेव्हा म्हणतात.
  • कनेक्ट करत आहे- जेव्हा क्लायंट सर्व्हरमध्ये सामील होतो तेव्हा कॉल केला जातो.
  • ऑनडिस्कनेक्ट- इव्हेंट इव्हेंटवर उलटा, कनेक्ट करत आहे, जेव्हा क्लायंट सर्व्हरवरून डिस्कनेक्ट होतो तेव्हा कॉल केला जातो.

केवळ वाचनीय गुणधर्म आणि कार्ये:

  • ClientSocket1.Socket.SendText() स्ट्रिंग
  • Socket.LocalHost- क्लायंटचे ऑनलाइन नाव परत करते.
  • Socket.LocalAddress- क्लायंट आयपी परत करते.
  • सॉकेट.रिमोटहोस्ट- नेटवर्कवरील सर्व्हरचे नाव परत करते.
  • सॉकेट.रिमोट ॲड्रेस- सर्व्हर आयपी परत करते.
  • Socket.ReceiveText- सर्व्हरकडून प्राप्त झालेला मजकूर संदेश परत करतो, त्यानंतर तो बफर साफ करतो, एका वेळी फक्त 1 वेळा वापरला जाऊ शकतो.
  • Socket.SendText(मजकूर)- सर्व्हरला टेक्स्ट प्रकाराचा मजकूर संदेश पाठवते स्ट्रिंग.

प्रदान केलेली माहिती तांत्रिक वैशिष्ट्यांची पूर्तता करणाऱ्या छोट्या सर्व्हर चॅटची अंमलबजावणी करण्यासाठी पुरेशी आहे: internet_sockets.doc (Word Doc 97-2003, 26.5 Kb).

हा लेख रविवार, 10 ऑक्टोबर 2010 रोजी सकाळी 1:24 वाजता विभागात लिहिला होता. आपण लेखावरील टिप्पण्यांवरील अद्यतनांची सदस्यता घेऊ शकता -. आपण करू शकता


हा लेख सॉकेट्स (“सॉकेट्स”) वर आधारित बोरलँड डेल्फीमध्ये क्लायंट/सर्व्हर आर्किटेक्चर ऍप्लिकेशन्स तयार करण्यासाठी समर्पित आहे. सॉकेट्सच्या विषयावरील मागील लेखाच्या विपरीत, येथे आपण सर्व्हर ऍप्लिकेशन्स तयार करण्याकडे पाहू.

हे त्वरित लक्षात घेतले पाहिजे की स्वतंत्र क्लायंट आणि सर्व्हर अनुप्रयोगांच्या सहअस्तित्वासाठी, अनेक संगणक असणे आवश्यक नाही. फक्त एक असणे पुरेसे आहे ज्यावर आपण एकाच वेळी सर्व्हर आणि क्लायंट दोन्ही चालवू शकता. या प्रकरणात, तुम्हाला होस्ट नाव लोकलहोस्ट किंवा IP पत्ता - 127.0.0.1 वापरणे आवश्यक आहे ज्या संगणकाशी तुम्हाला कनेक्ट करणे आवश्यक आहे.

तर, सिद्धांतासह प्रारंभ करूया. जर तुम्ही खात्रीपूर्वक अभ्यासक असाल (आणि तुमच्या डोळ्यांनी कोणतेही अल्गोरिदम पाहू शकत नाही), तर तुम्ही हा विभाग वगळला पाहिजे.

सॉकेट सर्व्हर ऑपरेशन अल्गोरिदम

सॉकेट सर्व्हर तुम्हाला काय करण्याची परवानगी देतो?.. ते कोणत्या तत्त्वावर कार्य करते?.. सॉकेट प्रोटोकॉलवर आधारित सर्व्हर तुम्हाला एकाच वेळी अनेक क्लायंटना सेवा देण्याची परवानगी देतो. शिवाय, तुम्ही त्यांच्या नंबरची मर्यादा स्वतः निर्दिष्ट करू शकता (किंवा ही मर्यादा पूर्णपणे काढून टाकू शकता, जसे की डीफॉल्टनुसार केली जाते). प्रत्येक कनेक्ट केलेल्या क्लायंटसाठी, सर्व्हर एक स्वतंत्र सॉकेट उघडतो ज्याद्वारे आपण क्लायंटसह डेटाची देवाणघेवाण करू शकता. दुसरा उत्तम उपाय म्हणजे प्रत्येक कनेक्शनसाठी स्वतंत्र प्रक्रिया (थ्रेड) तयार करणे.

खाली डेल्फी ऍप्लिकेशन्समध्ये सॉकेट सर्व्हर कसे कार्य करते याचे उदाहरण आकृती आहे:

चला आकृती अधिक तपशीलवार पाहू:

  1. पोर्ट आणि सर्व्हरटाइपची व्याख्या - क्लायंटला सर्व्हरशी सामान्यपणे कनेक्ट करता येण्यासाठी, सर्व्हरद्वारे वापरलेले पोर्ट क्लायंटने वापरलेल्या पोर्टशी (आणि उलट) तंतोतंत जुळणे आवश्यक आहे. सर्व्हरटाइप गुणधर्म कनेक्शन प्रकार निर्धारित करते (अधिक तपशीलांसाठी खाली पहा);
  2. ओपन सॉकेट - सॉकेट आणि निर्दिष्ट पोर्ट उघडते. येथे क्लायंट कनेक्ट होण्याची वाट पाहण्याची स्वयंचलित सुरुवात (ऐका);
  3. क्लायंटला कनेक्ट करणे आणि त्याच्याशी डेटाची देवाणघेवाण करणे - येथे क्लायंट त्याच्याशी डेटा कनेक्ट करतो आणि देवाणघेवाण करतो. आपण या लेखात आणि सॉकेट्स (क्लायंट भाग) बद्दलच्या लेखात या स्टेजबद्दल अधिक जाणून घेऊ शकता;
  4. क्लायंट डिस्कनेक्शन - येथे क्लायंट डिस्कनेक्ट झाला आहे आणि सर्व्हरसह त्याचे सॉकेट कनेक्शन बंद आहे;
  5. सर्व्हर आणि सॉकेट बंद करणे - प्रशासकाच्या आदेशानुसार, सर्व्हर बंद होतो, सर्व खुले सॉकेट चॅनेल बंद करतो आणि क्लायंट कनेक्शनची प्रतीक्षा करणे थांबवतो.
  6. हे नोंद घ्यावे की गुण 3-4 अनेक वेळा पुनरावृत्ती होते, म्हणजे. हे चरण प्रत्येक नवीन क्लायंट कनेक्शनसाठी केले जातात.

टीप:

या क्षणी डेल्फीमध्ये सॉकेट्सवर फारच कमी दस्तऐवजीकरण आहे, म्हणून जर तुम्हाला या विषयाचा शक्य तितका खोलवर अभ्यास करायचा असेल, तर मी तुम्हाला युनिक्स/लिनक्स सिस्टमवरील साहित्य आणि इलेक्ट्रॉनिक दस्तऐवजीकरण पाहण्याचा सल्ला देतो - सॉकेट्ससह कार्य करण्याचा सिद्धांत आहे. तेथे खूप चांगले वर्णन केले आहे. याव्यतिरिक्त, या OS साठी सॉकेट ऍप्लिकेशन्सची अनेक उदाहरणे आहेत (जरी मुख्यतः C/C++ आणि Perl मध्ये).

TServerSocket घटकाचे संक्षिप्त वर्णन

येथे आपण TServerSocket घटकाचे मुख्य गुणधर्म, पद्धती आणि घटनांशी परिचित होऊ.

गुणधर्म इव्हेंट पद्धती:

सॉकेट क्लास TServerWinSocket, ज्याद्वारे तुम्हाला सॉकेट चॅनेल उघडण्यासाठी प्रवेश आहे. पुढे आम्ही या मालमत्तेचा अधिक तपशीलवार विचार करू, कारण खरं तर, ते मुख्यांपैकी एक आहे. प्रकार: TServerWinSocket; सर्व्हर प्रकार सर्व्हर प्रकार. दोन मूल्यांपैकी एक घेऊ शकता: stNonBlocking - क्लायंट सॉकेटसह समकालिक कार्य. या प्रकारच्या सर्व्हरसह, तुम्ही OnClientRead आणि OnClientWrite इव्हेंटद्वारे क्लायंटसह कार्य करू शकता. stThreadBlocking हा असिंक्रोनस प्रकार आहे. प्रत्येक क्लायंट सॉकेट चॅनेलसाठी स्वतंत्र प्रक्रिया (थ्रेड) तयार केली जाते. प्रकार: TServerType; ThreadCacheSize ही क्लायंट प्रक्रियांची (थ्रेड) संख्या आहे जी सर्व्हरद्वारे कॅश केली जाईल. येथे तुम्हाला तुमच्या सर्व्हरवरील लोडवर अवलंबून सरासरी मूल्य निवडण्याची आवश्यकता आहे. कॅशिंग प्रत्येक वेळी एक वेगळी प्रक्रिया तयार करू नये आणि बंद सॉकेट नष्ट करू नये, परंतु नंतरच्या वापरासाठी त्यांना सोडण्यासाठी होते. प्रकार: पूर्णांक; सक्रिय सूचित करते की सर्व्हर सध्या सक्रिय आहे की नाही. म्हणजेच खरे मूल्य हे सूचित करते की सर्व्हर चालू आहे आणि क्लायंट प्राप्त करण्यास तयार आहे आणि असत्य दर्शविते की सर्व्हर बंद आहे. सर्व्हर सुरू करण्यासाठी, तुम्हाला फक्त ही प्रॉपर्टी ट्रूवर सेट करावी लागेल. प्रकार: बुलियन; क्लायंटसह कनेक्शन स्थापित करण्यासाठी पोर्ट पोर्ट नंबर. सर्व्हर आणि क्लायंट पोर्ट समान असणे आवश्यक आहे. 1025 ते 65535 पर्यंतच्या मूल्यांची शिफारस केली जाते, कारण 1 ते 1024 पर्यंत - सिस्टमद्वारे व्यापले जाऊ शकते. प्रकार: पूर्णांक; सेवा ही सेवा परिभाषित करणारी एक स्ट्रिंग आहे (ftp, http, pop, इ.) ज्याचा पोर्ट वापरला जाईल. विविध मानक प्रोटोकॉलशी संबंधित पोर्ट क्रमांकांची ही एक प्रकारची निर्देशिका आहे. प्रकार: स्ट्रिंग; उघडा सर्व्हर सुरू करतो. मूलत:, ही आज्ञा Active प्रॉपर्टीला True वर सेट करण्यासारखीच आहे; सर्व्हर बंद करा. मूलत:, हा आदेश सक्रिय गुणधर्म असत्य वर सेट करण्यासारखा आहे. OnClientConnect तेव्हा घडते जेव्हा क्लायंटने सॉकेट कनेक्शन स्थापित केले असते आणि सर्व्हरकडून प्रतिसादाची प्रतीक्षा करत असते (OnAccept); जेव्हा क्लायंट सॉकेट चॅनेलवरून डिस्कनेक्ट होतो तेव्हा OnClientDisconnect उद्भवते; चालू ऑपरेशन अयशस्वी झाल्यावर OnClientError उद्भवते, उदा. त्रुटी आढळली आहे; जेव्हा क्लायंटने सर्व्हरला काही डेटा पास केला तेव्हा OnClientRead उद्भवते. हा डेटा पुरवलेल्या सॉकेट पॅरामीटरद्वारे प्रवेश केला जाऊ शकतो: TCustomWinSocket; OnClientWrite उद्भवते जेव्हा सर्व्हर क्लायंटला सॉकेटवर डेटा पाठवू शकतो; या इव्हेंटच्या हँडलरमध्ये OnGetSocket तुम्ही ClientSocket पॅरामीटर संपादित करू शकता; या इव्हेंटच्या हँडलरमध्ये OnGetThread तुम्ही इच्छित TServerClientThread सबटास्कला SocketThread पॅरामीटर नियुक्त करून प्रत्येक क्लायंट चॅनेलसाठी एक अद्वितीय प्रक्रिया (थ्रेड) परिभाषित करू शकता; OnThreadStart, OnThreadEnd जेव्हा उपकार्य (प्रक्रिया, थ्रेड) अनुक्रमे सुरू किंवा थांबवले जाते तेव्हा उद्भवते; जेव्हा सर्व्हर क्लायंट स्वीकारतो किंवा कनेक्शन नाकारतो तेव्हा OnAccept उद्भवते; जेव्हा सर्व्हर क्लायंट कनेक्ट होण्याच्या प्रतीक्षेत जातो तेव्हा OnListen होते.

TSserverSocket.Socket(TSServerWinSocket)

तर सर्व्हर क्लायंटला डेटा कसा पाठवू शकतो? डेटा प्राप्त करण्याबद्दल काय? मुळात, जर तुम्ही OnClientRead आणि OnClientWrite इव्हेंटद्वारे काम करत असाल, तर तुम्ही क्लायंटसॉकेट पॅरामीटर (TCustomWinSocket) द्वारे क्लायंटशी संवाद साधू शकता. क्लायंट सॉकेट्सबद्दलच्या लेखात आपण या वर्गासह काम करण्याबद्दल वाचू शकता, कारण या वर्गाद्वारे डेटा पाठवणे/पाठवणे समान आहे - पद्धती (पाठवा/प्राप्त करा)(मजकूर, बफर, प्रवाह). TServerSocket.Socket सह काम करताना हेच लागू होते. तथापि, कारण येथे आम्ही सर्व्हरचा विचार करत आहोत, आम्ही काही उपयुक्त गुणधर्म आणि पद्धती हायलाइट केल्या पाहिजेत:

कनेक्ट केलेल्या क्लायंटची सक्रिय कनेक्शन (पूर्णांक) संख्या; ActiveThreads (पूर्णांक) चालू प्रक्रियांची संख्या; कनेक्शन्स (ॲरे) - प्रत्येक कनेक्ट केलेल्या क्लायंटसाठी स्वतंत्र TClientWinSocket वर्गांचा समावेश असलेला ॲरे. उदाहरणार्थ, ही आज्ञा:


ServerSocket1.Socket.Connections.SendText("हॅलो!");

पहिल्या कनेक्ट केलेल्या क्लायंटला "हॅलो!" संदेश पाठवते. या ॲरेच्या घटकांसह कार्य करण्यासाठी कमांड - देखील (पाठवा/प्राप्त करा)(मजकूर, बफर, प्रवाह); IdleThreads (पूर्णांक) निष्क्रिय प्रक्रियांची संख्या. अशा प्रक्रिया सर्व्हरद्वारे कॅश केल्या जातात (थ्रेडकॅशसाइज पहा); LocalAddress, LocalHost, LocalPort अनुक्रमे - स्थानिक IP पत्ता, होस्ट नाव, पोर्ट; RemoteAddress, RemoteHost, RemotePort अनुक्रमे - रिमोट IP पत्ता, होस्ट नाव, पोर्ट; लॉक आणि अनलॉक पद्धती, अनुक्रमे, सॉकेट ब्लॉक आणि अनब्लॉक करतात.

सराव आणि उदाहरणे

आता विशिष्ट उदाहरण वापरून वरील गोष्टी पाहू. तुम्ही येथे क्लिक करून तयार स्रोत डाउनलोड करू शकता.

तर, TServerSocket सह काम करण्याचे एक चांगले उदाहरण पाहू (हे उदाहरण या घटकाचा अभ्यास करण्यासाठी सर्वात दृश्य मदत आहे). खालील स्रोत सर्व महत्त्वाच्या सर्व्हर इव्हेंटचे लॉगिंग तसेच मजकूर संदेश प्राप्त करण्याची आणि पाठविण्याची क्षमता दर्शवतात:

उदाहरण 1. लॉगिंग आणि सर्व्हरच्या ऑपरेशनचा अभ्यास करणे, सॉकेटद्वारे संदेश पाठवणे/प्राप्त करणे.


(...येथे फाईल हेडर आणि TForm1 ची व्याख्या आणि त्याचे उदाहरण Form1 आहे) प्रक्रिया TForm1.Button1Click(प्रेषक: TObject); सुरू (पोर्ट निश्चित करा आणि सर्व्हर सुरू करा) सर्व्हरसॉकेट1.पोर्ट:= 1025; (इन्सर्ट पद्धत निर्दिष्ट स्थानावर ॲरेमध्ये स्ट्रिंग घालते) Memo2.Lines.Insert(0, "सर्व्हर सुरू होत आहे"); सर्व्हरसॉकेट1.ओपन; शेवट; प्रक्रिया TForm1.Button2Click(प्रेषक: TObject); सुरू (सर्व्हर थांबवा) ServerSocket1.Active:= False; Memo2.Lines.Insert(0, "सर्व्हर थांबला"); शेवट; प्रक्रिया TForm1.ServerSocket1Listen(प्रेषक: TObject; सॉकेट: TCustomWinSocket); सुरू (येथे क्लायंटसाठी सॉकेटवर सर्व्हर "ऐकत" आहे) Memo2.Lines.Insert(0, "पोर्टवर ऐकत आहे" + IntToStr(ServerSocket1.Port)); शेवट; प्रक्रिया TForm1.ServerSocket1Accept(प्रेषक: TObject; सॉकेट: TCustomWinSocket); सुरू (येथे सर्व्हर क्लायंट स्वीकारतो) Memo2.Lines.Insert(0, "क्लायंट कनेक्शन स्वीकारले"); शेवट; प्रक्रिया TForm1.ServerSocket1ClientConnect(प्रेषक: TObject; सॉकेट: TCustomWinSocket); सुरू (येथे क्लायंट कनेक्ट होतो) Memo2.Lines.Insert(0, "क्लायंट कनेक्ट केलेले"); शेवट; प्रक्रिया TForm1.ServerSocket1ClientDisconnect(प्रेषक: TObject; सॉकेट: TCustomWinSocket); सुरू (येथे क्लायंट डिस्कनेक्ट होतो) Memo2.Lines.Insert(0, "क्लायंट डिस्कनेक्ट झाला"); शेवट; प्रक्रिया TForm1.ServerSocket1ClientError(प्रेषक: TObject; सॉकेट: TCustomWinSocket; ErrorEvent: TERrorEvent; varत्रुटी कोड: पूर्णांक); सुरू (एक त्रुटी आली - त्याचा कोड प्रदर्शित करा) Memo2.Lines.Insert(0, "क्लायंट एरर. कोड = " + IntToStr(ErrorCode)); शेवट; प्रक्रिया TForm1.ServerSocket1ClientRead(प्रेषक: TObject; सॉकेट: TCustomWinSocket); सुरू (क्लायंटकडून एक संदेश प्राप्त झाला - तो Memo1 मध्ये प्रदर्शित करा) Memo2.Lines.Insert(0, "क्लायंटकडून मिळालेला संदेश"); Memo1.Lines.Insert(0, "> " + Socket.ReceiveText); शेवट; प्रक्रिया TForm1.ServerSocket1ClientWrite(प्रेषक: TObject; सॉकेट: TCustomWinSocket); सुरू (आता तुम्ही सॉकेटवर डेटा पाठवू शकता) Memo2.Lines.Insert(0, "आता सॉकेटवर लिहू शकतो"); शेवट; प्रक्रिया TForm1.ServerSocket1GetSocket(प्रेषक: TObject; सॉकेट: पूर्णांक; varक्लायंटसॉकेट: TServerClientWinSocket); सुरू Memo2.Lines.Insert(0, "सॉकेट मिळवा"); शेवट; प्रक्रिया TForm1.ServerSocket1GetThread(प्रेषक: TObject; क्लायंटसॉकेट: TServerClientWinSocket; varसॉकेटथ्रेड: TServerClientThread); सुरू Memo2.Lines.Insert(0, "थ्रेड मिळवा"); शेवट; प्रक्रिया TForm1.ServerSocket1ThreadEnd(प्रेषक: TObject; थ्रेड: TServerClientThread); सुरू Memo2.Lines.Insert(0, "थ्रेड एंड"); शेवट; प्रक्रिया TForm1.ServerSocket1ThreadStart(प्रेषक: TObject; थ्रेड: TServerClientThread); सुरू Memo2.Lines.Insert(0, "थ्रेड स्टार्ट"); शेवट; प्रक्रिया TForm1.Button3Click(प्रेषक: TObject); var i: पूर्णांक; सुरू (संपादन1 वरून सर्व क्लायंटना संदेश पाठवा) च्या साठी i:= 0 करण्यासाठी ServerSocket1.Socket.ActiveConnections - 1 करा ServerSocket1.Socket.Connections[i].SendText(Edit1.Text); Memo1.Lines.Insert(0, "end;

TServerSocket सह काम करण्याचे तंत्र (आणि फक्त सॉकेटसह)

प्रत्येक क्लायंटसाठी अद्वितीय डेटा संचयित करणे.

निश्चितच, जर तुमचा सर्व्हर अनेक क्लायंटना सेवा देत असेल, तर तुम्हाला प्रत्येक क्लायंटसाठी (नाव इ.) काही माहिती साठवावी लागेल आणि ही माहिती या क्लायंटच्या सॉकेटशी लिंक करावी लागेल. काही प्रकरणांमध्ये, हे सर्व मॅन्युअली करणे (सॉकेट हँडल, क्लायंट ॲरे इत्यादींना बंधनकारक) करणे फार सोयीचे नसते. म्हणून, प्रत्येक सॉकेटसाठी एक विशेष गुणधर्म आहे - डेटा. खरं तर, डेटा फक्त एक सूचक आहे. म्हणून, या मालमत्तेवर क्लायंट डेटा लिहिताना, सावधगिरी बाळगा आणि पॉइंटर्ससह कार्य करण्याच्या नियमांचे पालन करा (मेमरी वाटप, प्रकार व्याख्या इ.)!

सॉकेटद्वारे फाइल्स पाठवत आहे

येथे आपण सॉकेटद्वारे फाइल्स पाठवण्याकडे लक्ष देऊ (JINX च्या विनंतीनुसार) :-). मग सॉकेटवर फाइल कशी पाठवायची? अगदी साधे! तुम्हाला फक्त ही फाइल फाइल स्ट्रीम (TFileStream) म्हणून उघडायची आहे आणि ती सॉकेट (SendStream) द्वारे पाठवायची आहे! हे एका उदाहरणासह पाहू:


हे नोंद घ्यावे की सेंडस्ट्रीम पद्धत केवळ सर्व्हरद्वारेच नाही तर क्लायंटद्वारे देखील वापरली जाते (ClientSocket1.Socket.SendStream(srcfile))

ट्रान्समिशन दरम्यान अनेक ब्लॉक्स एकामध्ये का एकत्र केले जाऊ शकतात?

हे JINX च्या विनंतीनुसार देखील आहे :-). त्याबद्दल त्यांचे खूप खूप आभार! म्हणून, सर्वप्रथम, हे लक्षात घेतले पाहिजे की सॉकेटद्वारे पाठविलेला डेटा केवळ एका ब्लॉकमध्ये एकत्र केला जाऊ शकत नाही तर अनेक ब्लॉक्समध्ये विभक्त देखील केला जाऊ शकतो. वस्तुस्थिती अशी आहे की सॉकेट हा एक नियमित प्रवाह आहे, परंतु फाइल स्ट्रीम (TFileStream) च्या विपरीत, तो डेटा अधिक हळू हस्तांतरित करतो (आपल्याला समजते - नेटवर्क, मर्यादित रहदारी इ.). म्हणूनच दोन आज्ञा:


ServerSocket1.Socket.Connections.SendText("हॅलो,"); ServerSocket1.Socket.Connections.SendText("world!");

एका आदेशाशी पूर्णपणे समान:


ServerSocket1.Socket.Connections.SendText("हॅलो, वर्ल्ड!");

आणि म्हणूनच, जर तुम्ही सॉकेटद्वारे 100 KB ची फाईल पाठवली, तर तुम्ही ज्या व्यक्तीला हा ब्लॉक पाठवला आहे त्या व्यक्तीला अनेक ब्लॉक्स मिळतील जे ट्रॅफिक आणि लाईन कंजेशनवर अवलंबून असतात. शिवाय, आकार समान असणे आवश्यक नाही. हे खालीलप्रमाणे आहे की फाइल किंवा इतर कोणताही मोठा डेटा स्वीकारण्यासाठी, तुम्ही डेटाचे ब्लॉक्स स्वीकारले पाहिजे आणि नंतर त्यांना एका संपूर्णमध्ये एकत्र केले पाहिजे (आणि जतन करा, उदाहरणार्थ, फाइलमध्ये). या समस्येचे उत्कृष्ट समाधान म्हणजे समान फाइल प्रवाह - TFileStream (किंवा मेमरीमधील प्रवाह - TMemoryStream). तुम्ही सार्वत्रिक ReceiveBuf पद्धत वापरून OnRead (OnClientRead) इव्हेंटद्वारे सॉकेटमधून डेटाचे तुकडे प्राप्त करू शकता. प्राप्त झालेल्या ब्लॉकचा आकार ReceiveLength पद्धत वापरून निर्धारित केला जाऊ शकतो. तुम्ही सॉकेट स्ट्रीम देखील वापरू शकता (TClientSocket बद्दल लेख पहा). आणि येथे एक लहान उदाहरण आहे (अंदाजे):


सॉकेटचे निरीक्षण कसे करावे

ही समस्या गुंतागुंतीची आहे आणि दीर्घ विचार करणे आवश्यक आहे. आत्तासाठी, मी फक्त लक्षात ठेवेन की आपण नेहमी आपल्या प्रोग्रामद्वारे तयार केलेल्या सॉकेटचे निरीक्षण करू शकता :-). सॉकेट्स (विंडोजमधील बहुतेक वस्तूंप्रमाणे) त्यांचे स्वतःचे हँडल असते, हँडल गुणधर्मामध्ये लिहिलेले असते. त्यामुळे, एकदा तुम्ही हा वर्णनकर्ता ओळखल्यानंतर, तुम्ही कोणतेही सॉकेट (अगदी एखाद्याच्या प्रोग्रामद्वारे तयार केलेले) मुक्तपणे व्यवस्थापित करू शकाल! तथापि, बहुधा, दुसऱ्याच्या सॉकेटचे निरीक्षण करण्यासाठी, तुम्हाला WinAPI सॉकेट फंक्शन्स केवळ वापरावे लागतील.

उपसंहार

हा लेख डेल्फीमधील TServerSocket घटकासह कार्य करण्यासाठी मूलभूत तंत्रे आणि सॉकेट्सवर डेटाची देवाणघेवाण करण्यासाठी अनेक सामान्य तंत्रे दर्शवितो. आपल्याकडे प्रश्न असल्यास, ते मला ईमेलद्वारे पाठवा: [ईमेल संरक्षित], आणि आणखी चांगले - या साइटच्या परिषदेत लिहा (डेल्फी. सामान्य प्रश्न) जेणेकरून इतर वापरकर्ते तुमचा प्रश्न पाहू शकतील आणि त्याचे उत्तर देण्याचा प्रयत्न करू शकतील!


परिचय


हा लेख सॉकेट्स ("सॉकेट्स" - वर आधारित बोरलँड डेल्फीमध्ये क्लायंट/सर्व्हर आर्किटेक्चर ॲप्लिकेशन्स तयार करण्यासाठी समर्पित आहे. घरटे). सॉकेट्सच्या विषयावरील मागील लेखाच्या विपरीत, येथे आपण सर्व्हर ऍप्लिकेशन्स तयार करण्याकडे पाहू.

हे त्वरित लक्षात घेतले पाहिजे की स्वतंत्र क्लायंट आणि सर्व्हर अनुप्रयोगांच्या सहअस्तित्वासाठी, अनेक संगणक असणे आवश्यक नाही. फक्त एक असणे पुरेसे आहे ज्यावर आपण एकाच वेळी सर्व्हर आणि क्लायंट दोन्ही चालवू शकता. या प्रकरणात, आपण ज्या संगणकाशी कनेक्ट करू इच्छिता त्या संगणकाचे नाव म्हणून आपल्याला होस्ट नाव वापरण्याची आवश्यकता आहे लोकलहोस्टकिंवा IP पत्ता - 127.0.0.1 .

तर, सिद्धांतासह प्रारंभ करूया. जर तुम्ही खात्रीपूर्वक अभ्यासक असाल (आणि तुमच्या डोळ्यांनी कोणतेही अल्गोरिदम पाहू शकत नाही), तर तुम्ही हा विभाग वगळला पाहिजे.

सॉकेट सर्व्हर ऑपरेशन अल्गोरिदम


सॉकेट सर्व्हर तुम्हाला काय करण्याची परवानगी देतो?.. ते कोणत्या तत्त्वावर कार्य करते?.. सॉकेट प्रोटोकॉलवर आधारित सर्व्हर तुम्हाला एकाच वेळी अनेक क्लायंटना सेवा देण्याची परवानगी देतो. शिवाय, तुम्ही त्यांच्या नंबरची मर्यादा स्वतः निर्दिष्ट करू शकता (किंवा ही मर्यादा पूर्णपणे काढून टाकू शकता, जसे की डीफॉल्टनुसार केली जाते). प्रत्येक कनेक्ट केलेल्या क्लायंटसाठी, सर्व्हर एक स्वतंत्र सॉकेट उघडतो ज्याद्वारे आपण क्लायंटसह डेटाची देवाणघेवाण करू शकता. दुसरा उत्तम उपाय म्हणजे प्रत्येक कनेक्शनसाठी स्वतंत्र प्रक्रिया (थ्रेड) तयार करणे.

खाली डेल्फी ऍप्लिकेशन्समध्ये सॉकेट सर्व्हर कसे कार्य करते याचे उदाहरण आकृती आहे:

चला आकृती अधिक तपशीलवार पाहू:

  • पोर्ट आणि सर्व्हरटाइप गुणधर्मांची व्याख्या - क्लायंट सामान्यपणे सर्व्हरशी कनेक्ट होण्यासाठी सक्षम होण्यासाठी, सर्व्हरद्वारे वापरलेले पोर्ट क्लायंटने वापरलेल्या पोर्टशी (आणि उलट) तंतोतंत जुळणे आवश्यक आहे. सर्व्हरटाइप गुणधर्म कनेक्शन प्रकार निर्धारित करते (अधिक तपशीलांसाठी खाली पहा);
  • सॉकेट उघडत आहे - सॉकेट आणि निर्दिष्ट पोर्ट उघडणे. येथेच आम्ही आपोआप क्लायंट कनेक्ट होण्याची प्रतीक्षा करू लागतो ( ऐका);
  • क्लायंट कनेक्ट करणे आणि त्याच्याशी डेटाची देवाणघेवाण करणे - येथे क्लायंट त्याच्याशी डेटा कनेक्ट आणि एक्सचेंज करतो. आपण या लेखात आणि सॉकेट्स (क्लायंट भाग) बद्दलच्या लेखात या स्टेजबद्दल अधिक जाणून घेऊ शकता;
  • क्लायंट अक्षम करणे - येथे क्लायंट डिस्कनेक्ट होतो आणि सर्व्हरसह त्याचे सॉकेट कनेक्शन बंद आहे;
  • सर्व्हर आणि सॉकेट बंद करत आहे - प्रशासकाच्या आदेशानुसार, सर्व्हर बंद होतो, सर्व खुले सॉकेट चॅनेल बंद करतो आणि क्लायंट कनेक्शनची प्रतीक्षा करणे थांबवतो.

हे नोंद घ्यावे की गुण 3-4 अनेक वेळा पुनरावृत्ती होते, म्हणजे. हे चरण प्रत्येक नवीन क्लायंट कनेक्शनसाठी केले जातात.

नोंद : सध्या डेल्फीमधील सॉकेट्सवर फारच कमी दस्तऐवजीकरण आहे, त्यामुळे जर तुम्हाला या विषयाचा शक्य तितका खोलवर अभ्यास करायचा असेल, तर मी तुम्हाला युनिक्स/लिनक्स सिस्टीमवरील साहित्य आणि इलेक्ट्रॉनिक दस्तऐवजीकरण पाहण्याचा सल्ला देतो - तेथे खूपसॉकेट्ससह काम करण्याच्या सिद्धांताचे चांगले वर्णन केले आहे. याव्यतिरिक्त, या OS साठी सॉकेट ऍप्लिकेशन्सची अनेक उदाहरणे आहेत (जरी मुख्यतः C/C++ आणि Perl मध्ये).

TServerSocket घटकाचे संक्षिप्त वर्णन


येथे आपण परिचित होऊ मुख्यघटकाचे गुणधर्म, पद्धती आणि घटना TSserverSocket.

गुणधर्म

सॉकेट - TServerWinSocket वर्ग, ज्याद्वारे तुम्हाला सॉकेट चॅनेल उघडण्यासाठी प्रवेश आहे. पुढे आम्ही या मालमत्तेचा अधिक तपशीलवार विचार करू, कारण खरं तर, ते मुख्यांपैकी एक आहे. प्रकार: TSserverWinSocket ;
सर्व्हर प्रकार - सर्व्हर प्रकार. दोन मूल्यांपैकी एक घेऊ शकता: stNonBlocking- क्लायंट सॉकेटसह समकालिक कार्य. या प्रकारच्या सर्व्हरसह आपण इव्हेंटद्वारे क्लायंटसह कार्य करू शकता OnClientReadआणि OnClientWrite. stThreadBlocking- असिंक्रोनस प्रकार. प्रत्येक क्लायंट सॉकेट चॅनेलसाठी स्वतंत्र प्रक्रिया (थ्रेड) तयार केली जाते. प्रकार: TSserverType ;
ThreadCacheSize - क्लायंट प्रक्रियांची संख्या (थ्रेड) जी सर्व्हरद्वारे कॅश केली जाईल. येथे तुम्हाला तुमच्या सर्व्हरवरील लोडवर अवलंबून सरासरी मूल्य निवडण्याची आवश्यकता आहे. कॅशिंग प्रत्येक वेळी एक वेगळी प्रक्रिया तयार करू नये आणि बंद सॉकेट नष्ट करू नये, परंतु नंतरच्या वापरासाठी त्यांना सोडण्यासाठी होते. प्रकार: पूर्णांक ;
सक्रिय - दिलेल्या क्षणी सर्व्हर सक्रिय आहे की नाही याचे सूचक. ते खरे तर मूल्य आहे खरेसूचित करते की सर्व्हर चालू आहे आणि क्लायंट प्राप्त करण्यासाठी तयार आहे, आणि खोटे- सर्व्हर बंद आहे. सर्व्हर सुरू करण्यासाठी, तुम्हाला फक्त ही मालमत्ता सेट करण्याची आवश्यकता आहे खरे. प्रकार: बुलियन ;
बंदर - क्लायंटसह कनेक्शन स्थापित करण्यासाठी पोर्ट क्रमांक. सर्व्हर आणि क्लायंट पोर्ट समान असणे आवश्यक आहे. 1025 ते 65535 पर्यंतच्या मूल्यांची शिफारस केली जाते, कारण 1 ते 1024 पर्यंत - सिस्टमद्वारे व्यापले जाऊ शकते. प्रकार: पूर्णांक ;
सेवा - सेवा परिभाषित करणारी स्ट्रिंग ( एफटीपी, http, पॉप, इ.) ज्याचे पोर्ट वापरले जाईल. विविध मानक प्रोटोकॉलशी संबंधित पोर्ट क्रमांकांची ही एक प्रकारची निर्देशिका आहे. प्रकार: स्ट्रिंग ;

उघडा - सर्व्हर सुरू करतो. मूलत: ही आज्ञा मूल्य नियुक्त करण्यासारखीच आहे खरेमालमत्ता सक्रिय;
बंद - सर्व्हर थांबवतो. मूलत: ही आज्ञा मूल्य नियुक्त करण्यासारखीच आहे खोटेमालमत्ता सक्रिय.

OnClientConnect - जेव्हा क्लायंटने सॉकेट कनेक्शन स्थापित केले असेल आणि सर्व्हरकडून प्रतिसादाची वाट पाहत असेल तेव्हा उद्भवते ( OnAccept);
OnClientDisconnect - जेव्हा क्लायंट सॉकेट चॅनेलवरून डिस्कनेक्ट होतो तेव्हा उद्भवते;
OnClientError - जेव्हा वर्तमान ऑपरेशन अयशस्वी होते तेव्हा उद्भवते, म्हणजे त्रुटी आढळली आहे;
OnClientRead - जेव्हा क्लायंटने सर्व्हरला काही डेटा पाठवला तेव्हा उद्भवते. पास केलेल्या पॅरामीटरद्वारे हा डेटा ऍक्सेस केला जाऊ शकतो सॉकेट: TCustomWinSocket;
OnClientWrite - जेव्हा सर्व्हर क्लायंटला सॉकेटवर डेटा पाठवू शकतो तेव्हा उद्भवते;
OnGetSocket - या कार्यक्रमाच्या हँडलरमध्ये तुम्ही पॅरामीटर संपादित करू शकता क्लायंटसॉकेट;
OnGetThread - या इव्हेंटच्या हँडलरमध्ये तुम्ही पॅरामीटर नियुक्त करून प्रत्येक वैयक्तिक क्लायंट चॅनेलसाठी एक अद्वितीय प्रक्रिया (थ्रेड) परिभाषित करू शकता. सॉकेटथ्रेडइच्छित उपकार्य TServerClientThread;
OnThreadStart , OnThreadEnd - जेव्हा उपकार्य (प्रक्रिया, थ्रेड) अनुक्रमे सुरू किंवा थांबवले जाते तेव्हा उद्भवते;
OnAccept - जेव्हा सर्व्हर क्लायंटला स्वीकारतो किंवा त्याला कनेक्शन नाकारतो तेव्हा उद्भवते;
ऐका - जेव्हा सर्व्हर क्लायंट कनेक्ट होण्यासाठी प्रतीक्षा मोडमध्ये जातो तेव्हा उद्भवते.


TSserverSocket.Socket(TSServerWinSocket)


तर सर्व्हर क्लायंटला डेटा कसा पाठवू शकतो? डेटा प्राप्त करण्याबद्दल काय? मुख्यतः जर तुम्ही इव्हेंटद्वारे काम करत असाल OnClientReadआणि OnClientWrite, नंतर तुम्ही क्लायंटसॉकेट पॅरामीटर (TCustomWinSocket) द्वारे क्लायंटशी संवाद साधू शकता. क्लायंट सॉकेट्सबद्दलच्या लेखात आपण या वर्गासह काम करण्याबद्दल वाचू शकता, कारण या वर्गाद्वारे डेटा पाठवणे/पाठवणे समान आहे - पद्धती (पाठवा/प्राप्त करा)(मजकूर, बफर, प्रवाह). TServerSocket.Socket सह काम करताना हेच लागू होते. तथापि, कारण येथे आम्ही सर्व्हरचा विचार करत आहोत, आम्ही काही उपयुक्त गुणधर्म आणि पद्धती हायलाइट केल्या पाहिजेत:

  • सक्रिय कनेक्शन (पूर्णांक) - कनेक्ट केलेल्या क्लायंटची संख्या;
  • ActiveThreads (पूर्णांक) - चालू असलेल्या प्रक्रियेची संख्या;
  • जोडण्या (रचना) - प्रत्येक कनेक्ट केलेल्या क्लायंटसाठी स्वतंत्र TClientWinSocket वर्गांचा समावेश असलेला ॲरे. उदाहरणार्थ, ही आज्ञा:
    ServerSocket1.Socket.Connections.SendText("हॅलो!");
    पहिल्या कनेक्ट केलेल्या क्लायंटला "हॅलो!" संदेश पाठवते. या ॲरेच्या घटकांसह कार्य करण्यासाठी कमांड - देखील (पाठवा/प्राप्त करा)(मजकूर, बफर, प्रवाह);
  • IdleThreads (पूर्णांक) - विनामूल्य प्रक्रियांची संख्या. अशा प्रक्रिया सर्व्हरद्वारे कॅश केल्या जातात (पहा ThreadCacheSize);
  • स्थानिक पत्ता, LocalHost, लोकलपोर्ट- अनुक्रमे - स्थानिक IP पत्ता, होस्ट नाव, पोर्ट;
  • दूरस्थ पत्ता, रिमोटहोस्ट, रिमोटपोर्ट- अनुक्रमे - दूरस्थ IP पत्ता, होस्ट नाव, पोर्ट;
  • पद्धती कुलूपआणि अनलॉक करा- अनुक्रमे, सॉकेट ब्लॉक करणे आणि अनब्लॉक करणे.

सराव आणि उदाहरणे


आता विशिष्ट उदाहरण वापरून वरील गोष्टी पाहू. तुम्ही क्लिक करून तयार स्रोत डाउनलोड करू शकता.

तर, TServerSocket सह काम करण्याचे एक चांगले उदाहरण पाहू (हे उदाहरण या घटकाचा अभ्यास करण्यासाठी सर्वात दृश्य मदत आहे). खालील स्रोत सर्व महत्त्वाच्या सर्व्हर इव्हेंटचे लॉगिंग तसेच मजकूर संदेश प्राप्त करण्याची आणि पाठविण्याची क्षमता दर्शवतात:

उदाहरण १.लॉगिंग आणि सर्व्हरच्या ऑपरेशनचा अभ्यास करणे, सॉकेटद्वारे संदेश पाठवणे/प्राप्त करणे

(...येथे फाईल हेडर आणि TForm1 ची व्याख्या आणि त्याचे उदाहरण Form1 आहे)
(संपूर्ण स्त्रोत पहा)
प्रक्रिया TForm1.Button1Click(प्रेषक: TObject); सुरू (पोर्ट निश्चित करा आणि सर्व्हर सुरू करा) सर्व्हरसॉकेट1.पोर्ट:= 1025; (इन्सर्ट पद्धत निर्दिष्ट स्थानावर ॲरेमध्ये स्ट्रिंग घालते) Memo2.Lines.Insert(0,"सर्व्हर सुरू होत आहे"); सर्व्हरसॉकेट1.ओपन; शेवट प्रक्रिया TForm1.Button2Click(प्रेषक: TObject); सुरू (सर्व्हर थांबवा) ServerSocket1.Active:= False; Memo2.Lines.Insert(0,"सर्व्हर थांबला"); शेवट प्रक्रिया TForm1.ServerSocket1Listen(प्रेषक: TObject; सॉकेट: TCustomWinSocket); सुरू (येथे क्लायंटसाठी सॉकेटवर सर्व्हर "ऐकत" आहे) Memo2.Lines.Insert(0,"पोर्टवर ऐकत आहे"+IntToStr(ServerSocket1.Port)); शेवट प्रक्रिया TForm1.ServerSocket1Accept(प्रेषक: TObject; सॉकेट: TCustomWinSocket); सुरू (येथे सर्व्हर क्लायंट स्वीकारतो) Memo2.Lines.Insert(0,"क्लायंट कनेक्शन स्वीकारले"); शेवट प्रक्रिया TForm1.ServerSocket1ClientConnect(प्रेषक: TObject; सॉकेट: TCustomWinSocket); सुरू (येथे क्लायंट कनेक्ट होतो) Memo2.Lines.Insert(0,"क्लायंट कनेक्ट केलेले"); शेवट प्रक्रिया TForm1.ServerSocket1ClientDisconnect(प्रेषक: TObject; सॉकेट: TCustomWinSocket); सुरू (येथे क्लायंट डिस्कनेक्ट होतो) Memo2.Lines.Insert(0,"क्लायंट डिस्कनेक्ट झाला"); शेवट प्रक्रिया TForm1.ServerSocket1ClientError(प्रेषक: TObject; सॉकेट: TCustomWinSocket; ErrorEvent: TERrorEvent; var ErrorCode: Integer); सुरू (एक त्रुटी आली - त्याचा कोड प्रदर्शित करा) Memo2.Lines.Insert(0,"क्लायंट एरर. कोड = "+IntToStr(ErrorCode)); शेवट प्रक्रिया TForm1.ServerSocket1ClientRead(प्रेषक: TObject; सॉकेट: TCustomWinSocket); सुरू (क्लायंटकडून एक संदेश प्राप्त झाला - तो Memo1 मध्ये प्रदर्शित करा) Memo2.Lines.Insert(0,"क्लायंटकडून मिळालेला संदेश"); Memo1.Lines.Insert(0,"> "+Socket.ReceiveText); शेवट प्रक्रिया TForm1.ServerSocket1ClientWrite(प्रेषक: TObject; सॉकेट: TCustomWinSocket); सुरू (आता तुम्ही सॉकेटवर डेटा पाठवू शकता) Memo2.Lines.Insert(0,"आता सॉकेटवर लिहू शकतो"); शेवट प्रक्रिया TForm1.ServerSocket1GetSocket(प्रेषक: TObject; सॉकेट: पूर्णांक; var ClientSocket: TServerClientWinSocket); Memo2.Lines.Insert(0,"Get socket"); शेवट प्रक्रिया TForm1.ServerSocket1GetThread(प्रेषक: TObject; क्लायंटसॉकेट: TServerClientWinSocket; var SocketThread: TServerClientThread); Memo2.Lines.Insert(0,"Get Thread"); शेवट प्रक्रिया TForm1.ServerSocket1ThreadEnd(प्रेषक: TObject; थ्रेड: TServerClientThread); start Memo2.Lines.Insert(0,"थ्रेड एंड"); शेवट प्रक्रिया TForm1.ServerSocket1ThreadStart(प्रेषक: TObject; थ्रेड: TServerClientThread); start Memo2.Lines.Insert(0,"थ्रेड स्टार्ट"); शेवट प्रक्रिया TForm1.Button3Click(प्रेषक: TObject); var i: पूर्णांक; सुरू (संपादन1 वरून सर्व क्लायंटना संदेश पाठवा) i for i:= 0 ते ServerSocket1.Socket.ActiveConnections-1 सुरू करा ServerSocket1.Socket.Connections[i].SendText(Edit1.Text); शेवट Memo1.Lines.Insert(0,"

TServerSocket सह काम करण्याचे तंत्र (आणि फक्त सॉकेटसह)


प्रत्येक क्लायंटसाठी अद्वितीय डेटा संचयित करणे.


निश्चितपणे, जर तुमचा सर्व्हर अनेक क्लायंटना सेवा देत असेल, तर तुम्हाला प्रत्येक क्लायंटसाठी (नाव, इ.) काही माहिती संग्रहित करावी लागेल आणि ही माहिती या क्लायंटच्या सॉकेटमध्ये बांधावी लागेल. काही प्रकरणांमध्ये, हे सर्व मॅन्युअली करणे (सॉकेट हँडल, क्लायंट ॲरे इत्यादींना बंधनकारक) करणे फार सोयीचे नसते. म्हणून, प्रत्येक सॉकेटसाठी एक विशेष गुणधर्म आहे - डेटा. खरं तर, डेटा फक्त एक सूचक आहे. म्हणून, या मालमत्तेवर क्लायंट डेटा लिहिताना, सावधगिरी बाळगा आणि पॉइंटर्ससह कार्य करण्याच्या नियमांचे पालन करा (मेमरी वाटप, प्रकार व्याख्या इ.)!

सॉकेटद्वारे फाइल्स पाठवत आहे.


येथे आपण सॉकेटद्वारे फाइल्स पाठवण्याकडे लक्ष देऊ (JINX च्या विनंतीनुसार) :-). मग सॉकेटवर फाइल कशी पाठवायची? अगदी साधे! तुम्हाला फक्त ही फाइल फाइल स्ट्रीम (TFileStream) म्हणून उघडायची आहे आणि ती सॉकेट (SendStream) द्वारे पाठवायची आहे! हे एका उदाहरणासह पाहू:

पद्धत नोंद करावी सेंडस्ट्रीमकेवळ सर्व्हरद्वारेच नव्हे तर क्लायंटद्वारे देखील वापरले जाते ( ClientSocket1.Socket.SendStream(srcfile))

ट्रान्समिशन दरम्यान अनेक ब्लॉक्स एकामध्ये का एकत्र केले जाऊ शकतात?


हे JINX च्या विनंतीनुसार देखील आहे :-). त्याबद्दल त्यांचे खूप खूप आभार! म्हणून, सर्वप्रथम, हे लक्षात घेतले पाहिजे की सॉकेटद्वारे पाठविलेला डेटा केवळ एका ब्लॉकमध्ये एकत्र केला जाऊ शकत नाही तर अनेक ब्लॉक्समध्ये विभक्त देखील केला जाऊ शकतो. वस्तुस्थिती अशी आहे की सॉकेट हा एक नियमित प्रवाह आहे, परंतु फाइल स्ट्रीम (TFileStream) च्या विपरीत, तो डेटा अधिक हळू हस्तांतरित करतो (आपल्याला समजते - नेटवर्क, मर्यादित रहदारी इ.). म्हणूनच दोन आज्ञा:
ServerSocket1.Socket.Connections.SendText("हॅलो,");
ServerSocket1.Socket.Connections.SendText("world!");
एका आदेशाशी पूर्णपणे समान:
ServerSocket1.Socket.Connections.SendText("हॅलो, वर्ल्ड!");

आणि म्हणूनच, जर तुम्ही सॉकेटद्वारे 100 KB ची फाईल पाठवली, तर तुम्ही ज्या व्यक्तीला हा ब्लॉक पाठवला आहे त्या व्यक्तीला अनेक ब्लॉक्स मिळतील जे ट्रॅफिक आणि लाईन कंजेशनवर अवलंबून असतात. शिवाय, आकार समान असणे आवश्यक नाही. हे खालीलप्रमाणे आहे की फाइल किंवा इतर कोणताही मोठा डेटा स्वीकारण्यासाठी, तुम्ही डेटाचे ब्लॉक्स स्वीकारले पाहिजे आणि नंतर त्यांना एका संपूर्णमध्ये एकत्र केले पाहिजे (आणि जतन करा, उदाहरणार्थ, फाइलमध्ये). या समस्येचे उत्कृष्ट समाधान म्हणजे समान फाइल प्रवाह - TFileStream (किंवा मेमरीमधील प्रवाह - TMemoryStream). तुम्ही सार्वत्रिक पद्धतीचा वापर करून ऑनरीड (ऑनक्लायंटरीड) इव्हेंटद्वारे सॉकेटमधून डेटाचे तुकडे प्राप्त करू शकता बफ प्राप्त करा. आपण पद्धत वापरून परिणामी ब्लॉकचा आकार निर्धारित करू शकता प्राप्तीची लांबी. तुम्ही सॉकेट स्ट्रीम देखील वापरू शकता (TClientSocket बद्दलचा लेख पहा). आणि येथे एक लहान उदाहरण आहे (अंदाजे):

सॉकेटचे निरीक्षण कसे करावे


ही समस्या गुंतागुंतीची आहे आणि दीर्घ विचार करणे आवश्यक आहे. आत्तासाठी, मी फक्त लक्षात ठेवेन की आपण नेहमी आपल्या प्रोग्रामद्वारे तयार केलेल्या सॉकेटचे निरीक्षण करू शकता :-). सॉकेट्स (विंडोजमधील बहुतेक वस्तूंप्रमाणे) त्यांचे स्वतःचे हँडल असते, हँडल गुणधर्मामध्ये लिहिलेले असते. त्यामुळे, एकदा तुम्ही हा वर्णनकर्ता ओळखल्यानंतर, तुम्ही कोणतेही सॉकेट (अगदी एखाद्याच्या प्रोग्रामद्वारे तयार केलेले) मुक्तपणे व्यवस्थापित करू शकाल! तथापि, बहुधा, दुसऱ्याच्या सॉकेटचे निरीक्षण करण्यासाठी, तुम्हाला WinAPI सॉकेट फंक्शन्स केवळ वापरावे लागतील.


हा लेख डेल्फीमधील TServerSocket घटकासह कार्य करण्यासाठी मूलभूत तंत्रे आणि सॉकेट्सवर डेटाची देवाणघेवाण करण्यासाठी अनेक सामान्य तंत्रे दर्शवितो. आपल्याकडे प्रश्न असल्यास, ते मला ईमेलद्वारे पाठवा: [ईमेल संरक्षित], आणि आणखी चांगले - या साइटच्या परिषदेत लिहा (डेल्फी. सामान्य प्रश्न) जेणेकरून इतर वापरकर्ते तुमचा प्रश्न पाहू शकतील आणि त्याचे उत्तर देण्याचा प्रयत्न करू शकतील!

करिख निकोले ( नायट्रो). मॉस्को प्रदेश, झुकोव्स्की

हा लेख सॉकेट्स (“सॉकेट्स”) वर आधारित बोरलँड डेल्फीमध्ये क्लायंट/सर्व्हर आर्किटेक्चर ऍप्लिकेशन्स तयार करण्यासाठी समर्पित आहे. सॉकेट्सच्या विषयावरील मागील लेखाच्या विपरीत, येथे आपण सर्व्हर ऍप्लिकेशन्स तयार करण्याकडे पाहू.
हे त्वरित लक्षात घेतले पाहिजे की स्वतंत्र क्लायंट आणि सर्व्हर अनुप्रयोगांच्या सहअस्तित्वासाठी, अनेक संगणक असणे आवश्यक नाही. फक्त एक असणे पुरेसे आहे ज्यावर तुम्ही एकाच वेळी सर्व्हर आणि क्लायंट दोन्ही चालवू शकता. या प्रकरणात, तुम्हाला होस्ट नाव लोकलहोस्ट किंवा आयपी ॲड्रेस - 127.0.0.1 वापरणे आवश्यक आहे ज्या संगणकाशी तुम्हाला कनेक्ट करणे आवश्यक आहे.
तर, सिद्धांतासह प्रारंभ करूया. जर तुम्ही खात्रीपूर्वक अभ्यासक असाल (आणि तुमच्या डोळ्यांनी कोणतेही अल्गोरिदम पाहू शकत नाही), तर तुम्ही हा विभाग वगळला पाहिजे.
सॉकेट सर्व्हर ऑपरेशन अल्गोरिदम
सॉकेट सर्व्हर तुम्हाला काय करण्याची परवानगी देतो?.. ते कोणत्या तत्त्वावर कार्य करते?.. सॉकेट प्रोटोकॉलवर आधारित सर्व्हर तुम्हाला एकाच वेळी अनेक क्लायंटना सेवा देण्याची परवानगी देतो. शिवाय, तुम्ही त्यांच्या नंबरची मर्यादा स्वतः निर्दिष्ट करू शकता (किंवा ही मर्यादा पूर्णपणे काढून टाकू शकता, जसे की डीफॉल्टनुसार केली जाते). प्रत्येक कनेक्ट केलेल्या क्लायंटसाठी, सर्व्हर एक स्वतंत्र सॉकेट उघडतो ज्याद्वारे आपण क्लायंटसह डेटाची देवाणघेवाण करू शकता. दुसरा उत्तम उपाय म्हणजे प्रत्येक कनेक्शनसाठी स्वतंत्र प्रक्रिया (थ्रेड) तयार करणे.
खाली डेल्फी ऍप्लिकेशन्समध्ये सॉकेट सर्व्हर कसे कार्य करते याचे उदाहरण आकृती आहे:

चला या योजनेकडे अधिक तपशीलवार पाहू: · पोर्ट आणि सर्व्हरटाइपची व्याख्या - क्लायंट सर्व्हरशी सामान्यपणे कनेक्ट होण्यासाठी, सर्व्हरद्वारे वापरलेले पोर्ट क्लायंटने वापरलेल्या पोर्टशी तंतोतंत जुळत असणे आवश्यक आहे (आणि उलट). सर्व्हरटाइप गुणधर्म कनेक्शन प्रकार निर्धारित करते (अधिक तपशीलांसाठी खाली पहा); सॉकेट उघडणे - सॉकेट उघडणे आणि निर्दिष्ट पोर्ट. येथे क्लायंट कनेक्ट होण्याची वाट पाहण्याची स्वयंचलित सुरुवात (ऐका); · क्लायंट कनेक्ट करणे आणि त्याच्याशी डेटाची देवाणघेवाण करणे - येथे क्लायंट त्याच्याशी डेटा कनेक्ट करतो आणि देवाणघेवाण करतो. आपण या लेखात आणि सॉकेट्स (क्लायंट भाग) बद्दलच्या लेखात या स्टेजबद्दल अधिक जाणून घेऊ शकता; · क्लायंट डिस्कनेक्शन - येथे क्लायंट डिस्कनेक्ट झाला आहे आणि सर्व्हरसह त्याचे सॉकेट कनेक्शन बंद आहे; · सर्व्हर आणि सॉकेट बंद करणे - प्रशासकाच्या आदेशानुसार, सर्व्हर बंद होतो, सर्व खुले सॉकेट चॅनेल बंद करतो आणि क्लायंट कनेक्शनची प्रतीक्षा करणे थांबवतो.
हे नोंद घ्यावे की गुण 3-4 अनेक वेळा पुनरावृत्ती होते, म्हणजे. हे चरण प्रत्येक नवीन क्लायंट कनेक्शनसाठी केले जातात.
टीप: या क्षणी डेल्फीमधील सॉकेट्सवर फारच कमी दस्तऐवजीकरण आहे, म्हणून जर तुम्हाला या विषयाचा शक्य तितका खोलवर अभ्यास करायचा असेल, तर मी तुम्हाला युनिक्स/लिनक्स सिस्टम्सवरील साहित्य आणि इलेक्ट्रॉनिक दस्तऐवजीकरण पाहण्याचा सल्ला देतो - यासह कार्य करण्याचा सिद्धांत सॉकेट्सचे तेथे अतिशय चांगले वर्णन केले आहे. याव्यतिरिक्त, या OS साठी सॉकेट ऍप्लिकेशन्सची अनेक उदाहरणे आहेत (जरी मुख्यतः C/C++ आणि Perl मध्ये).
TServerSocket घटकाचे संक्षिप्त वर्णन
येथे आपण घटकाचे मुख्य गुणधर्म, पद्धती आणि घटनांशी परिचित होऊ
गुणधर्म
सॉकेट हा TServerWinSocket वर्ग आहे ज्याद्वारे तुम्हाला सॉकेट चॅनेल उघडण्यासाठी प्रवेश आहे. पुढे आम्ही या मालमत्तेचा अधिक तपशीलवार विचार करू, कारण खरं तर, ते मुख्यांपैकी एक आहे. प्रकार: TServerWinSocket;
सर्व्हर प्रकार - सर्व्हर प्रकार. दोन मूल्यांपैकी एक घेऊ शकता: stNonBlocking - क्लायंट सॉकेटसह समकालिक कार्य. या प्रकारच्या सर्व्हरसह, तुम्ही OnClientRead आणि OnClientWrite इव्हेंटद्वारे क्लायंटसह कार्य करू शकता. stThreadBlocking हा असिंक्रोनस प्रकार आहे. प्रत्येक क्लायंट सॉकेट चॅनेलसाठी स्वतंत्र प्रक्रिया (थ्रेड) तयार केली जाते. प्रकार: TServerType;
ThreadCacheSize - क्लायंट प्रक्रियांची संख्या (थ्रेड) जी सर्व्हरद्वारे कॅश केली जाईल. येथे तुम्हाला तुमच्या सर्व्हरवरील लोडवर अवलंबून सरासरी मूल्य निवडण्याची आवश्यकता आहे. प्रत्येक वेळी एक वेगळी प्रक्रिया तयार न करण्यासाठी आणि बंद सॉकेट नष्ट न करण्यासाठी, परंतु नंतरच्या वापरासाठी त्यांना सोडण्यासाठी कॅशिंग होते. प्रकार: पूर्णांक;
सक्रिय - सर्व्हर सध्या सक्रिय आहे की नाही याचे सूचक. म्हणजेच खरे मूल्य हे सूचित करते की सर्व्हर चालू आहे आणि क्लायंट प्राप्त करण्यास तयार आहे आणि असत्य दर्शविते की सर्व्हर बंद आहे. सर्व्हर सुरू करण्यासाठी, तुम्हाला फक्त ही प्रॉपर्टी ट्रूवर सेट करावी लागेल. प्रकार: बुलियन;
पोर्ट - क्लायंटशी कनेक्शन स्थापित करण्यासाठी पोर्ट नंबर. सर्व्हर आणि क्लायंट पोर्ट समान असणे आवश्यक आहे. 1025 ते 65535 पर्यंतच्या मूल्यांची शिफारस केली जाते, कारण 1 ते 1024 पर्यंत - सिस्टमद्वारे व्यापले जाऊ शकते. प्रकार: पूर्णांक;
सेवा - सेवा परिभाषित करणारी स्ट्रिंग (ftp, http, pop, इ.) ज्याचा पोर्ट वापरला जाईल. विविध मानक प्रोटोकॉलशी संबंधित पोर्ट क्रमांकांची ही एक प्रकारची निर्देशिका आहे. प्रकार: स्ट्रिंग;
पद्धती
उघडा - सर्व्हर सुरू करतो. मूलत:, ही आज्ञा Active प्रॉपर्टीला True वर सेट करण्यासारखीच आहे;
बंद करा - सर्व्हर थांबवते. मूलत:, हा आदेश सक्रिय गुणधर्म असत्य वर सेट करण्यासारखा आहे.
कार्यक्रम
OnClientConnect - जेव्हा क्लायंटने सॉकेट कनेक्शन स्थापित केले असेल आणि सर्व्हरकडून प्रतिसादाची वाट पाहत असेल (OnAccept);
OnClientDisconnect - जेव्हा क्लायंट सॉकेट चॅनेलवरून डिस्कनेक्ट होतो तेव्हा उद्भवते;
OnClientError - जेव्हा वर्तमान ऑपरेशन अयशस्वी होते तेव्हा उद्भवते, उदा. त्रुटी आढळली आहे;
OnClientRead - क्लायंटने सर्व्हरला काही डेटा पास केल्यावर होतो. हा डेटा पुरवलेल्या सॉकेट पॅरामीटरद्वारे प्रवेश केला जाऊ शकतो: TCustomWinSocket;
OnClientWrite - जेव्हा सर्व्हर क्लायंटला सॉकेटवर डेटा पाठवू शकतो तेव्हा उद्भवते;
OnGetSocket - या कार्यक्रमाच्या हँडलरमध्ये तुम्ही ClientSocket पॅरामीटर संपादित करू शकता;
OnGetThread - या इव्हेंटच्या हँडलरमध्ये तुम्ही इच्छित TServerClientThread सबटास्कला SocketThread पॅरामीटर नियुक्त करून प्रत्येक क्लायंट चॅनेलसाठी एक अनन्य प्रक्रिया (थ्रेड) परिभाषित करू शकता;
OnThreadStart, OnThreadEnd - जेव्हा उपकार्य (प्रक्रिया, थ्रेड) अनुक्रमे सुरू किंवा थांबवले जाते तेव्हा उद्भवते;
OnAccept - जेव्हा सर्व्हर क्लायंटला स्वीकारतो किंवा त्याला कनेक्शन नाकारतो तेव्हा उद्भवते;
OnListen - जेव्हा सर्व्हर क्लायंट कनेक्ट होण्यासाठी प्रतीक्षा मोडमध्ये जातो तेव्हा उद्भवते.
TSserverSocket.Socket(TSServerWinSocket)
तर सर्व्हर क्लायंटला डेटा कसा पाठवू शकतो? डेटा स्वीकारण्याबद्दल काय? मुळात, जर तुम्ही OnClientRead आणि OnClientWrite इव्हेंटद्वारे काम करत असाल, तर तुम्ही क्लायंटसॉकेट पॅरामीटर (TCustomWinSocket) द्वारे क्लायंटशी संवाद साधू शकता. क्लायंट सॉकेट्सबद्दलच्या लेखात आपण या वर्गासह काम करण्याबद्दल वाचू शकता, कारण या वर्गाद्वारे डेटा पाठवणे/पाठवणे समान आहे - पद्धती (पाठवा/प्राप्त करा)(मजकूर, बफर, प्रवाह). TServerSocket.Socket सह काम करताना हेच लागू होते. तथापि, कारण येथे आपण सर्व्हरचा विचार करत आहोत, आपण काही उपयुक्त गुणधर्म आणि पद्धती हायलाइट केल्या पाहिजेत: · ActiveConnections (Integer) - कनेक्ट केलेल्या क्लायंटची संख्या; · ActiveThreads (पूर्णांक) - चालू असलेल्या प्रक्रियांची संख्या; · कनेक्शन (ॲरे) - प्रत्येक कनेक्ट केलेल्या क्लायंटसाठी स्वतंत्र TClientWinSocket वर्गांचा समावेश असलेला ॲरे. उदा. या ॲरेच्या घटकांसह कार्य करण्यासाठी कमांड - देखील (पाठवा/प्राप्त करा)(मजकूर, बफर, प्रवाह); IdleThreads (पूर्णांक) - मुक्त प्रक्रियांची संख्या. अशा प्रक्रिया सर्व्हरद्वारे कॅश केल्या जातात (थ्रेडकॅशसाइज पहा); · LocalAddress, LocalHost, LocalPort - अनुक्रमे - स्थानिक IP पत्ता, होस्ट नाव, पोर्ट; रिमोट ॲड्रेस, रिमोटहोस्ट, रिमोटपोर्ट - अनुक्रमे - रिमोट आयपी ॲड्रेस, होस्ट नाव, पोर्ट; · पद्धती लॉक आणि अनलॉक - अनुक्रमे, सॉकेट ब्लॉक करणे आणि अनब्लॉक करणे.
सराव आणि उदाहरणे
आता विशिष्ट उदाहरण वापरून वरील गोष्टी पाहू. तुम्ही येथे क्लिक करून तयार स्रोत डाउनलोड करू शकता.
तर, TServerSocket सह काम करण्याचे एक चांगले उदाहरण पाहू (हे उदाहरण या घटकाचा अभ्यास करण्यासाठी सर्वात दृश्य मदत आहे). खालील स्रोत सर्व महत्त्वाच्या सर्व्हर इव्हेंटचे लॉगिंग तसेच मजकूर संदेश प्राप्त करण्याची आणि पाठविण्याची क्षमता दर्शवतात:
उदाहरण 1. लॉगिंग आणि सर्व्हरच्या ऑपरेशनचा अभ्यास करणे, सॉकेटद्वारे संदेश पाठवणे/प्राप्त करणे.

(...येथे फाईल हेडर आणि TForm1 ची व्याख्या आणि त्याचे उदाहरण Form1 आहे)

(संपूर्ण स्त्रोत येथे पहा)

प्रक्रिया TForm1.Button1Click (प्रेषक: TObject );

सुरू

(पोर्ट निश्चित करा आणि सर्व्हर सुरू करा)

सर्व्हरसॉकेट1.पोर्ट := 1025 ;

(इन्सर्ट पद्धत निर्दिष्ट स्थानावर ॲरेमध्ये स्ट्रिंग घालते)

Memo2.Lines .Insert (0 ,"सर्व्हर सुरू होत आहे" );

सर्व्हरसॉकेट1.ओपन ;

शेवट;

प्रक्रिया TForm1.Button2Click (प्रेषक: TObject ) ;

सुरू

(सर्व्हर थांबवा)

ServerSocket1.Active := False ;

Memo2.Lines .Insert (0 , "सर्व्हर थांबला" );

शेवट;

प्रक्रिया TForm1.ServerSocket1Listen (प्रेषक: TObject ;

सॉकेट: TCustomWinSocket);

सुरू

(येथे क्लायंटसाठी सॉकेटवर सर्व्हर "ऐकत" आहे)

Memo2.Lines .इन्सर्ट (0 , "पोर्टवर ऐकत आहे" +IntToStr (ServerSocket1.Port ) );

शेवट;

प्रक्रिया TForm1.ServerSocket1Accept (प्रेषक: TObject ;

सॉकेट: TCustomWinSocket);

सुरू

(येथे सर्व्हर क्लायंट स्वीकारतो)

Memo2.Lines .इन्सर्ट करा (0 , "क्लायंट कनेक्शन स्वीकारले" );

शेवट;

प्रक्रिया TForm1.ServerSocket1ClientConnect (प्रेषक: TObject ;

सॉकेट: TCustomWinSocket);

सुरू

(येथे क्लायंट कनेक्ट होतो)

Memo2.Lines .Insert (0 , "क्लायंट कनेक्ट केलेले" );

शेवट;

प्रक्रिया TForm1.ServerSocket1ClientDisconnect (प्रेषक: TObject ;

सॉकेट: TCustomWinSocket);

सुरू

(येथे क्लायंट डिस्कनेक्ट होतो)

Memo2.Lines.Insert(0,"क्लायंट डिस्कनेक्ट झाला");

शेवट;

प्रक्रिया TForm1.ServerSocket1ClientError (प्रेषक: TObject ;

सॉकेट: TCustomWinSocket; ErrorEvent: TERrorEvent;

var त्रुटी कोड: पूर्णांक);

सुरू

(एक त्रुटी आली - त्याचा कोड प्रदर्शित करा)

Memo2.Lines.Insert (0,"क्लायंट एरर. कोड = " +IntToStr (ErrorCode) );

शेवट;

प्रक्रिया TForm1.ServerSocket1ClientRead (प्रेषक: TObject ;

सॉकेट: TCustomWinSocket);

सुरू

(क्लायंटकडून एक संदेश प्राप्त झाला - तो Memo1 मध्ये प्रदर्शित करा)

Memo2.Lines.Insert(0, "क्लायंटकडून मेसेज आला") ;

Memo1.Lines.Insert(0,">" +Socket.ReceiveText);

शेवट;

प्रक्रिया TForm1.ServerSocket1ClientWrite (प्रेषक: TObject ;

सॉकेट: TCustomWinSocket);

सुरू

(आता तुम्ही सॉकेटवर डेटा पाठवू शकता)

Memo2.Lines .Insert (0 , "आता सॉकेटवर लिहू शकतो" );

शेवट;

प्रक्रिया TForm1.ServerSocket1GetSocket (प्रेषक: TObject ; सॉकेट: पूर्णांक ;

var ClientSocket: TServerClientWinSocket);

सुरू

Memo2.Lines.Insert(0,"Get socket");

शेवट;

प्रक्रिया TForm1.ServerSocket1GetThread (प्रेषक: TObject ;

क्लायंटसॉकेट: TServerClientWinSocket;

var SocketThread: TServerClientThread);

सुरू

Memo2.Lines.Insert(0,"Get Thread");

शेवट;

प्रक्रिया TForm1.ServerSocket1ThreadEnd (प्रेषक: TObject ;

सुरू

Memo2.Lines .इन्सर्ट (0 , "थ्रेड एंड" );

शेवट;

प्रक्रिया TForm1.ServerSocket1ThreadStart (प्रेषक: TObject ;

थ्रेड: TServerClientThread);

सुरू

Memo2.Lines .इन्सर्ट (0 , "थ्रेड स्टार्ट" );

शेवट;

प्रक्रिया TForm1.Button3Click (प्रेषक: TObject );

var i: पूर्णांक ;

सुरू

(संपादन1 वरून सर्व क्लायंटना संदेश पाठवा)

i साठी:= 0 ते ServerSocket1.Socket .ActiveConnections -1 सुरू होतात

ServerSocket1.Socket.Connections[i].SendText(Edit1.Text);

शेवट;

Memo1.Lines.Insert(0,"< " +Edit1.Text ) ;

शेवट;

पुढे, आम्ही उदाहरणे नव्हे तर TServerSocket सह कार्य करण्याच्या पद्धतींचा विचार करू.
TServerSocket सह काम करण्याचे तंत्र (आणि फक्त सॉकेटसह)
प्रत्येक क्लायंटसाठी अद्वितीय डेटा संचयित करणे.
निश्चितच, जर तुमचा सर्व्हर अनेक क्लायंटना सेवा देत असेल, तर तुम्हाला प्रत्येक क्लायंटसाठी (नाव, इ.) काही माहिती संग्रहित करावी लागेल आणि ही माहिती या क्लायंटच्या सॉकेटमध्ये बांधावी लागेल. काही प्रकरणांमध्ये, हे सर्व मॅन्युअली करणे (सॉकेट हँडल, क्लायंट ॲरे इत्यादींना बंधनकारक) करणे फार सोयीचे नसते. म्हणून, प्रत्येक सॉकेटसाठी एक विशेष गुणधर्म आहे - डेटा. खरं तर, डेटा फक्त एक सूचक आहे. म्हणून, या मालमत्तेवर क्लायंट डेटा लिहिताना, सावधगिरी बाळगा आणि पॉइंटर्ससह कार्य करण्याच्या नियमांचे पालन करा (मेमरी वाटप, प्रकार व्याख्या इ.)!
सॉकेटद्वारे फाइल्स पाठवत आहे.
येथे आपण सॉकेटद्वारे फाइल्स पाठवण्याकडे लक्ष देऊ (JINX च्या विनंतीनुसार) :-). मग सॉकेटवर फाइल कशी पाठवायची? अगदी साधे! तुम्हाला फक्त ही फाइल फाइल स्ट्रीम (TFileStream) म्हणून उघडायची आहे आणि ती सॉकेट (SendStream) द्वारे पाठवायची आहे! हे एका उदाहरणासह पाहू:

(सॉकेटद्वारे फाइल पाठवत आहे)

प्रक्रिया SendFileBySocket(फाइलनाव: स्ट्रिंग);

var srcfile: TFileStream;

सुरू

(फाइल फाइलनाव उघडा)

Srcfile:= TFileStream.Create (फाइलनाव,fmOpenRead);

(आम्ही ते पहिल्या कनेक्ट केलेल्या क्लायंटला पाठवतो)

ServerSocket1.Socket.Connections[0].SendStream(srcfile);

(फाइल बंद करा)

Srcfile.Free ;

शेवट;

हे नोंद घ्यावे की सेंडस्ट्रीम पद्धत केवळ सर्व्हरद्वारेच नाही तर क्लायंटद्वारे देखील वापरली जाते (ClientSocket1.Socket.SendStream(srcfile))
ट्रान्समिशन दरम्यान अनेक ब्लॉक्स एकामध्ये का एकत्र केले जाऊ शकतात?
हे JINX च्या विनंतीनुसार देखील आहे :-). त्याबद्दल त्यांचे खूप खूप आभार! म्हणून, प्रथम, हे लक्षात घेतले पाहिजे की सॉकेटद्वारे पाठविलेला डेटा केवळ एका ब्लॉकमध्ये एकत्र केला जाऊ शकत नाही तर अनेक ब्लॉक्समध्ये विभक्त देखील केला जाऊ शकतो. वस्तुस्थिती अशी आहे की सॉकेट हा एक नियमित प्रवाह आहे, परंतु फाइल स्ट्रीम (TFileStream) च्या विपरीत, तो डेटा अधिक हळू हस्तांतरित करतो (आपल्याला समजते - नेटवर्क, मर्यादित रहदारी इ.). म्हणूनच दोन आज्ञा:
ServerSocket1.Socket.Connections.SendText("हॅलो,");
ServerSocket1.Socket.Connections.SendText("world!");
एका आदेशाशी पूर्णपणे समान:
ServerSocket1.Socket.Connections.SendText("हॅलो, वर्ल्ड!");
आणि म्हणूनच, जर तुम्ही सॉकेटद्वारे 100 KB ची फाईल पाठवली, तर तुम्ही ज्या व्यक्तीला हा ब्लॉक पाठवला आहे त्या व्यक्तीला अनेक ब्लॉक्स मिळतील जे ट्रॅफिक आणि लाईन कंजेशनवर अवलंबून असतात. शिवाय, आकार समान असणे आवश्यक नाही. हे खालीलप्रमाणे आहे की फाइल किंवा इतर कोणताही मोठा डेटा स्वीकारण्यासाठी, तुम्ही डेटाचे ब्लॉक्स स्वीकारले पाहिजे आणि नंतर त्यांना एका संपूर्णमध्ये एकत्र केले पाहिजे (आणि जतन करा, उदाहरणार्थ, फाइलमध्ये). या समस्येचे उत्कृष्ट समाधान म्हणजे समान फाइल प्रवाह - TFileStream (किंवा मेमरीमधील प्रवाह - TMemoryStream). तुम्ही सार्वत्रिक ReceiveBuf पद्धत वापरून OnRead (OnClientRead) इव्हेंटद्वारे सॉकेटमधून डेटाचे तुकडे प्राप्त करू शकता. प्राप्त ब्लॉकचा आकार ReceiveLength पद्धत वापरून निर्धारित केला जाऊ शकतो. तुम्ही सॉकेट स्ट्रीम देखील वापरू शकता (TClientSocket बद्दलचा लेख पहा). आणि येथे एक लहान उदाहरण आहे (अंदाजे):

(सॉकेटद्वारे फाइल प्राप्त करा)

प्रक्रिया TForm1.ClientSocket1Read (प्रेषक: TObject ;

सॉकेट: TCustomWinSocket);

var l: पूर्णांक ;

बफ: पीसीचार;

Src: TFileStream;

सुरू

(परिणामी ब्लॉकचा आकार l मध्ये लिहा)

L:= Socket.ReceiveLength ;

(बफरसाठी मेमरी ऑर्डर करा)

GetMem (buf,l+1 );

(परिणामी ब्लॉक बफरमध्ये लिहा)

Socket.ReceiveBuf(buf,l);

(लेखनासाठी तात्पुरती फाइल उघडा)

Src:= TFileStream.Create("myfile.tmp" ,fmOpenReadWrite);

(फाइलच्या शेवटी स्थान ठेवा)

Src.Seek (0 ,soFromEnd);

(फाइलवर बफर लिहा)

Src.WriteBuffer(buf,l);

(फाइल बंद करा)

Src.Free ;

(मेमरी मोकळी करणे)

फ्रीमेम(बुफ);

शेवट;

सॉकेटचे निरीक्षण कसे करावे
हा मुद्दा गुंतागुंतीचा आहे आणि दीर्घ विचार करणे आवश्यक आहे. आत्तासाठी, मी फक्त लक्षात ठेवेन की आपण नेहमी आपल्या प्रोग्रामद्वारे तयार केलेल्या सॉकेटचे निरीक्षण करू शकता :-). सॉकेट्स (विंडोजमधील बहुतेक वस्तूंप्रमाणे) त्यांचे स्वतःचे हँडल असते, हँडल गुणधर्मामध्ये लिहिलेले असते. तर, एकदा तुम्ही हा वर्णनकर्ता ओळखल्यानंतर, तुम्ही कोणतेही सॉकेट (अगदी एखाद्याच्या प्रोग्रामद्वारे तयार केलेले) मुक्तपणे व्यवस्थापित करू शकाल! तथापि, बहुधा, एखाद्याच्या सॉकेटचे निरीक्षण करण्यासाठी, तुम्हाला WinAPI सॉकेट फंक्शन्स केवळ वापरावे लागतील.
उपसंहार
हा लेख डेल्फीमधील TServerSocket घटकासह कार्य करण्यासाठी मूलभूत तंत्रे आणि सॉकेट्सवर डेटाची देवाणघेवाण करण्यासाठी अनेक सामान्य तंत्रे दर्शवितो. आपल्याकडे प्रश्न असल्यास, ते मला ईमेलद्वारे पाठवा: [ईमेल संरक्षित], आणि आणखी चांगले - या साइटच्या परिषदेत लिहा (डेल्फी. सामान्य प्रश्न) जेणेकरून इतर वापरकर्ते तुमचा प्रश्न पाहू शकतील आणि त्याचे उत्तर देण्याचा प्रयत्न करू शकतील!
कारीख निकोले (नायट्रो). मॉस्को प्रदेश, झुकोव्स्की

शुभ दिवस, प्रिये!
माझा प्रश्न थोडा वरवरचा आहे, पण महत्वाचा आहे (किमान माझ्यासाठी :)), अधिक "सल्ला" -).

HTTP(S) प्रॉक्सी सर्व्हरचे एनालॉग लिहिण्याचे कार्य आहे, परंतु थोड्या विशिष्टतेसह: काही कनेक्ट केलेल्या क्लायंटच्या विनंत्या वेगळ्या पद्धतीने प्रक्रिया केल्या जातील आणि अशा क्लायंटसह देवाणघेवाण लहान पॅकेटमध्ये होईल. बाकीचे क्लायंट ("विशेषतः गिफ्ट केलेले नाही") नियमित प्रॉक्सीप्रमाणेच चांगले असावेत :). अशा सर्व्हरसाठी मुख्य आवश्यकता म्हणजे लहरी क्लायंट (हे असे आहेत जे लहान पॅकेट फवारणी करतील) आणि इतर सर्व क्लायंटला प्रतिरोधक असणे आणि एकाच वेळी जास्तीत जास्त (ओएस + हार्डवेअर इ. पर्यंत) संख्या राखणे. कनेक्शनला परवानगी आहे (उदाहरणार्थ, 100: )). त्याच वेळी, सर्व्हर अवजड आणि खूप जटिल होऊ नये.

आर्सेनलमधून फक्त मानक डेल्फी साधने आहेत (आम्ही इंडी आणि इतर लायब्ररी टाकून देतो).

वर वर्णन केलेल्या कार्यासाठी आधार म्हणून काय वापरायचे आणि कोणते अनुप्रयोग मॉडेल (तुमच्या मते) सर्वात योग्य आहे हा खरा प्रश्न आहे.

मनात येणारी पहिली गोष्ट म्हणजे TTCP, TSocket किंवा WinSock चे बेअर API.

मी TSocket सह बराच काळ काम केले (शेवटची वेळ 6-7 वर्षांपूर्वी होती) - त्यावेळी मला ते खरोखर आवडले नाही. काही पॅकेट्सना परवानगी दिली होती (जरी TCP "गॅरंटी" मानली जाते). जेव्हा मी येथे मंचावर विचारले की प्रकरण काय आहे, तेव्हा त्यांनी मला इशारा केला, जर माझी स्मरणशक्ती मला योग्यरित्या सेवा देत असेल तर नागले पद्धतीचा. पण समस्या कधीच सुटली नाही (त्यावेळी).

काल मी TCPServer ला चाचणी ड्राइव्ह देण्याचा प्रयत्न केला. त्यावर आधारित, मी GET विनंत्यांवर प्रक्रिया करण्यासाठी एक साधी प्रॉक्सी लिहिली, जी सर्वसाधारणपणे कार्य करते, परंतु अधिक हळू. OnAccept इव्हेंटवर प्रतिक्रिया दिली, ब्लॉकिंग मोड - bmThreadBlocking, ReceiveBuf आणि SendBuf वापरून सॉकेटमधून/वर वाचले आणि लिहिले.

सर्वसाधारणपणे, प्रियजनांनो, सर्व्हरचे कार्य व्यवस्थापित करण्याचा सर्वोत्तम मार्ग कोणता आहे (सर्व्हरवर कनेक्शन प्राप्त करणे आणि दुसऱ्या सर्व्हरकडून डेटा प्राप्त करण्यासाठी प्रवाहात तात्पुरती कनेक्शन तयार करणे आणि क्लायंटला परत पाठवणे) आणि काय वापरणे:
* बेअर विनसॉक API मध्ये लिहा, स्वतः थ्रेड तयार करा, ब्लॉकिंग मोडमध्ये कार्य करा
* बेअर विनसॉक API वर लिहा, नॉन-ब्लॉकिंग मोडमध्ये कार्य करा, नंतर, मला समजले आहे, थ्रेड तयार करण्याची आवश्यकता नाही
* वर वर्णन केल्याप्रमाणे, केवळ एक घटक/वर्ग संदर्भ बिंदू म्हणून वापरणे (उदाहरणार्थ, (T)TCP, (T)सॉकेट)
* डेल्फी युक्ती वापरा - थ्रेडब्लॉकिंग मोड
* अजून काही

शेवटपर्यंत वाचून प्रतिसाद देणाऱ्या प्रत्येकाचे आगाऊ आभार!


DVM (2010-05-11 18:43)

इंडीला काय आवडले नाही?


कर्नल ( 2010-05-11 18:50 )


> DVM © (11.05.10 18:43)
> इंडीला ते का आवडले नाही?

परवाना, दुरूस्तीची तीव्रता (या अर्थाने की कमी स्तरावर काहीतरी जोडण्यासाठी/बदलण्यासाठी तुम्हाला बरेच काही निश्चित करावे लागेल), नंतर, मला आठवते, थ्रेड मारण्यात समस्या होत्या (http://site/ दृश्य/६-१२३६५७७१४१/) .


DVM (2010-05-11 19:34)


> कर्नल © (11.05.10 18:50)

तुम्हाला सर्व्हरवर जास्तीत जास्त नियंत्रण हवे असल्यास, WinSock वर सर्वकाही स्वतः करा. मी कदाचित ब्लॉकिंग मोड आणि थ्रेड पूल सारखे काहीतरी निवडेल.


स्लिम ( 2010-05-11 20:37 )

कर्नल © (11.05.10 18:07)
त्यावर आधारित, मी GET विनंत्यांवर प्रक्रिया करण्यासाठी एक साधी प्रॉक्सी लिहिली

आपले कार्य खाली येते
1. क्लायंटकडून हेडर स्वीकारा, तेथून ऑर्डर केलेल्या सर्व्हरचे होस्ट:पोर्ट काढा
2. host:port द्वारे कनेक्ट करा आणि प्राप्त झालेले संदेश पॉइंट 1 वर कमीतकमी बदलांसह पाठवणे पूर्णपणे शक्य आहे. क्लायंटकडून डेटा
3. क्लायंट/सर्व्हर रहदारीचे पारदर्शक टनेलिंग प्रदान करा
4. (पर्यायी) विशेषत: उत्साही कनेक्शनची गती कमी करा, उदाहरणार्थ मूर्ख झोपेसह (8kb + स्लीप (1000) च्या सॉकेट बफरसह आम्हाला जास्तीत जास्त 8kb/सेकंद मिळतात)


सेर्गेई एम. ( 2010-05-11 22:02 )


> पॅकेट्सद्वारे परवानगी देण्यात आली होती (जरी TCP "गॅरंटी" मानले जाते).
> जेव्हा मी येथे मंचावर विचारले की काय प्रकरण आहे, तेव्हा त्यांनी मला इशारा केला,
> जर माझी स्मृती मला योग्यरित्या सेवा देत असेल तर नागले पद्धतीनुसार

तुमचा प्रश्न कशाबद्दल होता हे तुम्हाला आठवत नाही असे दिसते.
नागलेचा वापर केला जातो की नाही - याचा कोणत्याही प्रकारे "पॅकेट पासिंग" वर परिणाम होऊ शकत नाही मुळात.


कर्नल ( 2010-05-13 14:08 )

तुमच्या उत्तरांसाठी सर्वांचे आभार!


> DVM © (11.05.10 19:34)

नियंत्रणासाठी फक्त क्लायंटशी दिलेल्या पॅकेट आकारांसह संप्रेषण (हानीकारक क्लायंटसाठी लहान पॅकेट आणि इतरांसाठी मोठी पॅकेट) त्यांच्यावर "प्रक्रिया" करण्याची आणि पाठवलेला/प्राप्त डेटा मोजण्याची क्षमता आहे. हे सर्व, जर मी चुकलो नाही तर, सामान्य सॉकेट-आकाराच्या घटकांद्वारे यशस्वीरित्या केले जाते. किंवा शुद्ध WinSock वापरणे अद्याप चांगले आहे? :) येथे, कदाचित, त्यापैकी कोणते (सॉक घटक वि विनसॉक एपीआय) चांगले कार्यप्रदर्शन करेल यात तुम्हाला अधिक रस असेल. की या बाबतीत काही फरक नाही?

> स्लिम © (11.05.10 20:37)

बरं, मला माहित आहे की प्रॉक्सी कशी कार्य करते. तुम्ही वर्णन केल्याप्रमाणे मी केले.

> सर्जी एम. © (11.05.10 22:02)

मी खरंच विसरलो. मला या घटकांवर ते जुने स्त्रोत सापडले, बहुधा समस्या अशी होती की अल्प कालावधीत सर्व्हर स्वतः क्लायंटला चिकटून राहिला आणि सर्व क्लायंटना कमांड पाठवला. प्रत्येक गोष्टीला यशस्वीरित्या पाठवण्यासाठी, सुमारे 1 सेकंदाचा विलंब सेट करणे आवश्यक होते. (किमान ते माझ्यासाठी कार्य करते, फक्त नाही< ~1 сек.) после отсылки команды каждому ПК. Вот тут мне про Nagle скорее всего и намекнули.


DVM (2010-05-13 16:25)


> कर्नल © (१३.०५.१० १४:०८)


> येथे, बहुधा, तुम्हाला त्यापैकी कोणते (रस घटक
> वि विनसॉक API) कार्यप्रदर्शन अधिक चांगले होईल. किंवा
>या बाबतीत काही फरक नाही का?

घटक WinSock च्या आधारावर तयार केले आहेत. त्यांच्यात आणि शुद्ध विन्सॉकमध्ये व्यावहारिकदृष्ट्या कोणताही फरक नाही. किमान हे फरक शोधण्याची जागा नाही.


DVM (2010-05-13 16:26)


> कर्नल © (१३.०५.१० १४:०८)

दुसरी गोष्ट अशी आहे की आपण WinSock भोवती आपले स्वतःचे साधे रॅपर लिहू शकता, विशिष्ट कार्यासाठी अधिक योग्य - ही त्यांची सोय आहे.


कर्नल ( 2010-05-14 21:46 )

उत्तरांसाठी धन्यवाद, DVM!
मी सर्व्हरसॉकेटवर आधारित माझा स्वतःचा वर्ग तयार केला आहे, सर्वकाही द्रुत आणि आश्चर्यकारकपणे कार्य करते [पाह-पाह-पाह], तेथे पूर्णपणे पुरेसे नियंत्रण आहे.
PS: मी हा मेसेज ट्रायल प्रॉक्सीद्वारे पाठवला आहे :)


कर्नल ( 2010-05-18 17:36 )

सर्वांना नमस्कार! वेगळा विषय तयार करू नये म्हणून, मी येथे विचारेन (संभाषण या विषयाशी संबंधित असल्याने).

TServerSocket (मोड - stThreadBlocking) वर आधारित मला आवश्यक असलेली कार्यक्षमता मी प्रत्येक स्थापित कनेक्शनसाठी स्वतंत्र थ्रेड तयार करून व्यवस्थापित केली. मी त्या ठिकाणी पोहोचलो आहे जिथे मला [क्लायंट] दरम्यान बोगदा करणे आवश्यक आहे<->["प्रॉक्सी सर्व्हर"]<->SSL ऑपरेशनसाठी [सर्व्हरची विनंती केली. यंत्रणा अशी आहे: क्लायंट मला CONNECT (HTTP/1.0) विनंती पाठवतो, त्यानंतर मी (प्रॉक्सी) "200 ओके - कनेक्शन स्थापित" हेडर पाठवल्यानंतर, दोनपैकी एक कनेक्शन खंडित होईपर्यंत लूपमध्ये (क्लायंट किंवा टारगेटहोस्ट) ), मी क्लायंटकडून डेटा बफर करतो आणि क्लायंटकडून शून्य बाइट्स येईपर्यंत तो त्वरित विनंती केलेल्या सर्व्हरवर हस्तांतरित करतो. मग मी तेच करतो, परंतु त्याउलट, मी विनंती केलेल्या सर्व्हरवरून बफरमध्ये डेटा पकडतो आणि तो त्वरित क्लायंटकडे हस्तांतरित करतो. आणि त्यापैकी एक कनेक्शन खंडित होईपर्यंत हे सर्व पुनरावृत्ती होते.

...
const BufSize = 128;
...
क्लायंटस्ट्रीम: TWinSocketStream;
लक्ष्य कनेक्शन: TTcpClient;
बफ: बाइटचे ॲरे;
...
ClientStream:= TWinSocketStream.Create(ClientSocket, 60000);
...
(ClientIdestinationConnected) सुरू असताना
ClientWait:= (ClientStream.WaitForData(100));
जर क्लायंटवेट असेल तर सुरू करा
(ClientSocket.Connected) आणि (TargetConnection.Connected) आणि (RecLen > 0) सुरू असताना
TargetConnection.SendBuf(Buf, RecLen);
जर (ClientStream.WaitForData(10) नाही) तर ब्रेक करा;
RecLen:= ClientStream.Read(Buf, BufSize);
शेवट
शेवट

ServerWait:= TargetConnection.WaitForData(100);
जर सर्व्हर प्रतीक्षा करत असेल तर सुरू करा
(ClientSocket.Connected) आणि TargetConnection.Connected) आणि (RecLen > 0) सुरू असताना
ClientStream.Write(Buf, RecLen);
जर (ClientSocket.Connected नाही) किंवा (TargetConnection.Connected नाही) तर ब्रेक करा;
जर (TargetConnection.WaitForData(10) नाही) तर ब्रेक करा;
RecLen:= TargetConnection.ReceiveBuf(Buf, BufSize);
शेवट
शेवट
शेवट

सर्व काही ठीक होईल (आणि सामान्य लूपचे अनेक पास देखील योग्यरित्या प्रक्रिया केले जातात), परंतु जवळजवळ लगेचच सामान्य लूप गोठतो (अधिक तंतोतंत, ते गोठत नाही, परंतु अविरतपणे फिरते) आणि एक विचित्र चित्र दिसून येते: ClientStream.WaitForData(100) ( RecLen:= ClientStream.वाचा ...) या सॉकेटमधून सर्व वेळ शून्य होते. त्याच वेळी, दोन्ही कनेक्शन डिस्कनेक्ट होत नाहीत (जरी डेटा "अंडरट्रांसमिटेड" असेल तर ते डिस्कनेक्ट का होतील).

प्रश्न: मी काय चूक करत आहे? :)


कर्नल ( 2010-05-18 17:40 )

म्हणजेच, सोप्या भाषेत सांगायचे तर, काही काळानंतर सायकल “कातली”, परंतु एकही सॉकेट डेटा पाठवू इच्छित नाही :/



आम्ही वाचण्याची शिफारस करतो

शीर्षस्थानी