程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 使用Sockets

使用Sockets

編輯:關於C++

使用sockets Socket控件讓你建立一個利用TCP/IP和有關的協議與其他系統進行通信的應用。使用Sockets,你能夠讀和寫通過它連接的其他機器,而不用擔心實際的網絡軟件的相關細節。Sockets提供基於TCP/IP協議的連接。除此以外還能很好的工作,在其他相關的協議,例如Xerox Network System (XNS), Digital's DEC net, or Novell's IPX/SPX 家族。

C++ Builder提供你寫網絡服務器或客戶應用程序去讀和寫其他的系統。一個服務或客戶程序通常專注於一個單一的服務如超文本傳送協議(HTTP)或文件傳輸協議(FTP)。使用server sockets,一個應用程序可以提供這些服務中的一個去連接一個希望使用服務的客戶程序。Client sockets允許一個應用使用這些服務中的一個去連接提供這個服務的服務應用。

使用sockets去寫應用程序,你必須理解下面這些知識:

一、服務工具

當你需要寫網絡服務或客戶應用時,Sockets提供一種接合。對於許多服務,象HTTP或FTP,第三方服務商提供這些服務已經相當有效。有些甚至隨著操作系統捆綁而來,以便不用你自己寫。然而,當你想更多的控制服務的實現,如想讓你的應用程序與網絡通信更加緊密,或當沒有一個服務能提供你特殊需要的服務時,你可能想建立你自己的服務或客戶應用。例如,工作在分布式data sets時,你可能想為數據庫寫一層與其他系統通信的應用。想使用Sockets實現一個服務,你必須理解:

1.服務協議

在你寫一個網絡服務或客戶程序前,你必須明白你的應用將提供或使用什麼服務。你的網絡應用必須支持許多服務的標准協議。如果你為標准的服務例如HTTP,FTP寫網絡應用,或even finger or time,你必須先理解與其他系統通信所使用的協議。特殊服務細節你必須看提供的或使用的文檔。

如果你的應用程序提供一個新的服務與其他系統通信,第一步是為這個服務的

服務端和客戶端設計通信協議。什麼信息將發送?如何整理這些信息?如何對這些信息進行編碼?

應用程序通信

經常的,你的網絡服務端或客戶端應用程序要提供一層在網絡軟件和一個應用之間使用的服務。例如,一個HTTP服務站點在INternet與一個Web 服務應用之間為HTTP請求信息提供內容和應答。

在你的網絡應用(或客戶應用)和網絡軟件之間Sockets 提供一個接口。你必須提供一個接口,在你的應用程序與應用間使用。你可以拷貝第三方服務商提供的標准API(例如ISAPI),或你可以設計和發布你自己的API.

2.理解服務和端口

許多標准服務都有關聯的、指定的端口號。當 執行服務時,你可以為服務考慮一個端口號。如果你實現一個標准服務, Windows socket objects 提供一些方法讓你為服務尋找端口號。如果提供一個新的服務,在基於Windows 95 或 NT機器上,你能夠在文件Services中為你的服務指定一個相關聯的端口號。設置Services文件的更多信息請看微軟 的Windows Sockets文檔。

二、Socket連接的類型

Socket連接可以分成三個基本的類型,它們反映了如何開始連接和本地Socket 連接是什麼。這三個類型是:

1.客戶端連接

客戶端連接是一個本地系統的客戶端socket與一個遠程系統上的服務端Socket連接。客戶端連接由客戶端Socket開始。首先,客戶端Socket必須描述它想連接到的服務端Socket. 接著客戶端socket查找服務端socket,當找到服務器時,就要求連接。服務端socket可能不能完成正確的連接。服務器sockets維持一個客戶端請求隊列,在他們有時間時完成連接。當服務端socket接受客戶端連接,服務端socket將向它想連接的客戶socket發送一個完整的描述,客戶端的連接完成。

2.傾聽連接

服務器 socket不會去定位客戶端,代替的,他們形成被動的,"半連接"狀態,傾聽來自客戶端的請求。服務器 sockets形成一個隊列,存放 它們聽到的連接請求。這個隊列記錄著客戶端連接請求就象他們已連接進來一樣。當服務器sockets同意客戶連接請求時,它形成一個新的socket去連接客戶端,因此這個傾聽連接能保持開放狀態允許其他客戶端請求。

3.服務端連接

當傾聽socket同意一個客戶端請求時,服務器端socket形成一個服務器連接。當服務器端同意連接時,向客戶端發送一個服務端socket描述以完成連接,當客戶端socket收到這個描述時這個連接得到確認,連接完成。一但連接到客戶端的Socket完成,服務端連接就不能識別從一個客戶端來的連接。末端雙方有同樣的能力去接收同樣的事件類型。只有傾聽(listening)連接是根本不同的,它只有一個單一的末端。

三、sockets描述

Sockets讓你的網絡應用軟件通過網絡與其他系統進行通信。在網絡連接中每個socket可以看成一個終端點。它有一個指定的地址。

*這個系統正在運行

*它理解的接口類型

*用來連接的端口

一個完整的socket連接描述,你必須提供sockets 在連接兩端的地址。在你開始一個socket連接前,你必須完整的描述你想得到的連接。有些信息可以從你的應用

軟件運行的系統平台上得到。例如,你不需要描述一個客戶端socket的本地IP地址--這個信息可以從操作系統上獲得。你必須提供你工作所依靠的socket的類型的信息。客戶端socket必須描述他們想連接的服務器。偵聽服務器sockets必須描述他們提供反應的服務器的端口。一個socket 連接終端的完整描述包括兩部分:

1.IP地址

主機是這樣一個系統,它運行著包含有socket的應用程序。你必須描述主機給socket,通過給出主機的IP地址來完成這個描述。IP地址是一個有四個數字(byte)值的,在標准internet點付內的字符串。

例如123.197.1.2

一個簡單的系統可以支持多於一個的IP地址。IP地址通常難於記憶並且容易打錯。一個可供選擇的方法是使用主機名。主機名就是IP地址的別名,它就是你常看到的統一資源定位(URLs)。它是一個字符串,包括了域名和服務。

例如 http://www.wsite.com

許多內部網提供給主機的名字對應的系統IP地址是internetIP地址。在windows95 和NT機器上,如果一個主機名不能用,你可以在HOSTS文件中為你的本地IP地址(這個本地IP地址應該是指你想連接的主機IP地址--zyqsj)建立一個進入的名字。

關於HOSTS文件的更多信息請看WINDOWS SOCKETS的文檔。

服務器sockets不需要指定主機。本地IP地址可以從系統中讀到。如果本地系統支持多於一個的IP地址,服務器sockets將同時在所有的IP地址上偵聽客戶端請求。當一個服務器socket同意一個連接,客戶端提供一個遠程IP地址。客戶sockets必須指定遠程主機通過提供主機名或者IP地址。

在主機名和IP地址間作一個選擇

許多應用軟件使用一個主機名去指定一個系統。主機名容易記住和容易檢查排版錯誤。進一步講,服務器能改變系統或與IP地址關聯的特殊的主機名。使用一個主機名,能夠允許客戶端通過主機名描述找到抽象的站點,即使主機使用一個新的IP地址。

如果主機名是未知的,客戶socket必須指定服務器系統使用的IP地址。通過給一個IP地址來指定服務器將更快。當你提供主機名時,socket在定位服務器系統前,必須搜尋與這個主機名相關的IP地址。

2.端口號

雖然IP得地址提供了足夠的信息去找到socket連接中位於另一端的系統,你通常還需要指定那個系統的端口號。沒有端口號,一個系統在同一時間只能進行一個單一的連接。端口號是唯一標識那允許一個獨立系統連接到支持同時多個連接的主機,每個連接都必須指定一個端口號。

在網絡應用中,對於服務器工具來說端口號是一個數字代碼。有一個習慣就是偵聽服務連接到他們自己固定的端口號上,以便他們能找到客戶端sockets.服務器socket監聽為他們提供服務的相關端口號。當他們允許給予一個客戶端socket連接時,他們創建一個獨立的socket連接,使用不同的專用的端口號。通過這個方法,能持續的監聽相關服務的端口號。

客戶端socket使用一個專用的本地端口號,就不用其他的socket去尋找它們。他們指定他們想連接的服務器端socket的端口號,這樣他們就能找到服務器應用程序。常常的,這個端口號是通過命名想連接的服務來間接指定的。

四、使用socket控件

C++Builder提供兩個socket控件,客戶端sockets和服務器sockets.他們允許你的網絡應用構成連接其他的機器和允許你通過這個連接來讀寫信息。與每個socket控件相關聯的是windows socket對象,它們在終端的的作用是一個實際的socket連接。socket控件使用windows socket對象去封裝windows socket API 調用,所以你的應用不用去關心連接建立的細節或管理socket信息。

如果你想利用windows socket API調用或自定義連接細節,socket控件提供了便利,你可以使用windows socket對象的properies,events和方法。

1.使用客戶端sockets

添加一個客戶端socket控件(TClientSocket)到你的form或data module 使你的應用成為一個TCP/IP客戶。客戶sockets允許你指定你想連接的服務器socket和你希望服務器提供的服務。一但你描述你想得到的連接,你可以使用客戶socket控件去完成連接服務。

每個客戶socket控件使用獨立的客戶windows socket對象(TClientWinSocket)去應答連接中的客戶終端。使用客戶sockets去:

A.指定想得到的服務

客戶socket控件有一個數字properties,允許你指定想連接的服務器系統和端口。你可以通過主機名來指定服務器系統,使用Host property。

如果你不知道主機名,或者你關心找到服務器的速度,你可以指定服務器系統的IP地址,通過使用 Address property。你必須指定IP地址和主機名中的一個。

如果你兩個都指定,客戶socket控件將使用主機名。除服務器系統外,你必須指定你的客戶socket將連接的在服務器系統上的端口。你能夠直接使用Port property來指定服務端口號。或者直接在Service property使用想得到的服務的名字。如果你指定端口號和服務名,客戶socket控件將使用服務名。

B.建立連接

一旦你在客戶socket控件中完成了設置描述你想連接的服務器的屬性,你就可以進行連接,通過調用Open方法。如果你想你的應用啟動時自動建立連接,在設計時設置Active property為true,通過使用Object Inspector來設置。

C.取得關於連接的信息

完成連接到服務器socket後,你可以使用與你的客戶socket控件相關的客戶windows socket object去取得關於連接的信息。使用Socket property去訪問client windows socket object。windows socket object 有一個properties,它能讓你確定在連接的兩端客戶和服務器使用的地址和端口號。

當使用一個windows socket API調用時,你可以使用SocketHandle property區獲得socket連接使用的handle。你可以使用Handle property去訪問windows,以便接收來自socket連接的信息。AsyncStyles property決定哪種信息類型是windows handle要接收的。

D.關閉連接

當你完成通訊想關閉socket 連接時,你能夠通過調用Close方法來關閉連接。連接可能要由服務器端來關閉。如果是這種情況,你將收到一個OnDisconnect 事件的通知。

2.使用服務器sockets

添加一個服務端socket控件(TServerSocket)到你的form或data module使你的應用成為一個TCP/IP服務器。服務器sockets允許你指定你想提供的服務或你想用來監聽客戶請求時使用的端口。你可以使用服務器socket控件去監聽和允許客戶連接請求。每個服務器socket控件使用一個單一的服務器windows socket Object(TServerWinSocket)去應答在服務器端監聽到的連接。它通常使用一個服務器客戶winodws socket Object(TServerClientWinSocket)應答在服務器端每個活動的,連接著得到允許服務的客戶socket。使用服務器sockets去:

A.指定端口

在你的服務器socket能夠監聽客戶請求之前,你必須指定一個端口給你的監聽服務。你可以使用Port property來指定這個端口。如果你的服務器應用提供一個標准的服務,這個服務使用一個習慣使用的相關聯的端口。你能夠使用Service property直接指定端口號。使用Service property是一個好的主意,能夠減少設置端口號時的錯誤。如果你既指定了Port property,又指定了Service property,服務socket將使用服務名。

B.監聽客戶請求

一旦你在server socket控件上設置好你的端口號,你就能夠通過在運行時通過調用Open方法來監聽一個連接。如果你希望你的應用程序能夠在啟動的時候自動監聽連接,在設計的時候通過使用Object Inspector設置Active 屬性為true。

C.連接到客戶端。

當監聽服務socket控件接收到一個客戶端連接請求時他們將自動接受這個請求。當你沒次收到通知時,OnClientConnetc事件將發生。

D.取得關於連接的信息

一但你的服務器socket打開了監聽連接,你能夠使用與你服務器socket控件相關聯的服務器windows socket object來取得關於連接的信息。使用Socket property去訪問server windows socket object.windows socket object有一個屬性能夠讓你找到關於所有活動的客戶socket連接這些客戶socket是你通過服務器socket控件允許連接的。使用Handle屬性去存取windows通過socket連接收到的信息。

每個活動的,連接到客戶應用是通過服務、客戶windows socket bject (TServerClientWinSocket)封裝的。你能夠通過server windows socket object的連接屬性來訪問所有的這些。這些server client windows socket object有些屬性讓你能夠決定哪些地址和端口號給連接的兩端--客戶和服務器socket使用。當你使用windows socket API調用時,可以使用SocketHandle屬性去獲得socket連接使用的handle。你能夠使用Handle屬性去訪問windows從socket連接處得來的信息。AsyncStyles屬性決定windows handle將接收哪種類型的信息。

E.關閉連接

當你決定關閉監聽連接時,調用Close方法。這將關閉所有打開著的,連接到客戶應用的連接,取消任何尚未同意的連接,接著關閉監聽連接以便你的服務socket控件不在接受任何新的連接。當客戶端關閉他們自己獨立的連接到你的server socket的連接時,你可以在OnClientDisconnect事件中得到訊息。

五、socket事件的應答

當使用sockets寫應用程序時,大多數工作發生在socket控件的handler事件中.當通過socket連接開始讀或寫時,OnRead和OnWrite事件在non-blocking client sockets中發生從而通知sockets.同樣的,服務器sockets(blocking or non-blocking)收到OnClientRead和OnClientWrite事件.

當服務器結束一個連接時,客戶scokets收到一個OnDisconnect事件.當客戶端結束一個連接時,服務器socket收到一個OnClientDisconnect事件.

另外,客戶端Sockets和服務器端socket從連接中收到一個錯誤信息時,都將產生有個錯誤事件.

錯誤事件:客戶sockets和服務器sockets通常會產生一個OnError事件,當他們從連接中收到一個錯誤信息的時候.你能夠寫一個OnError事件處理去響應這些錯誤信息.這個OnError事件處理提供傳送關於socket試圖做什麼的時候這個錯誤發生的信息,以及錯誤信息提供的錯誤代碼.你可以在OnError事件處理中對這個錯誤作出響應,並且把錯誤代碼改為0,以避免socket產生一個例外.

當開始和完成發生時,socket控件通常會收到一個事件號(number of events).如果你的應用程序需要改變socket開始操作的處理過程或通過連接開始讀或寫操作時,你將寫事件handlers去應答這些client events和server events.

A.client events

當一個客戶socket打開一個連接時,以下事件發生:

1.一個OnLookup事件最先發生,它試圖去定位server socket.在這裡你不能改變Host,Address,Port,Service屬性去改變你想定位的服務器.你能夠使用Socket屬性去訪問client windows socket object,並且使用它的SocketHandle屬性去調用windows API,以便改變socket的客戶屬性.例如,如果你想在客戶應用軟件中設置端口號,你必須在server client連接前做這件事.

2.windows socket設置和初始化事件通知.

3.當找到server socket時一個OnConnecting事件發生.在這事件中,windows Socket object可以利用的是通過socket屬性提供關於連接的另一端的服務socket的一些信息.這是獲得實際使用來連接的端口和IP地址的第一個機會,它可能不同於從監聽socket處同意連接時得到的端口或IP地址.

4.服務器同意連接請求,客戶端socket完成連接.

5.當一個連接得到確定後,一個OnConnect事件發生.如果你的socket立即開始通過連接讀或寫,就應寫一個OnConnect事件Handler去作這件事.

B.服務器端事件(server events)

服務器socket控件通過兩中方式連接:監聽連接和連接到客戶應用.服務器socket收到這兩個連接的所有事件.

