⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mainsercli.pas

📁 delphi 代理服务器程序,通过实践操作
💻 PAS
字号:
unit MainSerCli;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ScktComp, Menus;

const
   CMax=1000;  //客户端最大连接数Gi<s:
type
        session_record=record
        Used: boolean; {会话记录是否可用}
        SS_Handle: integer; {代理服务器套接字句柄}
        CSocket: TClientSocket; {用于连接远程的套接字}
        Lookingup: boolean; {是否正在查找服务器}
        LookupTime: integer; {查找服务器时间}
        Request: boolean; {是否有请求}
        request_str: string; {请求数据块}
        client_connected: boolean; {客户机联机标志}
        remote_connected: boolean; {远程服务器连接标志}
 end;

type
  TMainSerCliFm = class(TForm)
    Button2: TButton;
    ServerSocket1: TServerSocket;
    ClientSocket1: TClientSocket;
    Button3: TButton;
    MainMenu1: TMainMenu;
    N1: TMenuItem;
    N3: TMenuItem;
    GroupBox1: TGroupBox;
    Memo1: TMemo;
    GroupBox2: TGroupBox;
    Memo2: TMemo;
    Button1: TButton;
    Button4: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Edit1: TEdit;
    procedure ServerSocket1ClientConnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ServerSocket1ClientDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ServerSocket1Listen(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure N3Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure ServerSocket1ClientRead(Sender: TObject;
      Socket: TCustomWinSocket);

    procedure ClientSocket1Connect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ClientSocket1Disconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ClientSocket1Write(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);

    procedure Button3Click(Sender: TObject);
    procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;
      ErrorEvent: TErrorEvent; var ErrorCode: Integer);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure ServerSocket1ClientError(Sender: TObject;
      Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
      var ErrorCode: Integer);
    procedure FormActivate(Sender: TObject);


  private
    { Private declarations }
  public
    { Public declarations }
    service_enabled: boolean;           {代理服务是否开启}
    sessions: integer;                  {会话数}
    session:array[0..CMax] of session_record;
    lookuptimeout: integer;           {连接超时值}
    invalidrequests: integer;
 end;

var
  MainSerCliFm: TMainSerCliFm;

implementation

uses SysInitFm, DataModuleFm;

{$R *.dfm}

procedure TMainSerCliFm.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 TMainSerCliFm.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 {修正会话数组,释放尾部未用项}
    begin
      sessions:=sessions-k;
 //     setlength(session,sessions);
    end;

end;

procedure TMainSerCliFm.ServerSocket1Listen(Sender: TObject;
  Socket: TCustomWinSocket);
begin
        Memo1.Text :='等待客户端连接...';
end;



procedure TMainSerCliFm.N3Click(Sender: TObject);
begin
      SysInitForm.ShowModal();
end;

procedure TMainSerCliFm.Button1Click(Sender: TObject);
var
localport:String;
begin

    localport:=DataModuleForm.ReadInifile('..\config\SYSINIT.ini','本地服务端口','PORT');
    if localport='' then
    begin
          showmessage('本地服务端口未设置');
          exit;
    end;
     ServerSocket1.Port:= strtoint(localport);

    try
      ServerSocket1.Open;
      Memo1.Text:='启动服务端服务成功'
    except
      showmessage('启动服务端服务失败');
    end;
end;

procedure TMainSerCliFm.Button4Click(Sender: TObject);
begin
 try
    ServerSocket1.Close;
    ClientSocket1.Close;
    Memo1.Text:='关闭服务端服务成功'
  except
    showmessage('关闭服务端服务失败');
  end;
end;

procedure TMainSerCliFm.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
host,port: string;
i,j: integer;
begin
    host:=DataModuleForm.ReadInifile('..\config\SYSINIT.ini','交通罚款中转服务器','IP');
    if host='' then
    begin
          showmessage('交通罚款中转服务器IP地址未设置');
          exit;
    end;

    port:=DataModuleForm.ReadInifile('..\config\SYSINIT.ini','交通罚款中转服务器','PORT');
    if port='' then
    begin
          showmessage('交通罚款中转服务器端口未设置');
          exit;
    end;

    for i:=1 to sessions do {判断是哪一个会话}
      if session[i-1].Used and (session[i-1].SS_Handle=Socket.sockethandle) then
      begin
        session[i-1].request_str:=Socket.ReceiveText; {保存请求数据}
        Memo1.Lines.Add(session[i-1].request_str);

        if not session[i-1].remote_connected then {假如远征尚未连接}
        begin
          session[i-1].Request:=true; {置请求数据就绪标志}
          session[i-1].CSocket.active:=false;
          session[i-1].CSocket.Host:=host; {设置远程主机地址}
          session[i-1].CSocket.Port:=strtoint(port); {设置端口}
          session[i-1].CSocket.active:=true;
          session[i-1].Lookingup:=true; {置标志}
          session[i-1].LookupTime:=0; {从0开始计时}
        end
        else
          session[i-1].CSocket.socket.sendtext(session[i-1].request_str);
      end;
