程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 用DELPHI設計代理服務器程序(前面一貼,沒貼好,請原諒)

用DELPHI設計代理服務器程序(前面一貼,沒貼好,請原諒)

編輯:Delphi

用DELPHI設計代理服務器程序


摘自《天極網學習中心》 (文/萬雪勇)

  用Delphi開發串口通信軟件一般有兩種方法:一是利用Windows的通信API函數,另一種是采用Microsoft的MSComm控件。利用API編寫串口通信程序較為復雜,需要掌握大量通信知識,其優點是可實現的功能更強大,應用面更廣泛,更適合於編寫較為復雜的低層次通信程序。而利用MSComm控件則相對較簡單,該控件具有豐富的與串口通信密切相關的屬性及事件,提供了對串口的各種操作。
  一、MSComm控件的主要屬性及事件
  (1)CommPort:設置或返回串行端口號,缺省為1。
  (2)Setting:設置或返回串口通信參數,格式為“波特率,奇偶校驗位,數據位,停止位”。例如:MSComm1.Setting:=9600,n,8,1
  (3)PortOpen:打開或關閉串行端口,格式為:MSComm1.PortOpen:={True|False}
  (4)InBufferSize:設置或返回接收緩沖區的大小,缺省值為1024字節。
  (5)InBufferCount:返回接收緩沖區內等待讀取的字節數,可通過設置該屬性為0來清空接收緩沖區。
  (6)RThreshold:該屬性為一閥值,它確定當接收緩沖區內的字節個數達到或超過該值後就產生代碼為ComEvReceive的OnComm事件。
  (7)SThreshold:該屬性為一閥值,它確定當發送緩沖區內的字節個數少於該值後就產生代碼為ComEvSend的OnComm事件。
  (8)InputLen:設置或返回接收緩沖區內用Input讀入的字節數,設置該屬性為0表示Input讀取整個緩沖區的內容。
  (9)Input:從接收緩沖區讀取一串字符。
  (10)OutBufferSize:設置或返回發送緩沖區的大小,缺省值為512字節。
  (11)OutBufferCount:返回發送緩沖區內等待發送的字節數,可通過設置該屬性為0來清空緩沖區。
  (12)OutPut:向發送緩沖區傳送一串字符。
  如果在通信過程中發生錯誤或事件,就會引發OnComm事件,並由CommEvent屬性代碼反映錯誤類型,在通信程序的設計中可根據該屬性值來執行不同的操作。CommEvent屬性值及其含義如下:
  (1)ComEvSend:值為1,發送緩沖區的內容少於SThreshold指定的值。
  (2)ComEvReceive:值為2,接收緩沖區內字符數達到RThreshold指定的值。
  (3)ComEvFrame:值為1004,硬件檢測到幀錯誤。
  (4)ComEvRxOver:值為1008,接收緩沖區溢出。
  (5)ComEvTxFull:值為1010,發送緩沖區溢出。
  (6)ComEvRxParity:值為1009,奇偶校驗錯誤。
  (7)ComEvEOF:值為7,接收數據中出現文件尾(ASCII碼為26)字符。
  二、程序樣例
  在Delphi3.0中無法使用MSComm控件,筆者使用的是Delphi5.0。MSComm控件是VB中的OCX控件,首先需要將其添加到Delphi中,選擇菜單“Component”→“Import ActiveX Control”,在“Import ActiveX”頁內選擇“Microsoft Comm Control”,點擊“Install”安裝,安裝後在“ActiveX”組件板中出現MSComm圖標,即可被使用。有一點要注意,在Object Inspector中MSComm控件的Input和Output屬性是不可見的,但它們仍然存在,這兩個屬性的類型是OleVariant(Ole萬能變量)。
  下面是一接收程序的樣例(主要部分),大家可根據實際需要進行完善。
  在Form中放置一Memo控件用於顯示接收的數據,Combobox1選擇通信參數(Setting屬性值),Combobox2選擇串口(CommPort屬性值),按Button1開始接收數據,按Button2停止接收。
procedure TForm1.FormCreate(Sender: TObject);
begin
  Mscomm1.InBufferCount :=0; // 清空接收緩沖區
  Mscomm1.InputLen :=0; // Input讀取整個緩沖區內容
  Mscomm1.RThreshold :=1; // 每次接收到字符即產生OnComm事件
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
  Mscomm1.Settings :=ComboBox1.Text;
  if ComboBox2.Text =com1 then // 假設只考慮com1和com2兩種情況
    Mscomm1.CommPort :=1
  else
    Mscomm1.CommPort :=2;
  Mscomm1.PortOpen :=true; // 打開串口
  Mscomm1.DTREnable :=true; // 數據終端准備好
  Mscomm1.RTSEnable :=true; // 請求發送
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
  Mscomm1.PortOpen :=false; // 關閉串口
   Mscomm1.DTREnable :=false;
  Mscomm1.RTSEnable :=false;
end;
procedure TForm1.MSComm1Comm(Sender: TObject);
var recstr:Olevariant;
begin
  if Mscomm1.CommEvent = 2 then
  begin
   recstr := Mscomm1.Input ;
   Memo1.text := Memo1.Text + recstr;
  end;
end;
//主窗口建立
procedure TForm1.FormCreate(Sender: TObject);
begin
  Service_Enabled:=false;
  timer2.Enabled:=true;{窗口建立時,打開定時器}
end;
//窗口關閉時
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  timer1.Enabled:=false;{關閉定時器}
  if Service_Enabled then
    serversocket1.Active:=false;{退出程序時關閉服務}
end;
//退出程序按鈕
procedure TForm1.N01Click(Sender: TObject);
begin
  form1.Close;{退出程序}
end;
//開啟代理服務後
procedure TForm1.ServerSocket1Listen(Sender: TObject;Socket: TCustomWinSocket);
begin
  Service_Enabled:=true;{置正在服務標志}
  N11.Enabled:=false;
  N21.Enabled:=true;
end;
//被代理端連接到代理服務器後,建立一個會話,並與套接字綁定...
procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;Socket: TCustomWinSocket);
var i,j: integer;
begin
  j:=-1;
  for i:=1 to sessions do{查找是否有空白項}
    if not session[i-1].Used and not session[i-1].CSocket.active then
    begin
      j:=i-1;{有,分配它}
      session[j].Used:=true;{置為在用}
      break;
    end
    else
      if not session[i-1].Used and session[i-1].CSocket.active then
         session[i-1].CSocket.active:=false;
    if j=-1 then
    begin{無,新增一個}
      j:=sessions;
      inc(sessions);
      setlength(session,sessions);
      session[j].Used:=true;{置為在用}
      session[j].CSocket:=TClientSocket.Create(nil);
      session[j].CSocket.OnConnect:=ClientSocket1Connect;
      session[j].CSocket.OnDisconnect:=ClientSocket1Disconnect;
      session[j].CSocket.OnError:=ClientSocket1Error;
      session[j].CSocket.OnRead:=ClientSocket1Read;
      session[j].CSocket.OnWrite:=ClientSocket1Write;
      session[j].Lookingup:=false;
    end;
    session[j].SS_Handle:=socket.socketHandle; {保存句柄,實現綁定}
    session[j].Request:=false;{無請求}
    session[j].client_connected:=true;{客戶機已連接}
    session[j].remote_connected:=false;{遠程未連接}
    edit1.text:=inttostr(sessions);
end;
//被代理端斷開時
procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;Socket: TCustomWinSocket);
var i,j,k: integer;
begin
  for i:=1 to sessions do
    if (session[i-1].SS_Handle=socket.SocketHandle) and session[i-1].Used then
    begin
      session[i-1].client_connected:=false; {客戶機未連接}
      if session[i-1].remote_connected then
        session[i-1].CSocket.active:=false {假如遠程尚連接,斷開它}
      else
        session[i-1].Used:=false;{假如兩者都斷開,則置釋放資源標志}
      break;
    end;
    j:=sessions;
    k:=0;
    for i:=1 to j do{統計會話數組尾部有幾個未用項}
    begin
      if session[j-i].Used then break;
      inc(k);
    end;
    if k>0 then{修正會話數組,釋放尾部未用項}
   

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