監聽時事件

當構成監聽連接前,OnListen事件發生.在這個時候你能夠通過socket屬性獲得server windows socket object.你能夠使用它的SocketHandle屬性去改變socket,在socket打開監聽之前.例如,如果你想限定監聽服務使用的IP地址,你可以在這個OnListen事件Handler中做.

與客戶端連接的事件

當一個服務器socket同意一個客戶連接請求時,接下來的事件發生:

1.服務器socket產生一個OnGetSocket事件,通過windows socket handle傳送給連接的另一端的socket.如果你想提供自己定義的TServerClientWinSocket of descendant,你可以在OnGetSocket 事件 handler中建立,將被用來替代TServerClientWinSocket.

2.一個OnAccept事件發生,傳送新的TServerClientWinSocket對象給事件句柄.這是第一個要點,當你使用TServerClientWinSocket的屬性去獲得被連接中服務的那端的客戶的信息時.

3.如果服務類型是stThreadBlocking,一個OnGetThread事件發生.如果你想提供自己定義的TServerClientThread子類,你可以在OnGetThread事件句柄中建立一個,它將替代TServerClientThread.

4.如果服務類型是stThreadBlocking,一個ONThreadStart事件發生當這個線程(thread)開始執行時.如果你想執行任何初始化這個線程,或調用一些windows socket API在這線程開始通過連接讀和寫之前,應該使用OnThreadStart事件句柄.

5.當客戶端完成一個連接時,一個OnClientConnect事件發生.如果是non-blocking服務,你可能想開始通過socket連接在這端進行讀或寫操作.

六、通過socket連接進行讀和寫

通過socket連接到其他機器的原因是想通過這些連接來讀和寫信息.什麼信息是你要讀和寫的,或者當你想讀和寫時是依靠哪些socket連接的相關服務的.

通過sockets進行讀和寫可以是異步的,所以在你的網絡應用中不需要阻塞其他代碼的執行.這是調用non-blocking connection.你也同樣可以通過blocking connection,這時你的下一行代碼的執行必須等到讀或寫操作完成.

A.Non-blocking連接,讀和寫是異步的, 所以在你的網絡應用中不需要阻塞其他代碼的執行.建立一個Non-blocking連接:

1.在客戶socket中設置ClientType屬性為ctNonBlocking.

2.在服務器socket中設置ServerType屬性為stNonBlocking.

當連接是non-blocking時,連接的另一端企圖讀或寫時讀和寫事件將把這個信息通知你的socket.

讀和寫操作事件

Non-blocking sockets想通過連接讀或寫時,它會產生一個讀和寫操作事件通知你的socket.在客戶端sockets,你可以在OnRead或OnWrite事件句柄中對這些事件做出反應.在服務器端Scokets,可以在OnClientRead或OnClientWrite事件句柄中對這些事件做出反應.與socket連接相關聯的windows socket object在事件句柄的讀或寫中被當作一個參數.Windows socket object提供一個方法號(number of methods)以允許你通過連接讀或寫.

通過socket連接讀,使用ReceiveBuf或ReceiveText方法.在使用ReceiveBuf方法前,使用Receivelength方法去確定在連接的另一端socket准備發送的字節數(number of bytes).

通過socket連接寫,使用SendBuf,SendStream,或SendText方法.如果你通過socket發送信息後不在需要socket連接,你可以使用SendStreamThenDrop方法. SendStreamThenDrop在寫完所有的信息後將關閉Socket連接,它能夠從stream讀信息.如果你使用SendStream或SendStreamThenDrop方法,不要釋放Stream object, socket在連接結束後會自動釋放這個Stream.

注意:SendStreamThenDrop將關閉一個獨立的客戶連接服務,而不是監聽連接.

B.Blocking connections

當你使用的連接是Blocking時,你的Socket必須通過連接發起讀或寫操作,勝過被動的等待從socket連接發來的通知. 當你的連接末端的讀和寫操作發生改變時使用Blocking socket.對於客戶端sockets,設置ClientType屬性為ctBlocking 以便構成一個blocing connection.根據你的客戶端應用想完成什麼,你可能想建立一個執行線程去完成讀或寫.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved