WinSock編程的多線程式控制

Delphi中Socket的操作方式
Delphi分別使用TClientSocket元件和TServerSocket元件來操縱用戶端 Socket和伺服器段Socket的連接和通信。根據連接發起的方式以及本地 Socket要連接的目標,Socket之間的連接可以分為:用戶端連接、監聽連接以及伺服器端連接。
(1)所謂用戶端連接,是指由用戶端的 Socket提出連接請求,要連接的目標是伺服器端的Socket。為此,用戶端的Socket首先要描述它要連接的伺服器端Socket,主要是伺服器端Socket的位址和埠號,然後再定位所要連接的伺服器端Socket。找到以後,就向伺服器端Socket請求連接。此時,伺服器端的Socket未必正好處於準備好狀態。不過,伺服器端Socket會自動維護一個客戶請求佇列,通過這個佇列的優先順序,會在適當的時候通過請求回應的方式向用戶端Socket發出“允許連接”(Accept)的信號,這樣便在用戶端和伺服器端通過Sockets建立了連接!
(2)所謂監聽連接,是指伺服器端Socket並不定位具體的用戶端Socket,而是處於等待連接狀態,當伺服器端 Socket監聽到或者接收到用戶端Socket的連接請求的時候,它就回應用戶端Socket的請求建立一個新的Socket控制碼並與用戶端連接,而伺服器端Socket繼續處於監聽狀態,這樣可以與多個用戶端同時建立連接。
(3)所謂伺服器端連接,是指當伺服器端Socket接收到用戶端Socket的連接請求後,就把伺服器端Socket的描述發送給用戶端。一旦用戶端確認了此描述,就建立了連接!
3 線程式控制制的提出
一旦伺服器與用戶端建立了連接之後,就可以通過 Internet 傳輸資料和檔。但是在WinSock中存在兩種傳輸模式“阻塞”和“非阻塞”的概念。
一般都採用非阻塞方式。在用戶端,如果把 ClientType特性設置為ctNonBlocking,表示採用非阻塞方式進行連接。當伺服器端 Socket試圖進行讀/寫操作的時候,用戶端 Socket就會得到通知,即OnRead或者OnWrite事件。
對於伺服器端Socket來說,如果把ServerType特性設置為 StNonBlocking,表示採取非阻塞方式進行連接。當用戶端 Socket試圖進行讀/寫的時候,伺服器端Socket就會得到通知,即OnClientRead或者OnClientWrite事件。
與非阻塞方式不同的是,在阻塞方式下沒有諸如OnRead或者OnWrite等非同步事件。Socket必須主動去讀或者寫資料。在讀寫操作完成之前,其他代碼都無法執行,成為了純粹的獨佔使用方式,整個應用程式將處於等待狀態,大大降低應用程式的性能。
對於用戶端Socket來說,如果把 ClientType特性設置為ctBlocking,表示採取阻塞方式進行連接,為了盡可能的減少阻塞方式的負面影響,可以把所有涉及到讀寫的操作放在一個單獨的線程中,這樣可以使其他的線程可以繼續得到執行。
對於伺服器端 Socket來說,如果把ServerType設置為stThreadBlocking,表示採取阻塞方式進行連接。Delphi 中將為每一個阻塞方式的連接自動分配一個新的線程,這樣即使一個客戶正在進行讀寫操作,其他的客戶也不必等待。
4 在用戶端使用多線程技術
在阻塞模式下,為了盡可能的減少阻塞方式的副作用,可以把所有的涉及到讀寫操作放在一個單獨的線程種。為此,需要創建一個新的線程物件,然後重載它的Execute方法,線上程代碼中,我們通過TWinSockStream物件來進行讀寫操作。
Procedure TClientThread.Execute;
Var sStream: TWinSockStream;
sBuffer: string;
Begin
//建一個TWinSocketStream物件實例,設置連接超時
SSteam: = TWinSockStream.Create (ClientSocket.Socket, 60000);
Try //獲取和操作命令,直到連接斷開或者線程終止
While (not Terminate) and (ClientSocket.Active) do
begin
try
GetNextRequest (sBuffer);
//將請求寫回到Server
sStream.Write (sBuffer, Length (sBuffer) + 1);

Except
if not(Except Object is EAbort) then
//處理一些自定義的異常情況
Synchronize(HandleThreadException);
end;
end;
finally
sStream.Free;
end;
End;
5 在伺服器端使用多線程技術
在伺服器端,Delphi將自動為每一個阻塞方式的連接分配一個新的線程,並通過TServerClientThread來操縱每一個線程。所以不能通過物件庫中的嚮導來創建線程物件,只能手工建立一個TServerClientThread的派生類,然後重載ClientExcute方法。Procedure TServerThread.ClientExcute;
Var sStream:TWinSocketStream;
sBuffer:array[0..9] of char
Begin
//獲取和操作命令,直到連接斷開或者線程終止
While (not Terminate) and (ClientSocket.Active) do
Begin
Try
sStream:= TWinSocketStream.Create(ClientSocket.Socket,60000);
try //填充SBuffer陣列
FillChar(sBuffer,10,0);
//延遲時間60秒
If sStream.WaitForData(60000) then
Begin
If sStream.Read(sBuffer,10)=0 then
ClientSocket.Close;
……
End
Else ClientSocket.Close;
except
HandleException;
end;
Finally
sStream.Free;
end;
end;
End;
總結:通過用戶端和伺服器端的多線程式控制制,當我們需要對大信息量的資料處理的時候,尤為方便,而且能夠很大程度上提高網路資源的利用率。目前我們正在研究通過線程式控制制來對資料庫的查詢進行優化處理以及資料發送問題!

posted @ 2010-12-25 09:46  delphi中间件  阅读(391)  评论(0编辑  收藏  举报