end;


procedure TMainSerCliFm.ClientSocket1Connect(Sender: TObject;
  Socket: TCustomWinSocket);
var
i: integer;
begin
    for i:=1 to sessions do
    if (session[i-1].CSocket.socket.sockethandle=socket.SocketHandle) and session[i-1].Used then
    begin
      session[i-1].CSocket.tag:=socket.SocketHandle;
      session[i-1].remote_connected:=true; {置远程主机已连通标志}
      session[i-1].Lookingup:=false; {清标志}
      break;
    end;
end;

procedure TMainSerCliFm.ClientSocket1Disconnect(Sender: TObject;
  Socket: TCustomWinSocket);
var
i,j,k: integer;
begin
    for i:=1 to sessions do
      if (session[i-1].CSocket.tag=socket.SocketHandle) and session[i-1].Used then
      begin
        session[i-1].remote_connected:=false; {置为未连接}
        if not session[i-1].client_connected then
          session[i-1].Used:=false {假如客户机已断开,则置释放资源标志}
        else
        for k:=1 to serversocket1.Socket.ActiveConnections do
          if (serversocket1.Socket.Connections[k-1].SocketHandle=session[i-1].SS_Handle) and session[i-1].used then
          begin
            serversocket1.Socket.Connections[k-1].Close;
            break;
          end;
        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
  begin
    sessions:=sessions-k;
  //  setlength(session,sessions);
  end;

end;

procedure TMainSerCliFm.ClientSocket1Write(Sender: TObject;
  Socket: TCustomWinSocket);
var
i: integer;
begin
    for i:=1 to sessions do
    if (session[i-1].CSocket.tag=socket.SocketHandle) and session[i-1].Used then
      begin
      if session[i-1].Request then
      begin
      socket.SendText(session[i-1].request_str); {假如有请求,发送}
      session[i-1].Request:=false; {清标志}
      end;
      break;
    end;
end;


procedure TMainSerCliFm.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
var
i,j: integer;
rec_bytes: integer; {传回的数据块长度}
rec_Buffer: array[0..8193] of char; {传回的数据块缓冲区}
begin

  FillChar(rec_Buffer,sizeof(rec_Buffer),0);

  for i:=1 to sessions do
  if (session[i-1].CSocket.tag=socket.SocketHandle) and session[i-1].Used then
  begin
      rec_bytes:=socket.ReceiveBuf(rec_buffer,8192); {接收数据}
      for j:=1 to serversocket1.Socket.ActiveConnections do
      if serversocket1.Socket.Connections[j-1].SocketHandle=session[i-1].SS_Handle then
      begin
          serversocket1.Socket.Connections[j-1].SendBuf(rec_buffer,rec_bytes); {发送数据}
          Memo2.Lines.Add(rec_buffer);
          break;
      end;
  break;
end;
end;


procedure TMainSerCliFm.Button3Click(Sender: TObject);
begin
          ServerSocket1.Close;
          ClientSocket1.Close;
          MainSerCliFm.Close;
end;

procedure TMainSerCliFm.ClientSocket1Error(Sender: TObject;
  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
  var ErrorCode: Integer);
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
    begin
      sessions:=sessions-k;
 //     setlength(session,sessions);
    end;
    errorcode:=0;
end;

procedure TMainSerCliFm.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
         ServerSocket1.Close;
          ClientSocket1.Close;
end;

procedure TMainSerCliFm.ServerSocket1ClientError(Sender: TObject;
  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
  var ErrorCode: Integer);
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
      begin
      sessions:=sessions-k;
 //     setlength(session,sessions);
    end;
    errorcode:=0;
end;

procedure TMainSerCliFm.FormActivate(Sender: TObject);
begin
      sessions:=0;
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -