當(dāng)前位置:
首頁(yè) >
Delphi的Socket编程要分几步?
發(fā)布時(shí)間:2025/3/15
39
豆豆
生活随笔
收集整理的這篇文章主要介紹了
Delphi的Socket编程要分几步?
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Delphi的Socket編程要分幾步?
2008-12-20 02:03:24 標(biāo)簽:Delphi Socket 編程 [推送到技術(shù)圈]
| ClientSocket 和ServerSocket 幾個(gè)重要的屬性:??? 1.client和server都有port屬性,需要一致才能互相通信??? 2.client有Address屬性,使用時(shí)填寫(xiě)對(duì)方(server)的IP地址??? ???? 幾個(gè)重要的事件:??? ??? client:??? OnRead事件,當(dāng)client受到?jīng)_擊消息時(shí)在OnRead事件中可以獲得server發(fā)送過(guò)來(lái)消息。??? ??? Server:???? OnClientRead事件,與上述client的作用相同??? ???? 發(fā)送信息:??? ??? clien使用SocketClient1.Socket.SendBuf(char類型的數(shù)組,信息長(zhǎng)度);??? ??? server使用SocketServer1.Socket.Connection[0].SendBuf(char類型的數(shù)組,信息長(zhǎng)度);??? ???? 接收信息??? ???? clien使用SocketClient1.Socket.ReceiveBuf(char類型的數(shù)組,信息長(zhǎng)度);??? ???? server使用SocketServer1.Socket.Connection[0].ReceiveBuf(char類型的數(shù)組,信息長(zhǎng)度);??? ???? 使用sockets ???????? Socket 控件讓你建立一個(gè)利用TCP/IP和有關(guān)的協(xié)議與其他系統(tǒng)進(jìn)行通信的應(yīng)用。使用Sockets,你能夠讀和寫(xiě)通過(guò)它連接的其他機(jī)器,而不用擔(dān)心實(shí)際的網(wǎng)絡(luò)軟件的相關(guān)細(xì)節(jié)。Sockets提供基于TCP/IP協(xié)議的連接。除此以外還能很好的工作,在其他相關(guān)的協(xié)議。??? ???????? Delphi 提供你寫(xiě)網(wǎng)絡(luò)服務(wù)器或客戶應(yīng)用程序去讀和寫(xiě)其他的系統(tǒng)。一個(gè)服務(wù)或客戶程序通常專注于一個(gè)單一的服務(wù)如超文本傳送協(xié)議(HTTP)或文件傳輸協(xié)議 (FTP)。使用server?????????? sockets,一個(gè)應(yīng)用程序可以提供這些服務(wù)中的一個(gè)去連接一個(gè)希望使用服務(wù)的客戶程序。Client?????????? sockets允許一個(gè)應(yīng)用使用這些服務(wù)中的一個(gè)去連接提供這個(gè)服務(wù)的服務(wù)應(yīng)用。??? ??????? 使用sockets去寫(xiě)應(yīng)用程序,你必須理解下面這些知識(shí):??? ??? 一、服務(wù)工具??? ???? 當(dāng)你需要寫(xiě)網(wǎng)絡(luò)服務(wù)或客戶應(yīng)用時(shí),Sockets提供一種接合。對(duì)于許多服務(wù),象HTTP 或??? FTP,第三方服務(wù)商提供這些服務(wù)已經(jīng)相當(dāng)有效。有些甚至隨著操作系統(tǒng)捆綁而來(lái),以便不用你自己寫(xiě)。然而,當(dāng)你想更多的控制服務(wù)的實(shí)現(xiàn),如想讓你的應(yīng)用程序與網(wǎng)絡(luò)通信更加緊密,或當(dāng)沒(méi)有一個(gè)服務(wù)能提供你特殊需要的服務(wù)時(shí),你可能想建立你自己的服務(wù)或客戶應(yīng)用。例如,工作在分布式 data??????????? sets時(shí),你可能想為數(shù)據(jù)庫(kù)寫(xiě)一層與其他系統(tǒng)通信的應(yīng)用。想使用Sockets實(shí)現(xiàn)一個(gè)服務(wù),你必須理解:??? ???? ????? 1.服務(wù)協(xié)議??? ???? 在你寫(xiě)一個(gè)網(wǎng)絡(luò)服務(wù)或客戶程序前,你必須明白你的應(yīng)用將提供或使用什么服務(wù)。你的網(wǎng)絡(luò)應(yīng)用必須支持許多服務(wù)的標(biāo)準(zhǔn)協(xié)議。如果你為標(biāo)準(zhǔn)的服務(wù)例如 HTTP,FTP寫(xiě)網(wǎng)絡(luò)應(yīng)用,你必須先理解與其他系統(tǒng)通信所使用的協(xié)議。特殊服務(wù)細(xì)節(jié)你必須看提供的或使用的文檔。??? ???????? 如果你的應(yīng)用程序提供一個(gè)新的服務(wù)與其他系統(tǒng)通信,第一步是為這個(gè)服務(wù)的服務(wù)端和客戶端設(shè)計(jì)通信協(xié)議。什么信息將發(fā)送?如何整理這些信息?如何對(duì)這些信息進(jìn)行編碼???? ???? ????? 應(yīng)用程序通信??? ?????? 經(jīng)常的,你的網(wǎng)絡(luò)服務(wù)端或客戶端應(yīng)用程序要提供一層在網(wǎng)絡(luò)軟件和一個(gè)應(yīng)用之間使用的服務(wù)。例如,一個(gè)HTTP服務(wù)站點(diǎn)在INternet與一個(gè)Web 服務(wù)應(yīng)用之間為HTTP請(qǐng)求信息提供內(nèi)容和應(yīng)答。??? ?????????? 在你的網(wǎng)絡(luò)應(yīng)用(或客戶應(yīng)用)和網(wǎng)絡(luò)軟件之間Sockets 提供一個(gè)接口。你必須提供一個(gè)接口,在你的應(yīng)用程序與應(yīng)用間使用。你可以拷貝第三方服務(wù)商提供的標(biāo)準(zhǔn)API(例如ISAPI),或你可以設(shè)計(jì)和發(fā)布你自己的API.??? ???? ????? 2.理解服務(wù)和端口??? ????? 許多標(biāo)準(zhǔn)服務(wù)都有關(guān)聯(lián)的、指定的端口號(hào)。當(dāng)執(zhí)行服務(wù)時(shí),你可以為服務(wù)考慮一個(gè)端口號(hào)。如果你實(shí)現(xiàn)一個(gè)標(biāo)準(zhǔn)服務(wù),Windows??? socket???? objects??? 提供一些方法讓你為服務(wù)尋找端口號(hào)。如果提供一個(gè)新的服務(wù),在基于Windows 95??? 或 NT機(jī)器上,你能夠在文件Services中為你的服務(wù)指定一個(gè)相關(guān)聯(lián)的端口號(hào)。設(shè)置Services文件的更多信息請(qǐng)看微軟的Windows??? Sockets文檔。??? ???? ????? 二、Socket連接的類型??? ????? Socket連接可以分成三個(gè)基本的類型,它們反映了如何開(kāi)始連接和本地Socket 連接是什么。這三個(gè)類型是:??? ???? ???? 1.客戶端連接??? ?????? 客戶端連接是一個(gè)本地系統(tǒng)的客戶端socket與一個(gè)遠(yuǎn)程系統(tǒng)上的服務(wù)端Socket連接。客戶端連接由客戶端Socket開(kāi)始。首先,客戶端 Socket必須描述它想連接到的服務(wù)端Socket. 接著客戶端socket查找服務(wù)端socket,當(dāng)找到服務(wù)器時(shí),就要求連接。服務(wù)端socket可能不能完成正確的連接。服務(wù)器sockets維持一個(gè)客戶端請(qǐng)求隊(duì)列,在他們有時(shí)間時(shí)完成連接。當(dāng)服務(wù)端socket接受客戶端連接,服務(wù)端socket將向它想連接的客戶socket發(fā)送一個(gè)完整的描述,客戶端的連接完成。??? ???? ???????? 2.傾聽(tīng)連接??? ???????? 服務(wù)器 socket不會(huì)去定位客戶端,代替的,他們形成被動(dòng)的,"半連接"狀態(tài),傾聽(tīng)來(lái)自客戶端的請(qǐng)求。服務(wù)器?????????? sockets形成一個(gè)隊(duì)列,存放它們聽(tīng)到的連接請(qǐng)求。這個(gè)隊(duì)列記錄著客戶端連接請(qǐng)求就象他們已連接進(jìn)來(lái)一樣。當(dāng)服務(wù)器sockets同意客戶連接請(qǐng)求時(shí),它形成一個(gè)新的socket去連接客戶端,因此這個(gè)傾聽(tīng)連接能保持開(kāi)放狀態(tài)允許其他客戶端請(qǐng)求。??? ???? ???????? 3.服務(wù)端連接??? ???????? 當(dāng)傾聽(tīng)socket同意一個(gè)客戶端請(qǐng)求時(shí),服務(wù)器端socket形成一個(gè)服務(wù)器連接。當(dāng)服務(wù)器端同意連接時(shí),向客戶端發(fā)送一個(gè)服務(wù)端socket描述以完成連接,當(dāng)客戶端socket收到這個(gè)描述時(shí)這個(gè)連接得到確認(rèn),連接完成。一但連接到客戶端的Socket完成,服務(wù)端連接就不能識(shí)別從一個(gè)客戶端來(lái)的連接。末端雙方有同樣的能力去接收同樣的事件類型。只有傾聽(tīng)(listening)連接是根本不同的,它只有一個(gè)單一的末端。??? 三、sockets描述??? ???????? Sockets讓你的網(wǎng)絡(luò)應(yīng)用軟件通過(guò)網(wǎng)絡(luò)與其他系統(tǒng)進(jìn)行通信。在網(wǎng)絡(luò)連接中每個(gè)socket可以看成一個(gè)終端點(diǎn)。它有一個(gè)指定的地址。??? ???? ????????? *這個(gè)系統(tǒng)正在運(yùn)行??? ????????? *它理解的接口類型??? ????????? *用來(lái)連接的端口??? ????????? 一個(gè)完整的socket連接描述,你必須提供sockets?????????? 在連接兩端的地址。在你開(kāi)始一個(gè)socket連接前,你必須完整的描述你想得到的連接。有些信息可以從你的應(yīng)用軟件運(yùn)行的系統(tǒng)平臺(tái)上得到。例如,你不需要描述一個(gè)客戶端socket的本地IP地址--這個(gè)信息可以從操作系統(tǒng)上獲得。你必須提供你工作所依靠的socket的類型的信息。客戶端socket必須描述他們想連接的服務(wù)器。偵聽(tīng)服務(wù)器sockets必須描述他們提供反應(yīng)的服務(wù)器的端口。一個(gè)socket?????????? 連接終端的完整描述包括兩部分:??? ???? ???1.IP地址??? ??????? 主機(jī)是這樣一個(gè)系統(tǒng),它運(yùn)行著包含有socket的應(yīng)用程序。你必須描述主機(jī)給socket,通過(guò)給出主機(jī)的IP地址來(lái)完成這個(gè)描述。IP地址是一個(gè)有四個(gè)數(shù)字(byte)值的,在標(biāo)準(zhǔn)internet點(diǎn)付內(nèi)的字符串。??? ??????? 例如123.197.1.2??? ??????? 一個(gè)簡(jiǎn)單的系統(tǒng)可以支持多于一個(gè)的IP地址。IP地址通常難于記憶并且容易打錯(cuò)。一個(gè)可供選擇的方法是使用主機(jī)名。主機(jī)名就是IP地址的別名,它就是你常看到的統(tǒng)一資源定位(URLs)。它是一個(gè)字符串,包括了域名和服務(wù)。??? ??????? 例如??????? [url]http://www.wsite.com???[/url] ??????? 許多內(nèi)部網(wǎng)提供給主機(jī)的名字對(duì)應(yīng)的系統(tǒng)IP地址是internetIP地址。在windows95?????? 和NT機(jī)器上,如果一個(gè)主機(jī)名不能用,你可以在HOSTS文件中為你的本地IP地址(這個(gè)本地IP地址應(yīng)該是指你想連接的主機(jī)IP地址--zyqsj)建立一個(gè)進(jìn)入的名字。??? ??????? 關(guān)于HOSTS文件的更多信息請(qǐng)看WINDOWS??? SOCKETS的文檔。??? ??????? 服務(wù)器sockets不需要指定主機(jī)。本地IP地址可以從系統(tǒng)中讀到。如果本地系統(tǒng)支持多于一個(gè)的IP地址,服務(wù)器sockets將同時(shí)在所有的IP地址上偵聽(tīng)客戶端請(qǐng)求。當(dāng)一個(gè)服務(wù)器socket同意一個(gè)連接,客戶端提供一個(gè)遠(yuǎn)程IP地址。客戶sockets必須指定遠(yuǎn)程主機(jī)通過(guò)提供主機(jī)名或者IP地址。??? ???? ???????? 在主機(jī)名和IP地址間作一個(gè)選擇??? ???????? 許多應(yīng)用軟件使用一個(gè)主機(jī)名去指定一個(gè)系統(tǒng)。主機(jī)名容易記住和容易檢查排版錯(cuò)誤。進(jìn)一步講,服務(wù)器能改變系統(tǒng)或與IP地址關(guān)聯(lián)的特殊的主機(jī)名。使用一個(gè)主機(jī)名,能夠允許客戶端通過(guò)主機(jī)名描述找到抽象的站點(diǎn),即使主機(jī)使用一個(gè)新的IP地址。??? ????????? 如果主機(jī)名是未知的,客戶socket必須指定服務(wù)器系統(tǒng)使用的IP地址。通過(guò)給一個(gè)IP地址來(lái)指定服務(wù)器將更快。當(dāng)你提供主機(jī)名時(shí),socket在定位服務(wù)器系統(tǒng)前,必須搜尋與這個(gè)主機(jī)名相關(guān)的IP地址。??? ???? ????2.端口號(hào)??? ???????? 雖然IP得地址提供了足夠的信息去找到socket連接中位于另一端的系統(tǒng),你通常還需要指定那個(gè)系統(tǒng)的端口號(hào)。沒(méi)有端口號(hào),一個(gè)系統(tǒng)在同一時(shí)間只能進(jìn)行一個(gè)單一的連接。端口號(hào)是唯一標(biāo)識(shí)那允許一個(gè)獨(dú)立系統(tǒng)連接到支持同時(shí)多個(gè)連接的主機(jī),每個(gè)連接都必須指定一個(gè)端口號(hào)。??? ???????? 在網(wǎng)絡(luò)應(yīng)用中,對(duì)于服務(wù)器工具來(lái)說(shuō)端口號(hào)是一個(gè)數(shù)字代碼。有一個(gè)習(xí)慣就是偵聽(tīng)服務(wù)連接到他們自己固定的端口號(hào)上,以便他們能找到客戶端sockets.服務(wù)器socket監(jiān)聽(tīng)為他們提供服務(wù)的相關(guān)端口號(hào)。當(dāng)他們?cè)试S給予一個(gè)客戶端socket連接時(shí),他們創(chuàng)建一個(gè)獨(dú)立的socket連接,使用不同的專用的端口號(hào)。通過(guò)這個(gè)方法,能持續(xù)的監(jiān)聽(tīng)相關(guān)服務(wù)的端口號(hào)。??? ???????? 客戶端socket使用一個(gè)專用的本地端口號(hào),就不用其他的socket去尋找它們。他們指定他們想連接的服務(wù)器端socket的端口號(hào),這樣他們就能找到服務(wù)器應(yīng)用程序。常常的,這個(gè)端口號(hào)是通過(guò)命名想連接的服務(wù)來(lái)間接指定的。??? ???????? 四、使用socket控件??? ???????? Delphi提供兩個(gè)socket控件,客戶端sockets和服務(wù)器sockets.他們?cè)试S你的網(wǎng)絡(luò)應(yīng)用構(gòu)成連接其他的機(jī)器和允許你通過(guò)這個(gè)連接來(lái)讀寫(xiě)信息。與每個(gè)socket控件相關(guān)聯(lián)的是windows????????? socket對(duì)象,它們?cè)诮K端的的作用是一個(gè)實(shí)際的socket連接。socket控件使用windows????????? socket對(duì)象去封裝windows??? socket???? API???? 調(diào)用,所以你的應(yīng)用不用去關(guān)心連接建立的細(xì)節(jié)或管理socket信息。??? ???????? 如果你想利用windows???? socket??? API調(diào)用或自定義連接細(xì)節(jié),socket控件提供了便利,你可以使用windows??? socket對(duì)象的properies,events和方法。??? ???? ??????? 1.使用客戶端sockets??? ???????? 添加一個(gè)客戶端socket控件(TClientSocket)到你的form或data???? module??? 使你的應(yīng)用成為一個(gè)TCP/IP客戶。客戶sockets允許你指定你想連接的服務(wù)器socket和你希望服務(wù)器提供的服務(wù)。一但你描述你想得到的連接,你可以使用客戶socket控件去完成連接服務(wù)。??? ???????? 每個(gè)客戶socket控件使用獨(dú)立的客戶windows???? socket對(duì)象(TClientWinSocket)去應(yīng)答連接中的客戶終端。使用客戶sockets去:??? ???? ???????? A.指定想得到的服務(wù)??? ???????? 客戶socket控件有一個(gè)數(shù)字properties,允許你指定想連接的服務(wù)器系統(tǒng)和端口。你可以通過(guò)主機(jī)名來(lái)指定服務(wù)器系統(tǒng),使用Host????????? property。??? ???????? 如果你不知道主機(jī)名,或者你關(guān)心找到服務(wù)器的速度,你可以指定服務(wù)器系統(tǒng)的IP地址,通過(guò)使用 Address??? property。你必須指定IP地址和主機(jī)名中的一個(gè)。??? ???????? 如果你兩個(gè)都指定,客戶socket控件將使用主機(jī)名。除服務(wù)器系統(tǒng)外,你必須指定你的客戶socket將連接的在服務(wù)器系統(tǒng)上的端口。你能夠直接使用 Port????????? property來(lái)指定服務(wù)端口號(hào)。或者直接在Service???? property使用想得到的服務(wù)的名字。如果你指定端口號(hào)和服務(wù)名,客戶socket控件將使用服務(wù)名。??? ???? ???????? B.建立連接??? ???????? 一旦你在客戶socket控件中完成了設(shè)置描述你想連接的服務(wù)器的屬性,你就可以進(jìn)行連接,通過(guò)調(diào)用Open方法。如果你想你的應(yīng)用啟動(dòng)時(shí)自動(dòng)建立連接,在設(shè)計(jì)時(shí)設(shè)置Active??????? property為true,通過(guò)使用Object????????? Inspector來(lái)設(shè)置。??? ???? ???????? C.取得關(guān)于連接的信息??? ???????? 完成連接到服務(wù)器socket后,你可以使用與你的客戶socket控件相關(guān)的客戶windows??? socket??? object去取得關(guān)于連接的信息。使用Socket??? property去訪問(wèn)client??? windows??? socket???? object。 windows??? socket??? object 有一個(gè)properties,它能讓你確定在連接的兩端客戶和服務(wù)器使用的地址和端口號(hào)。??? ???????? 當(dāng)使用一個(gè)windows??? socket??? API 調(diào)用時(shí),你可以使用SocketHandle??? property區(qū)獲得socket連接使用的handle。你可以使用Handle??? property去訪問(wèn)windows,以便接收來(lái)自socket連接的信息。????? ???????? AsyncStyles????? property決定哪種信息類型是windows??? handle要接收的。??? ???? ???????? D.關(guān)閉連接??? ???????? 當(dāng)你完成通訊想關(guān)閉socket 連接時(shí),你能夠通過(guò)調(diào)用Close方法來(lái)關(guān)閉連接。連接可能要由服務(wù)器端來(lái)關(guān)閉。如果是這種情況,你將收到一個(gè)OnDisconnect??? 事件的通知。??? ???? ???? 2.使用服務(wù)器sockets??? ????? 添加一個(gè)服務(wù)端socket控件ServerSocket 到你的form或data??? module使你的應(yīng)用成為一個(gè)TCP/IP服務(wù)器。服務(wù)器sockets允許你指定你想提供的服務(wù)或你想用來(lái)監(jiān)聽(tīng)客戶請(qǐng)求時(shí)使用的端口。你可以使用服務(wù)器socket控件去監(jiān)聽(tīng)和允許客戶連接請(qǐng)求。每個(gè)服務(wù)器socket控件使用一個(gè)單一的服務(wù)器windows??? socket??? Object(TServerWinSocket)去應(yīng)答在服務(wù)器端監(jiān)聽(tīng)到的連接。它通常使用一個(gè)服務(wù)器客戶winodws??? socket??? Object(TServerClientWinSocket)應(yīng)答在服務(wù)器端每個(gè)活動(dòng)的,連接著得到允許服務(wù)的客戶socket。使用服務(wù)器 sockets去:??? ???? ?????? A.指定端口??? ?????? 在你的服務(wù)器socket能夠監(jiān)聽(tīng)客戶請(qǐng)求之前,你必須指定一個(gè)端口給你的監(jiān)聽(tīng)服務(wù)。你可以使用Port???? property來(lái)指定這個(gè)端口。如果你的服務(wù)器應(yīng)用提供一個(gè)標(biāo)準(zhǔn)的服務(wù),這個(gè)服務(wù)使用一個(gè)習(xí)慣使用的相關(guān)聯(lián)的端口。你能夠使用Service???? property直接指定端口號(hào)。使用Service???? property是一個(gè)好的主意,能夠減少設(shè)置端口號(hào)時(shí)的錯(cuò)誤。如果你既指定了Port????????? property,又指定了Service???? property,服務(wù)socket將使用服務(wù)名。??? ???? ????? B.監(jiān)聽(tīng)客戶請(qǐng)求??? ?????? 一旦你在server???? socket控件上設(shè)置好你的端口號(hào),你就能夠通過(guò)在運(yùn)行時(shí)通過(guò)調(diào)用Open方法來(lái)監(jiān)聽(tīng)一個(gè)連接。如果你希望你的應(yīng)用程序能夠在啟動(dòng)的時(shí)候自動(dòng)監(jiān)聽(tīng)連接,在設(shè)計(jì)的時(shí)候通過(guò)使用Object???? Inspector設(shè)置Active 屬性為true。??? ???? ????? C.連接到客戶端。??? ?????? 當(dāng)監(jiān)聽(tīng)服務(wù)socket控件接收到一個(gè)客戶端連接請(qǐng)求時(shí)他們將自動(dòng)接受這個(gè)請(qǐng)求。當(dāng)你沒(méi)次收到通知時(shí),OnClientConnetc事件將發(fā)生。??? ???? ????? D.取得關(guān)于連接的信息??? ????? 一但你的服務(wù)器socket打開(kāi)了監(jiān)聽(tīng)連接,你能夠使用與你服務(wù)器socket控件相關(guān)聯(lián)的服務(wù)器windows??? socket???? object來(lái)取得關(guān)于連接的信息。使用Socket???? property去訪問(wèn)server???? windows???? socket???? object。windows??? socket??? object有一個(gè)屬性能夠讓你找到關(guān)于所有活動(dòng)的客戶socket連接這些客戶socket是你通過(guò)服務(wù)器socket控件允許連接的。使用Handle屬性去存取windows通過(guò)socket連接收到的信息。??? ????? 每個(gè)活動(dòng)的,連接到客戶應(yīng)用是通過(guò)服務(wù)、客戶windows?? socket?? bject??? (TServerClientWinSocket)封裝的。你能夠通過(guò)server??? windows?? socket?? object的連接屬性來(lái)訪問(wèn)所有的這些。這些server??? client?? windows??? socket??? object有些屬性讓你能夠決定哪些地址和端口號(hào)給連接的兩端--客戶和服務(wù)器socket使用。當(dāng)你使用windows?? socket?? API調(diào)用時(shí),可以使用SocketHandle屬性去獲得socket連接使用的handle。你能夠使用Handle屬性去訪問(wèn)windows從 socket連接處得來(lái)的信息。AsyncStyles屬性決定windows??? handle將接收哪種類型的信息。??? ???? ????? E.關(guān)閉連接??? ????? 當(dāng)你決定關(guān)閉監(jiān)聽(tīng)連接時(shí),調(diào)用Close方法。這將關(guān)閉所有打開(kāi)著的,連接到客戶應(yīng)用的連接,取消任何尚未同意的連接,接著關(guān)閉監(jiān)聽(tīng)連接以便你的服務(wù) socket控件不在接受任何新的連接。當(dāng)客戶端關(guān)閉他們自己獨(dú)立的連接到你的server????????? socket的連接時(shí),你可以在OnClientDisconnect事件中得到訊息。??? ???? ????五、socket事件的應(yīng)答??? ????? 當(dāng)使用sockets寫(xiě)應(yīng)用程序時(shí),大多數(shù)工作發(fā)生在socket控件的handler事件中。當(dāng)通過(guò)socket連接開(kāi)始讀或?qū)憰r(shí),OnRead和 OnWrite事件在non-blocking??? client??? sockets中發(fā)生從而通知sockets.同樣的,服務(wù)器sockets(blocking??? or??? non-blocking)收到OnClientRead和OnClientWrite事件.??? ???? 當(dāng)服務(wù)器結(jié)束一個(gè)連接時(shí),客戶scokets收到一個(gè)OnDisconnect事件.當(dāng)客戶端結(jié)束一個(gè)連接時(shí),服務(wù)器socket收到一個(gè)OnClientDisconnect事件.??? ???? 另外,客戶端Sockets和服務(wù)器端socket從連接中收到一個(gè)錯(cuò)誤信息時(shí),都將產(chǎn)生有個(gè)錯(cuò)誤事件.??? ???? ???? 錯(cuò)誤事件:客戶sockets和服務(wù)器sockets通常會(huì)產(chǎn)生一個(gè)OnError事件,當(dāng)他們從連接中收到一個(gè)錯(cuò)誤信息的時(shí)候.你能夠?qū)懸粋€(gè) OnError事件處理去響應(yīng)這些錯(cuò)誤信息.這個(gè)OnError事件處理提供傳送關(guān)于socket試圖做什么的時(shí)候這個(gè)錯(cuò)誤發(fā)生的信息,以及錯(cuò)誤信息提供的錯(cuò)誤代碼.你可以在OnError事件處理中對(duì)這個(gè)錯(cuò)誤作出響應(yīng),并且把錯(cuò)誤代碼改為0,以避免socket產(chǎn)生一個(gè)例外.??? ???? ???? 當(dāng)開(kāi)始和完成發(fā)生時(shí),socket控件通常會(huì)收到一個(gè)事件號(hào)(number??????? of??????? events).如果你的應(yīng)用程序需要改變socket開(kāi)始操作的處理過(guò)程或通過(guò)連接開(kāi)始讀或?qū)懖僮鲿r(shí),你將寫(xiě)事件handlers去應(yīng)答這些 client???? events和server??? events.??? ???? ?????? A.client???? events??? ?????? 當(dāng)一個(gè)客戶socket打開(kāi)一個(gè)連接時(shí),以下事件發(fā)生:??? ?????? 1.一個(gè)OnLookup事件最先發(fā)生,它試圖去定位server??????? socket.在這里你不能改變Host,Address,Port,Service屬性去改變你想定位的服務(wù)器.你能夠使用Socket屬性去訪問(wèn) client??????? windows??????? socket??????? object,并且使用它的SocketHandle屬性去調(diào)用windows?????? API,以便改變socket的客戶屬性.例如,如果你想在客戶應(yīng)用軟件中設(shè)置端口號(hào),你必須在server?????? client連接前做這件事.??? ?????? 2.windows??? socket設(shè)置和初始化事件通知.??? ?????? 3.當(dāng)找到server?????? socket 一個(gè)OnConnecting事件發(fā)生.在這事件中,windows??????? Socket??????? object可以利用的是通過(guò)socket屬性提供關(guān)于連接的另一端的服務(wù)socket的一些信息.這是獲得實(shí)際使用來(lái)連接的端口和IP地址的第一個(gè)機(jī)會(huì),它可能不同于從監(jiān)聽(tīng)socket處同意連接時(shí)得到的端口或IP地址.??? ?????? 4.服務(wù)器同意連接請(qǐng)求,客戶端socket完成連接.??? ?????? 5.當(dāng)一個(gè)連接得到確定后,一個(gè)OnConnect事件發(fā)生.如果你的socket立即開(kāi)始通過(guò)連接讀或?qū)?就應(yīng)寫(xiě)一個(gè)OnConnect事件Handler去作這件事.??? ???? ?????? B.服務(wù)器端事件(server??????? events)??? ?????? 服務(wù)器socket控件通過(guò)兩中方式連接:監(jiān)聽(tīng)連接和連接到客戶應(yīng)用.服務(wù)器socket收到這兩個(gè)連接的所有事件.??? ???? ?????? 監(jiān)聽(tīng)時(shí)事件??? ?????? 當(dāng)構(gòu)成監(jiān)聽(tīng)連接前,OnListen事件發(fā)生.在這個(gè)時(shí)候你能夠通過(guò)socket屬性獲得server??????? windows??????? socket??????? object.你能夠使用它的SocketHandle屬性去改變socket,在socket打開(kāi)監(jiān)聽(tīng)之前.例如,如果你想限定監(jiān)聽(tīng)服務(wù)使用的IP地址,你可以在這個(gè)OnListen事件Handler中做.??? ???? ?????? 與客戶端連接的事件 ?????? 當(dāng)一個(gè)服務(wù)器socket同意一個(gè)客戶連接請(qǐng)求時(shí),接下來(lái)的事件發(fā)生:??? ?????? 1.服務(wù)器socket產(chǎn)生一個(gè)OnGetSocket事件,通過(guò)windows?? socket??? handle傳送給連接的另一端的socket.如果你想提供自己定義的TServerClientWinSocket?? of?? descendant,你可以在OnGetSocket??????? 事件 handler中建立,將被用來(lái)替代TServerClientWinSocket.??? 2.一個(gè)OnAccept事件發(fā)生,傳送新的TServerClientWinSocket對(duì)象給事件句柄.這是第一個(gè)要點(diǎn),當(dāng)你使用TServerClientWinSocket的屬性去獲得被連接中服務(wù)的那端的客戶的信息時(shí).??? 3.如果服務(wù)類型是stThreadBlocking,一個(gè)OnGetThread事件發(fā)生。如果你想提供自己定義的TServerClientThread子類,你可以在OnGetThread事件句柄中建立一個(gè),它將替代TServerClientThread.??? ?????? 4.如果服務(wù)類型是stThreadBlocking,一個(gè)ONThreadStart事件發(fā)生。當(dāng)這個(gè)線程(thread)開(kāi)始執(zhí)行時(shí).如果你想執(zhí)行任何初始化這個(gè)線程,或調(diào)用一些windows?? socket??? API在這線程開(kāi)始通過(guò)連接讀和寫(xiě)之前,應(yīng)該使用OnThreadStart事件句柄. 5.當(dāng)客戶端完成一個(gè)連接時(shí),一個(gè)OnClientConnect事件發(fā)生.如果是non-blocking服務(wù),你可能想開(kāi)始通過(guò)socket連接在這端進(jìn)行讀或?qū)懖僮???? ???? ????六、通過(guò)Socket 連接進(jìn)行讀和寫(xiě)??? ??????? 通過(guò)socket連接到其他機(jī)器的原因是想通過(guò)這些連接來(lái)讀和寫(xiě)信息.什么信息是你要讀和寫(xiě)的,或者當(dāng)你想讀和寫(xiě)時(shí)是依靠哪些socket連接的相關(guān)服務(wù)的.??? ??????? 通過(guò)sockets進(jìn)行讀和寫(xiě)可以是異步的,所以在你的網(wǎng)絡(luò)應(yīng)用中不需要阻塞其他代碼的執(zhí)行。這是調(diào)用non-blocking?????? connection.你也同樣可以通過(guò)blocking?????? connection,這時(shí)你的下一行代碼的執(zhí)行必須等到讀或?qū)懖僮魍瓿???? ???? ????? A.Non-blocking ????? 連接,讀和寫(xiě)是異步的,?? 所以在你的網(wǎng)絡(luò)應(yīng)用中不需要阻塞其他代碼的執(zhí)行.建立一個(gè)Non-blocking連接:??? ????? 1.在客戶socket中設(shè)置ClientType屬性為ctNonBlocking.??? ????? 2.在服務(wù)器socket中設(shè)置ServerType屬性為stNonBlocking.??? ????? 當(dāng)連接是non-blocking時(shí),連接的另一端企圖讀或?qū)憰r(shí)讀和寫(xiě)事件將把這個(gè)信息通知你的socket.??? ???? ????? 讀和寫(xiě)操作事件??? ?????? Non-blocking?? sockets想通過(guò)連接讀或?qū)憰r(shí),它會(huì)產(chǎn)生一個(gè)讀和寫(xiě)操作事件通知你的socket.在客戶端sockets,你可以在OnRead或OnWrite事件句柄中對(duì)這些事件做出反應(yīng).在服務(wù)器端Scokets,可以在OnClientRead或OnClientWrite事件句柄中對(duì)這些事件做出反應(yīng).與 socket連接相關(guān)聯(lián)的windows?????? socket?????? object在事件句柄的讀或?qū)懼斜划?dāng)作一個(gè)參數(shù).Windows?? socket?? object提供一個(gè)方法號(hào)(number?? of?? methods)以允許你通過(guò)連接讀或?qū)???? 通過(guò)socket連接讀,使用ReceiveBuf或ReceiveText方法.在使用ReceiveBuf方法前,使用Receivelength方法去確定在連接的另一端socket準(zhǔn)備發(fā)送的字節(jié)數(shù)(number?????? of?????? bytes).??? ????? 通過(guò)socket連接寫(xiě),使用SendBuf,SendStream,或SendText方法.如果你通過(guò)socket發(fā)送信息后不在需要socket連接,你可以使用SendStreamThenDrop方法.?? SendStreamThenDrop在寫(xiě)完所有的信息后將關(guān)閉Socket連接,它能夠從stream讀信息.如果你使用SendStream或 SendStreamThenDrop方法,不要釋放Stream?? object,?? socket在連接結(jié)束后會(huì)自動(dòng)釋放這個(gè)Stream.??? ????? 注意:SendStreamThenDrop將關(guān)閉一個(gè)獨(dú)立的客戶連接服務(wù),而不是監(jiān)聽(tīng)連接.??? ???? ????? B.Blocking?????? connections??? ????? 當(dāng)你使用的連接是Blocking時(shí),你的Socket必須通過(guò)連接發(fā)起讀或?qū)懖僮?勝過(guò)被動(dòng)的等待從socket連接發(fā)來(lái)的通知.?????? 當(dāng)你的連接末端的讀和寫(xiě)操作發(fā)生改變時(shí) ????? 使用Blocking??? socket.對(duì)于客戶端sockets,設(shè)置ClientType屬性為ctBlocking 以便構(gòu)成一個(gè)blocing?????? connection.根據(jù)你的客戶端應(yīng)用想完成什么,你可能想建立一個(gè)執(zhí)行線程去完成讀或?qū)懖僮?以便你的應(yīng)用能夠繼續(xù)執(zhí)行其他的線程,當(dāng)它在等待通過(guò)連接讀或?qū)懖僮鞯耐瓿???? ??????對(duì)于服務(wù)器sockets,設(shè)置ServerType屬性為stThreadBlocking 以便構(gòu)成一個(gè)blocking connection.因?yàn)閎locking????? connections在等待通過(guò)連接讀或?qū)懶畔⑼瓿蓵r(shí)掛起了其他代碼的執(zhí)行,服務(wù)器socket控件通常產(chǎn)生一個(gè)新的執(zhí)行線程給每一個(gè)客戶連接,當(dāng) ServerType設(shè)置為stThreadBlocking時(shí).許多使用Blocking連接的應(yīng)用都寫(xiě)使用線程(using?????? threads.甚至如果你不使用線程,你可能也想使用 TWinSocketStream 去讀和寫(xiě).??? ????? 1)using?????? threads??? ????? 當(dāng)使用一個(gè)blocking?????? connection進(jìn)行讀或?qū)懖僮鲿r(shí),客戶sockets不會(huì)自動(dòng)產(chǎn)生一個(gè)新線程.如果你的客戶應(yīng)用程序沒(méi)有什么事做,直到讀或?qū)懶畔⑼瓿?那么這正是你想要的.如果你的應(yīng)用包括了一個(gè)用戶界面,它還需要響應(yīng)用戶的操作,那么,你可能想產(chǎn)生一個(gè)獨(dú)立的線程去讀寫(xiě).當(dāng)服務(wù)器sockets形成一個(gè) blocking連接時(shí),他們常常產(chǎn)生獨(dú)立的線程給每一個(gè)客戶連接,所以沒(méi)有客戶需要等待直到其他客戶完成通過(guò)連接讀或?qū)懖僮?在默認(rèn)情況下,服務(wù)器 sockets使用TServerClientThread對(duì)象去實(shí)現(xiàn)為每個(gè)連接執(zhí)行不同的線程.??? ????? TServerClientThread對(duì)象模擬發(fā)生在non-blocking連接中的OnClientRead和OnClientWrite事件.可是,這些事件發(fā)生在監(jiān)聽(tīng)socket上時(shí),不是本地線程(thread-local).如果客戶請(qǐng)求頻繁,你將想建立你自己的 TServerClientThread子類去提供一個(gè)安全線程(Thread-Safe)去完成讀和寫(xiě)操作.??? ????? 當(dāng)寫(xiě)客戶線程或?qū)懛?wù)器線程時(shí),你能夠使用TwinSocketStream去做實(shí)際的讀寫(xiě)操作.??? ????? A)寫(xiě)客戶端線程??? ????? 為客戶端連接寫(xiě)一個(gè)線程,定義一個(gè)新線程對(duì)象,使用新線程對(duì)象對(duì)話框.你的新線程對(duì)象Execute方法的句柄的通過(guò)線程連接進(jìn)行讀寫(xiě)操作的細(xì)節(jié),可以建立一個(gè)TWinSocketStream對(duì)象,然后使用它來(lái)讀或?qū)???? ????? 使用你自己的線程,在OnConnect事件句柄中建立它.關(guān)于建立和運(yùn)行線程的更多信息,請(qǐng)看Executing?????? thread?????? objects.??? ???? ??? B)寫(xiě)服務(wù)器線程??? ????? 服務(wù)器連接線程由TServerClientThread派生.因?yàn)檫@個(gè),不能使用新線程對(duì)象對(duì)話框替代的. ???? ???? 注意你將用重載ClientExcute方法替代Execute方法.執(zhí)行ClientExecute方法必須為客戶端連接寫(xiě)一個(gè)同樣的Execute方法線程.然而,當(dāng)你從控件欄上放一個(gè)客戶socket控件到你的應(yīng)用上時(shí)來(lái)替代這個(gè)方法時(shí).監(jiān)聽(tīng)服務(wù)socket同意一個(gè)連接時(shí),服務(wù)客戶線程必須使用 TServerClientWinSocket對(duì)象來(lái)建立.這可以利用共公共的CientSocket屬性.另外,你能夠使用 HandleException這個(gè)protected性的方法,勝過(guò)??? ??? 你自己寫(xiě)你的thread-safe例外操作.??? ???? ??? 警告:Server?? sockets會(huì)緩存他們使用到的線程.確信ClientExecute方法執(zhí)行一些必要的初始化操作,以便它們?cè)谧詈髨?zhí)行時(shí)不致于產(chǎn)生不利的結(jié)果.??? ???? ??? 當(dāng)你使用你的線程時(shí),在OnGetThread事件句柄中建立它.當(dāng)建立線程,設(shè)置CreateSuspended參數(shù)為false.??? ???? ????? C.使用TwinSocketStream??? ????? 當(dāng)為一個(gè)blocking連接實(shí)現(xiàn)一個(gè)線程時(shí),你必須確定在連接的另一端的socket是準(zhǔn)備寫(xiě)還是讀.Blocking連接不會(huì)通知socket當(dāng)它準(zhǔn)備好寫(xiě)或讀操作的時(shí)候.想看看連接是否準(zhǔn)備好,使用TWinSocketStream對(duì)象.TWinSocketStream提供一個(gè)方法去幫助調(diào)整讀或?qū)懖僮鲿r(shí)間的選擇.調(diào)用WaitForData方法去等待,直到socket另一端的準(zhǔn)備好寫(xiě)操作.當(dāng)讀寫(xiě)操作使用TWinSocketStream時(shí), 如果讀或?qū)懖僮髟谥付ǖ臅r(shí)間期限內(nèi)未能完成,Stream將發(fā)生超時(shí).這個(gè)超時(shí)被當(dāng)作一個(gè)結(jié)果,socket應(yīng)用不會(huì)暫停,而是不斷的通過(guò)一個(gè) dropped???? connection試圖讀或?qū)???? ???? ??? 注意:你不能在non-blocking連接中使用TWinSocketStream 本文出自 51CTO.COM技術(shù)博客 |
總結(jié)
以上是生活随笔為你收集整理的Delphi的Socket编程要分几步?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Javascript实例:Select的
- 下一篇: Delphi 中的 Var buffer