Delph7中TcpClient和TcpServer用法分析


http://blog.csdn.net/quicmous/article/details/4263115

最近使用了Delphi7提供的TcpCLient和TcpServer兩個VCL控件,發現這兩個控件使用非常簡單,不像網上不少帖子說的那樣難用、性能差。

TcpClient和TcpServer沒有采用事件驅動的模式,而是采取了同步方法調用的策略(網上有帖子稱之為阻塞模式),大大簡化了編寫Sockets通訊程序的過程。如果我們還停留在事件驅動的思維習慣上,就會發現很難使用這兩個控件。

Delphi7提供了一個名為NetChat的演示程序,該程序展示了TcpClient和TcpServer的初步用法。

一、 數據的發送與接收

//數據發送代碼:
procedure TForm1.btnSendClick(Sender: TObject);
var
  I: Integer;
begin
  TcpClient1.RemoteHost := edtRemoteHost.Text; //服務器IP
  TcpClient1.RemotePort := edtRemotePort.Text; //服務器端口號
  try
    if TcpClient1.Connect then
      for I := 0 to memSend.Lines.Count - 1 do
      TcpClient1.Sendln(memSend.Lines[I]);
  finally
    TcpClient1.Disconnect;
  end;
end;

//在OnAccept事件中接收數據(此處作了簡化):
procedure TForm1.TcpServer1Accept(sender: TObject;
  ClientSocket: TCustomIpClient);
var
  s: string;
begin
  s := ClientSocket.Receiveln;
  while s <> '' do
  begin
    //此處對s做適當處理,代碼略。
    s := ClientSocket.Receiveln;
  end;
end;

 

TcpServer在接收到數據后,只產生一個OnAccept事件。在OnAccept時間響應函數中,我們循環調用ClientSocket參數的Receiveln方法接受數據。讓該方法返回空字符串時,意味着連接已經斷開

需要注意的是:
1.Receiveln方法在客戶端沒有傳送數據時一直處於等待狀態。
2.演示程序用s <> ''判斷連接是否斷開,下面我們可以看到其它判斷方法。

二、 TcpServer的OnAccept事件中的參數ClientSocket

OnAccept事件響應函數帶一個名為ClientSocket的參數,該參數是一個TCustomIpClient類型的對象。利用該參數可以方便我們訪問客戶端信息(客戶端IP、端口等),並管理連接。

前面我們看到可以利用Receiveln返回空值的條件判斷連接是否結束。如果希望實現超時斷開連接功能的話,可以采用ClientSocket對象的WaitForData方法,等待數據。該方法允許指定等待時間,方法聲明如下:

function WaitForData(TimeOut: Integer = 0): boolean;

可以調用ClientSocket的Disconnect方法在退出前斷開連接

三、 關於OnAccept多線程的問題

在同時收到多個客戶端信息時,OnAccept應該在內存存在多個線程實例。因此,在OnAccept的代碼,必須符合多線程設計原則。

Delphi的VCL庫和其它一些組件是面向單線程設計的。這表明對VCL控件等組件的調用,必須通過TThread類的Synchronize方法調用。在NetChat這個演示程序中,提供了相應的代碼供參考。更多資料請參考Delphi多線程編程的相關資料。

四、從服務器返回數據

如果需要從服務器返回數據的話,只需要在OnAccept中調用ClientSocket.Sendln方法即可。

客戶端需要做的就是在執行完TcpClient1.Sendln后,直接調用 TcpClient1.Receiveln即可。該方法會等待服務器傳回的信息。當然如果希望超時斷開的話,也可以調用WaitForData方法,判斷在給定時間內是否有數據返回。

四、 常見問題

問題:為什么TcpClient的OnReceive事件不響應服務器傳回的數據?

原因很簡單,OnReceive事件是由TcpClient的Receiveln等函數激發的,用於在Receiveln等函數接受到數據之前過濾數據用。

因此,如果你不調用TcpClient的Receiveln等函數,OnReceive事件就永遠不會被激發。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM