delphi TServersocket 数据转发器原理及实现代码

delphi TServersocket 数据转发器原理及实现代码

const
  MAX_BUF_SIZE=8192;          //8192 
  type
 //数据转发器数据结构
  PRepeatDataBuffer=^stRepeatDataBuffer;
  stRepeatDataBuffer=record   //转发数据缓冲区
    oh:stOrderHeader;       //数据包头定义
    targetSocket:TCustomWinSocket;    //转发目标socket
    buf:array[0..MAX_BUF_SIZE-1] of byte;    //数据缓冲区
  end;
//异步数据转发关键代码:
procedure TDM.ssData1ClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
  oh:stOrderHeader;//包头;
  pBuf:pRepeatDatabuffer;  //数据缓冲区结构
  requestLen,recvLen:integer;
begin
  recvLen:=socket.ReceiveLength;
  if(recvLen=0)then exit;
  if(socket.Data=nil)then      //未分配数据块
  begin
    socket.ReceiveBuf(oh,sizeof(oh)); //接收数据头
    if(not uOrder.VerifyOH(oh))then exit;  //检验包头
    getmem(pBuf,sizeof(stRepeatDatabuffer));  //分配 数据块;
    zeromemory(pBuf,sizeof(stRepeatDatabuffer));
    pBuf^.oh:=oh;
    socket.Data:=pBuf;                          //socket连接数据块
    if (oh.len=0) then exit;
    pBuf^.targetSocket:=getSocket(oh.pid,ssData1);   //查找转发目标socket
    if pBuf^.targetSocket=nil then  begin socket.Close;exit;end;
    pBuf^.targetSocket.SendBuf(oh,sizeof(stOrderHeader)); //发送包头
    recvLen:=recvLen-sizeof(stOrderHeader);
    if(recvLen=0)then exit;
  end else begin
    pBuf:=socket.Data;                          //数据块地址
  end;
  recvLen:=socket.ReceiveBuf(pBuf^.buf,MAX_BUF_SIZE);    //接收数据并转发
  if(recvLen=-1)then exit;
  if(pBuf^.targetSocket.Connected)then
  begin
    recvLen:=pBuf^.targetSocket.SendBuf(pBuf^.buf,recvLen);  //发送到目标socket
  end;
end;
//根据id查找socket
function TDM.getSocket(id:DWORD;ServerSocket:TServerSocket):TCustomWinSocket;
var
  i:integer;
  poh:POrderHeader;
begin
  result:=nil;
  for I := 0 to ServerSocket.Socket.ActiveConnections-1 do
  begin
    poh:=ServerSocket.Socket.Connections[i].Data;
    if(poh=nil)then continue;

    if(poh^.id=Id)then
    begin
      result:=ServerSocket.Socket.Connections[i];
      exit;
    end;
  end;
end;
//断开链接时释放缓冲区
procedure TDM.ssData1ClientDisconnect(Sender: TObject;Socket: TCustomWinSocket);
begin

  if socket.Data<>nil then
  begin
    freemem(socket.Data);
    socket.Data:=nil;
  end;
  fmain.LogMain('ssData1ClientDisconnect:'+socket.RemoteAddress);

end;
procedure TDM.ssData1ClientError(Sender: TObject; Socket: TCustomWinSocket;
  ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
  fMain.LogMain('ssData1ClientError:'+socket.RemoteAddress+':'+getSocketErr(ErrorEvent,ErrorCode));
  ErrorCode:=0;
end;
//----------------------------------------------------------------------------------------
function tdm.getSocketErr(ErrorEvent: TErrorEvent;ErrorCode:integer):string;
var
  sErrorCode,inf,sErrorEvent:string;
begin
  sErrorCode:='错误代码:'+inttostr(ErrorCode);
  if ErrorEvent=eeConnect then
  begin
    sErrorEvent:='链接失败!';
  end;
  if ErrorEvent=eeGeneral then
  begin
    sErrorEvent:='没法识别的错误!';
  end;
  if ErrorEvent=eeSend then
  begin
    sErrorEvent:='发送数据失败!';
  end;
    if ErrorEvent=eeReceive then
  begin
    sErrorEvent:='接受数据失败!';
  end;
    if ErrorEvent=eeDisconnect then
  begin
    //DisCon(socket);

    sErrorEvent:='关闭链接失败!';
  end;
    if ErrorEvent=eeAccept then
  begin
    sErrorEvent:='接受链接失败!';
  end;
  inf:=sErrorEvent+sErrorCode;
  result:=inf;
end;