日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

TCP中间件_Delphi_client

發(fā)布時(shí)間:2023/11/29 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 TCP中间件_Delphi_client 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1、界面

  1.1、formMain.pas

    1.1.1、

object frmMain: TfrmMainLeft = 191Top = 103Width = 542Height = 466Caption = 'frmMain'Color = clBtnFaceFont.Charset = DEFAULT_CHARSETFont.Color = clWindowTextFont.Height = -11Font.Name = 'MS Sans Serif'Font.Style = []OldCreateOrder = FalsePosition = poDesktopCenterOnCreate = FormCreateDesignSize = (534439)PixelsPerInch = 96TextHeight = 13object Label1: TLabelLeft = 16Top = 8Width = 41Height = 13AutoSize = FalseCaption = 'IP : 'endobject Label2: TLabelLeft = 176Top = 8Width = 49Height = 13AutoSize = FalseCaption = 'Port : 'endobject btnSetIpPort: TButtonLeft = 16Top = 32Width = 75Height = 25Caption = '設(shè)置信息'TabOrder = 0OnClick = btnSetIpPortClickendobject Memo1: TMemoLeft = 16Top = 128Width = 497Height = 299Anchors = [akLeft, akTop, akRight, akBottom]Lines.Strings = ('Memo1')ScrollBars = ssBothTabOrder = 1endobject btnSend: TButtonLeft = 96Top = 32Width = 75Height = 25Caption = '發(fā)送消息'TabOrder = 2OnClick = btnSendClickendobject btnStatus: TButtonLeft = 176Top = 32Width = 75Height = 25Caption = 'skt狀態(tài)'TabOrder = 3OnClick = btnStatusClickendobject btnClearMemo: TButtonLeft = 256Top = 32Width = 89Height = 25Caption = '清空消息框'TabOrder = 4OnClick = btnClearMemoClickendobject btnAllClients: TButtonLeft = 208Top = 64Width = 137Height = 25Caption = '所有客戶端信息'TabOrder = 5OnClick = btnAllClientsClickendobject btnSocket: TButtonLeft = 16Top = 96Width = 153Height = 25Caption = '客戶端網(wǎng)絡(luò)信息'TabOrder = 6OnClick = btnSocketClickendobject edtAddress: TEditLeft = 16Top = 64Width = 185Height = 21TabOrder = 7Text = 'edtAddress'endobject btnBlock: TButtonLeft = 192Top = 96Width = 153Height = 25Caption = '客戶端內(nèi)存塊信息'TabOrder = 8OnClick = btnBlockClickendobject edtIP: TEditLeft = 40Top = 4Width = 121Height = 21TabOrder = 9Text = '192.168.1.233'endobject edtPort: TEditLeft = 216Top = 4Width = 89Height = 21TabOrder = 10Text = '9888'endobject btnFrmSQL: TButtonLeft = 432Top = 32Width = 75Height = 25Caption = 'btnFrmSQL'TabOrder = 11OnClick = btnFrmSQLClickend end

  1.2、formSQL.pas

    1.2.1、

object frmSQL: TfrmSQLLeft = 362Top = 105Width = 457Height = 480Caption = 'frmSQL'Color = clBtnFaceFont.Charset = DEFAULT_CHARSETFont.Color = clWindowTextFont.Height = -11Font.Name = 'MS Sans Serif'Font.Style = []OldCreateOrder = FalsePosition = poDesktopCenterDesignSize = (449453)PixelsPerInch = 96TextHeight = 13object Label1: TLabelLeft = 16Top = 14Width = 145Height = 13AutoSize = FalseCaption = 'SQL語(yǔ)句 : 'endobject lvSQL: TListViewLeft = 16Top = 96Width = 416Height = 345Anchors = [akLeft, akTop, akRight, akBottom]Columns = <>GridLines = TrueOwnerData = TrueReadOnly = TrueRowSelect = TrueTabOrder = 0ViewStyle = vsReportOnData = lvSQLDataendobject Button1: TButtonLeft = 359Top = 8Width = 75Height = 25Anchors = [akTop, akRight]Caption = 'Button1'TabOrder = 1OnClick = Button1Clickendobject edtSQL: TEditLeft = 80Top = 10Width = 264Height = 21Anchors = [akLeft, akTop, akRight]TabOrder = 2Text = 'select * from file_tbl where rownum<5'endobject btnBLOB: TButtonLeft = 16Top = 48Width = 75Height = 25Caption = 'btnBLOB'TabOrder = 3OnClick = btnBLOBClickend end

?

2、代碼:

  2.1、formMain.pas

unit formMain;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls,classDrTcp, Winsock2;typeTfrmMain = class(TForm)Memo1: TMemo;btnSetIpPort: TButton;btnSend: TButton;btnStatus: TButton;btnClearMemo: TButton;btnAllClients: TButton;btnSocket: TButton;edtAddress: TEdit;btnBlock: TButton;Label1: TLabel;edtIP: TEdit;Label2: TLabel;edtPort: TEdit;btnFrmSQL: TButton;procedure btnSetIpPortClick(Sender: TObject);procedure btnSendClick(Sender: TObject);procedure btnClearMemoClick(Sender: TObject);procedure btnStatusClick(Sender: TObject);procedure btnAllClientsClick(Sender: TObject);procedure FormCreate(Sender: TObject);procedure btnSocketClick(Sender: TObject);procedure btnBlockClick(Sender: TObject);procedure btnFrmSQLClick(Sender: TObject);publicpublicprocedure UnpackClients(_pc :PChar; _iLen :integer);procedure UnpackSocket(_pc :PChar; _iLen :integer);procedure UnpackBlock(_pc :PChar; _iLen :integer);end;varfrmMain: TfrmMain;implementationusesformSQL;{$R *.dfm}procedure TfrmMain.FormCreate(Sender: TObject); begin // edtIP.Text := '192.168.1.15'; end;procedure TfrmMain.btnSetIpPortClick(Sender: TObject); var iPort :Integer; begin//TdrTcpClient.SetIpPort('127.0.0.1', 9888);//TdrTcpClient.SetIpPort('192.168.1.15', 9888);//TdrTcpClient.SetIpPort('192.168.1.233', 9888);iPort := StrToIntDef(trim(edtPort.Text), 9888);TdrTcpClient.SetIpPort(Trim(edtIP.Text), iPort); end;procedure TfrmMain.btnSendClick(Sender: TObject); beginTdrTcpClient.SendSQL('select * from ccc'); end;procedure TfrmMain.btnStatusClick(Sender: TObject); beginMemo1.Lines.Add(IntToStr(TdrTcpClient.Status)); end;procedure TfrmMain.btnClearMemoClick(Sender: TObject); beginMemo1.Lines.Clear; end;procedure TfrmMain.UnpackClients(_pc: PChar; _iLen: integer); var iLen, iIdx :integer;str :string;ll :LONGLONG; beginMemo1.Lines.Add('所有客戶端的 IP/Port 信息 :');CopyMemory(@ll, @_pc[0], SizeOf(LONGLONG));Memo1.Lines.Add(' 當(dāng)前時(shí)間(ms) : '+inttostr(ll));iIdx := SizeOf(LONGLONG);Dec(_iLen, 8);while _iLen>0 dobeginCopyMemory(@ll, @_pc[iIdx], 8);Memo1.Lines.Add(' 時(shí)間(ms) : '+inttostr(ll));CopyMemory(@iLen, @_pc[iIdx+8], 4);SetLength(str, iLen);CopyMemory(@str[1], @_pc[iIdx+4+8], iLen);Inc(iIdx, 4+8+iLen);Memo1.Lines.Add(' '+str);Memo1.Lines.Add('');Dec(_iLen, 4+8+iLen);end;SetLength(str, 0); end;procedure TfrmMain.UnpackSocket(_pc: PChar; _iLen: integer); var strIpRes, strMacRes, strReq :string;iLenIpRes, iLenMacRes, iLenReq :Integer;iLenMsg :Integer;strMsg :string; beginCopyMemory(@iLenMsg, @_pc[0], 4);if (iLenMsg < 0) thenbeginiLenMsg := -iLenMsg;SetLength(strMsg, iLenMsg);CopyMemory(@strMsg[1], @_pc[4], iLenMsg);Memo1.Lines.Add('請(qǐng)求主機(jī)信息(未找到):');Memo1.Lines.Add(' '+strMsg);endelsebeginCopyMemory(@iLenIpRes, @_pc[4], 4);SetLength(strIpRes, iLenIpRes - 4);CopyMemory(@strIpRes[1], @_pc[8], iLenIpRes - 4);CopyMemory(@iLenMacRes, @_pc[4+iLenIpRes], 4);SetLength(strMacRes, iLenMacRes - 4);CopyMemory(@strMacRes[1], @_pc[4+iLenIpRes+4], iLenMacRes - 4);CopyMemory(@iLenReq, @_pc[4+iLenIpRes+iLenMacRes], 4);SetLength(strReq, iLenReq - 4);CopyMemory(@strReq[1], @_pc[4+iLenIpRes+iLenMacRes+4], iLenReq - 4);Memo1.Lines.Add('請(qǐng)求主機(jī)"'+strReq+'"的信息:');Memo1.Lines.Add(' IP : '+strIpRes);Memo1.Lines.Add(' Mac : '+strMacRes);end; end;procedure TfrmMain.UnpackBlock(_pc: PChar; _iLen: integer); var iTotalLen :Integer;iValidBeginOffset :Integer;iValidLen :Integer;dwType :DWORD;dwLastTick :DWORD;// *** iLenBlockMsg, iOffset, iIdx :Integer;iLenReq :Integer;strReq :string;dwTick :DWORD; beginCopyMemory(@iLenBlockMsg, @_pc[0], 4);CopyMemory(@dwTick, @_pc[4], 4);CopyMemory(@iLenReq, @_pc[iLenBlockMsg], 4);SetLength(strReq, iLenReq-4);CopyMemory(@strReq[1], @_pc[iLenBlockMsg+4], iLenReq-4);Memo1.Lines.Add('請(qǐng)求主機(jī)"'+strReq+'"的信息:'+inttostr(dwTick));Memo1.Lines.Add(' '+inttostr(dwTick)+' : '+inttostr(Length(strReq)));iIdx := 0;iOffset := 8;Dec(iLenBlockMsg, iOffset);while iLenBlockMsg > 0 dobeginInc(iIdx);CopyMemory(@iTotalLen, @_pc[iOffset+0], 4);CopyMemory(@iValidBeginOffset,@_pc[iOffset+4], 4);CopyMemory(@iValidLen, @_pc[iOffset+8], 4);CopyMemory(@dwType, @_pc[iOffset+12], 4);CopyMemory(@dwLastTick, @_pc[iOffset+16], 4);Memo1.Lines.Add(' 內(nèi)存塊('+inttostr(iIdx)+') :');Memo1.Lines.Add(' 總長(zhǎng) : ' +inttostr(iTotalLen));Memo1.Lines.Add(' (有效數(shù)據(jù))開始偏移 : '+inttostr(iValidBeginOffset));Memo1.Lines.Add(' (有效數(shù)據(jù))長(zhǎng)度 : ' +inttostr(iValidLen));Memo1.Lines.Add(' 用途 : 0x' +inttohex(dwType, 8));Memo1.Lines.Add(' 最后申請(qǐng)時(shí)間 : ' +inttostr(dwLastTick));Inc(iOffset, 20);Dec(iLenBlockMsg, 20);end; end;procedure TfrmMain.btnAllClientsClick(Sender: TObject); var pc :array[0..255] of Char;iPktLen, iPktIdx, iPktType :Integer; beging_callbackWnd.FfuncClients := UnpackClients;iPktLen := TCP_PACKET_HEADER_LEN;iPktIdx := 0;iPktType:= OP_TYPE_MANAGE_CLIENTS;CopyMemory(@pc[0], @iPktLen, 4);CopyMemory(@pc[4], @iPktIdx, 4);CopyMemory(@pc[8], @iPktType, 4);TdrTcpClient.SendBytes(@pc[0], iPktLen); end;procedure TfrmMain.btnSocketClick(Sender: TObject); var pc :array[0..255] of Char;iPktLen, iPktIdx, iPktType :Integer;strRemoteAddress :string;iLen :Integer; beginstrRemoteAddress := Trim(edtAddress.Text);g_callbackWnd.FfuncSocket := UnpackSocket;iPktLen := TCP_PACKET_HEADER_LEN + (4 + Length(strRemoteAddress));iPktIdx := 0;iPktType:= OP_TYPE_MANAGE_SOCKET_REQ;CopyMemory(@pc[0], @iPktLen, 4);CopyMemory(@pc[4], @iPktIdx, 4);CopyMemory(@pc[8], @iPktType, 4);// ***iLen := 4 + Length(strRemoteAddress);CopyMemory(@pc[12], @iLen, 4);CopyMemory(@pc[16], @strRemoteAddress[1], Length(strRemoteAddress));TdrTcpClient.SendBytes(@pc[0], iPktLen); end;procedure TfrmMain.btnBlockClick(Sender: TObject); var pc :array[0..255] of Char;iPktLen, iPktIdx, iPktType :Integer;strRemoteAddress :string;iLen :Integer; beginstrRemoteAddress := Trim(edtAddress.Text);g_callbackWnd.FfuncBlock := UnpackBlock;iPktLen := TCP_PACKET_HEADER_LEN + (4+Length(strRemoteAddress));iPktIdx := 0;iPktType:= OP_TYPE_MANAGE_BLOCK_REQ;CopyMemory(@pc[0], @iPktLen, 4);CopyMemory(@pc[4], @iPktIdx, 4);CopyMemory(@pc[8], @iPktType, 4);// ***iLen := 4 + Length(strRemoteAddress);CopyMemory(@pc[12], @iLen, 4);CopyMemory(@pc[16], @strRemoteAddress[1], Length(strRemoteAddress));TdrTcpClient.SendBytes(@pc[0], iPktLen); end;procedure TfrmMain.btnFrmSQLClick(Sender: TObject); beginfrmSQL.Show; end;end.

  2.2、formSQL.pas

unit formSQL;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, ComCtrls, StdCtrls,classDrTcp;typeTfrmSQL = class(TForm)lvSQL: TListView;Button1: TButton;edtSQL: TEdit;Label1: TLabel;btnBLOB: TButton;procedure Button1Click(Sender: TObject);procedure lvSQLData(Sender: TObject; Item: TListItem);procedure btnBLOBClick(Sender: TObject);privateFbuffer :TdrBuffer;procedure UnpackSQL(_buffer :TdrBuffer);publicFdataSet :TdrDataSet;FiColumnCnt :Integer;end;varfrmSQL: TfrmSQL;implementationusesformMain;{$R *.dfm}procedure TfrmSQL.Button1Click(Sender: TObject); var pc :array[0..255] of Char;iPktLen, iPktIdx, iPktType :Integer;strSql :string;iLenSQL :Integer; beginif (Fbuffer <> nil) thenbeging_bufferPool.ReleaseBlock(Fbuffer);Fbuffer := nil;end;strSql := Trim(edtSQL.Text);iLenSQL := Length(strSql);if iLenSQL = 0 thenbeginfrmMain.Memo1.Lines.Add('no sql');Exit;end;g_callbackWnd.FfuncSQL := UnpackSQL;Inc(iLenSQL, 4);iPktLen := TCP_PACKET_HEADER_LEN + iLenSQL;iPktIdx := 0;iPktType:= OP_TYPE_MANAGE_SQL;CopyMemory(@pc[0], @iPktLen, 4);CopyMemory(@pc[4], @iPktIdx, 4);CopyMemory(@pc[8], @iPktType, 4);// ***CopyMemory(@pc[TCP_PACKET_HEADER_LEN], @iLenSQL, 4);CopyMemory(@pc[TCP_PACKET_HEADER_LEN + 4], PChar(strSql), iLenSQL - 4);TdrTcpClient.SendBytes(@pc[0], iPktLen); end;procedure TfrmSQL.UnpackSQL(_buffer :TdrBuffer); var columnNew :TListColumn;i :Integer; beginif (Fbuffer <> nil) thenbeging_bufferPool.ReleaseBlock(Fbuffer);Fbuffer := nil;end;Fbuffer := _buffer;if not Assigned(FdataSet) thenFdataSet := TdrDataSet.Create;FdataSet.Unpack(@_buffer.Fpc[TCP_PACKET_HEADER_LEN], _buffer.FiValidLen - TCP_PACKET_HEADER_LEN);if (FdataSet.ColumnCount <= 0) thenExit;lvSQL.Columns.Clear;FiColumnCnt := FdataSet.ColumnCount;for i:=0 to FiColumnCnt-1 dobegincolumnNew := lvSQL.Columns.Add;columnNew.AutoSize := True;columnNew.Caption := FdataSet.GetFieldName(i);end;lvSQL.Items.Count := FdataSet.RowCount;//lvSQL.Refresh; lvSQL.Repaint; end;procedure TfrmSQL.lvSQLData(Sender: TObject; Item: TListItem); var iColIdx :Integer;rec :TdrRecord;wstr :WideString; beginif (FdataSet = nil) then Exit;if (FdataSet.RowCount <= 0) then Exit;for iColIdx:=0 to FiColumnCnt-1 dobeginrec := FdataSet.Rec[Item.Index, iColIdx];//wstr := rec.asString;//frmMain.Memo1.Lines.Add(IntToStr(Item.Index)+','+IntToStr(iColIdx)+' : '+IntToStr(Integer(rec.FpcRecord)));if (iColIdx = 0) thenItem.Caption := rec.asStringelseItem.SubItems.Add(rec.asString);end; end;procedure TfrmSQL.btnBLOBClick(Sender: TObject); var item :TListItem;rec :TdrRecord;pc :PChar;iLen :Integer; beginitem := lvSQL.Selected;frmMain.Memo1.Lines.Add('ListView select item index : '+IntToStr(item.Index));rec := FdataSet.Rec[item.Index, 3];rec.asByteArray(nil, iLen);frmMain.Memo1.Lines.Add(IntToStr(iLen)); end;end.

  2.3、classDrTcp.pas

unit classDrTcp;interfaceusesWindows, Classes, Winsock, SysUtils, Messages, Math;// Math和StrUtils里面都有 IfThen(...)函數(shù)constBUFFER_BLOCK = 1024 * 1024;TCP_PACKET_HEADER_LEN = 4 * 3;// 調(diào)試輸出信息WM_TCP_RECV = WM_USER + $1000;WM_LOG_CONSOLE = WM_USER + $1001;WM_TCP_PUSH = WM_USER + 1000;WM_TCP_CLIENTS = WM_USER + 1001;WM_CLIENT_SOCKET_MSG_REQ = WM_USER + 1002;WM_CLIENT_SOCKET_MSG_RES = WM_USER + 1003; WM_CLIENT_BLOCK_MSG_REQ = WM_USER + 1004;WM_CLIENT_BLOCK_MSG_RES = WM_USER + 1005;WM_MANAGE_SQL = WM_USER + 1006;// TCP數(shù)據(jù) 操作類型:高16位:高一級(jí)類型; 低16位:低一級(jí)類型// (正值)正常的 C/S之間的業(yè)務(wù)邏輯數(shù)據(jù)OP_TYPE_SQL = $00010000;OP_TYPE_PUSH = $00020000;OP_TYPE_HEARTBEAT = $00030000;// (負(fù)值)C/S之間的 管理數(shù)據(jù)OP_TYPE_MANAGE = $80000000;OP_TYPE_MANAGE_CLIENTS = $80000001; // c請(qǐng)求s,所有客戶端的socket信息(簡(jiǎn)單)OP_TYPE_MANAGE_SOCKET_REQ = $80000010; // c-->s,s-->c, 某個(gè)客戶端的詳細(xì)socket信息 (request) (搬運(yùn)工)OP_TYPE_MANAGE_SOCKET_RES = $80000020; // (response)(搬運(yùn)工)OP_TYPE_MANAGE_BLOCK_REQ = $80000030; // c-->s,s-->c, 某個(gè)客戶端的內(nèi)存block信息 (request) (搬運(yùn)工)OP_TYPE_MANAGE_BLOCK_RES = $80000040; // (response)(搬運(yùn)工)OP_TYPE_MANAGE_SQL = $80000002; // 我的SQL語(yǔ)句操作OP_TYPE_RECV = $90000000;constDR_LONGNVARCHAR = -16;DR_NCHAR = -15;DR_NVARCHAR = -9;DR_ROWID = -8;DR_BIT = -7;DR_TINYINT = -6;DR_BIGINT = -5;DR_LONGVARBINARY= -4;DR_VARBINARY = -3;DR_BINARY = -2;DR_LONGVARCHAR = -1;DR_NULL = 0;DR_CHAR = 1;DR_NUMERIC = 2;DR_DECIMAL = 3;DR_INTEGER = 4;DR_SMALLINT = 5;DR_FLOAT = 6;DR_REAL = 7;DR_DOUBLE= 8;DR_VARCHAR = 12;DR_BOOLEAN = 16;DR_DATALINK= 70;DR_DATE = 91;DR_TIME = 92;DR_TIMESTAMP = 93;DR_OTHER = 1111;DR_JAVA_OBJECT = 2000;DR_DISTINCT = 2001;DR_STRUCT = 2002;DR_ARRAY = 2003;DR_BLOB = 2004;DR_CLOB = 2005;DR_REF = 2006;DR_SQLXML = 2009;DR_NCLOB = 2011;//常量定義 ConstMAX_HOSTNAME_LEN = 128;MAX_DOMAIN_NAME_LEN = 128;MAX_SCOPE_ID_LEN = 256;MAX_ADAPTER_NAME_LENGTH = 256;MAX_ADAPTER_DESCRIPTION_LENGTH = 128;MAX_ADAPTER_ADDRESS_LENGTH = 8; //定義相關(guān)結(jié)構(gòu) TypeTIPAddressString = Array[0..4*4-1] of Char;PIPAddrString = ^TIPAddrString;TIPAddrString = RecordNext : PIPAddrString;IPAddress : TIPAddressString;IPMask : TIPAddressString;Context : Integer;end;PFixedInfo = ^TFixedInfo;TFixedInfo = Record { FIXED_INFO }HostName : Array[0..MAX_HOSTNAME_LEN+3] of Char;DomainName : Array[0..MAX_DOMAIN_NAME_LEN+3] of Char;CurrentDNSServer : PIPAddrString;DNSServerList : TIPAddrString;NodeType : Integer;ScopeId : Array[0..MAX_SCOPE_ID_LEN+3] of Char;EnableRouting : Integer;EnableProxy : Integer;EnableDNS : Integer;end;PIPAdapterInfo = ^TIPAdapterInfo;TIPAdapterInfo = Record { IP_ADAPTER_INFO }Next : PIPAdapterInfo;ComboIndex : Integer;AdapterName : Array[0..MAX_ADAPTER_NAME_LENGTH+3] of Char;Description : Array[0..MAX_ADAPTER_DESCRIPTION_LENGTH+3] of Char;AddressLength : Integer;Address : Array[1..MAX_ADAPTER_ADDRESS_LENGTH] of Byte;Index : Integer;_Type : Integer;DHCPEnabled : Integer;CurrentIPAddress : PIPAddrString;IPAddressList : TIPAddrString;GatewayList : TIPAddrString;DHCPServer : TIPAddrString;HaveWINS : Bool;PrimaryWINSServer : TIPAddrString;SecondaryWINSServer : TIPAddrString;LeaseObtained : Integer;LeaseExpires : Integer;end;function GetAdaptersInfo(_ai : PIPAdapterInfo; var _dwBufLen : DWORD) : Integer;StdCall;external 'iphlpapi.dll';typeTdrBuffer = classpublicFpc :PChar;FiTotalLen :Integer;FiValidBeginOffset :Integer;FiValidLen :Integer;FdwType :DWORD; // 用于什么的? TCP接收/SQL/PUSH/...?FdwLastTick :DWORD; // 最后一次被Aquire時(shí)候的GetTickCountend;TdrBufferPool = class//(TObject)publicconstructor create;destructor destroy;override;privateFlist :TList;FlistAll :TList;//... 這個(gè)沒弄,還有加鎖沒弄...FhEvent :THandle;//...privatefunction NewBlock(_iLen :Integer = 0) :TdrBuffer;function DelBlock(_buffer :TdrBuffer) :Integer;publicfunction AquireBlock(_dwType :DWORD; _iLen :Integer) :TdrBuffer;function ReleaseBlock(_buffer :TdrBuffer) :Integer;publicproperty ListAll :TList read FlistAll;end;// ***TdrRecvBuffer = class//(TObject)publicconstructor Create;destructor Destroy;override;privateFlist :TList;FiTotalLen :Integer;FiPktIdx :Integer; // TCP包 序號(hào) FhEvent :THandle;FiFirstPktLen :Integer;publicfunction BufferAuqire(out _pc :PChar; out _iLen :integer) :integer;function BufferReleaseAll :integer;function BufferRecv(_iRecv :Integer; _iBlockIdx: integer) :Integer;function BufferHandleAll :Integer;// 處理所有已經(jīng)接收到的 TCP包privatefunction BufferHandle :Integer;// 處理單個(gè) TCP包// ***private// 從接收到的緩沖區(qū)里面 得到TCP包頭的信息function TcpPktHeader(out _iPktLen, _iPktIdx, _iPktType :Integer) :Integer; // 始終默認(rèn)是 [0]的緩沖區(qū)塊// 從TCP包頭的信息中,判斷 我們是否需要這個(gè)TCP包(0:不需要; >0:需要; <0:出錯(cuò)信息)function TcpPktIsNeed(_iPktIdx, _iPktType :integer):Integer;procedure TcpPktDispatch(_buffer :TdrBuffer);end;// ***TdrTcpClient = class(TThread)publicFiErrorNo :Integer;FiStatus :integer; // 線程的狀態(tài)(0:初始狀態(tài); 1:運(yùn)行中; -1:結(jié)束)publicFskt :TSocket;privatefunction RecvTimeoutSet :Integer;function RecvTimeoutCancel :Integer;function Recv01() :Integer;protectedprocedure Execute; override;publicfunction Send01(_pbyte :PByte; _iLen :integer) :Integer;publicclass procedure SetIpPort(_strDestIp :string; _iDestPort :integer);class function Conn :Integer;class procedure SendSQL(_str :string);class procedure SendBytes(_pc :PChar; _iLen :Integer);class function ConnectDest :TSocket;class function Status :Integer;class procedure SendHeartBeat;end;// ***TdrDataSet = class;TdrRecord = classpublicconstructor Create(_dataset :TdrDataSet; _iRowIdx, _iColumnIdx :Integer);procedure FenXi;privateFdataset :TdrDataSet;FiRowIdx, FiColumnIdx :Integer;FpcRecord :PChar; // 指向某個(gè)Record的指針publicfunction asByteArray(_pByte :PByte; out _iLen :Integer) :Integer;function asInteger :Integer;function asSingle :Single;function asDouble :Double;function asString :string;privatefunction GetFieldType :Integer;function GetFieldTypeName :string;function GetFieldName :string;publicproperty FieldType :Integer read GetFieldType;property FieldTypeName :string read GetFieldTypeName;property FieldName :string read GetFieldName;end;TdrDataSet = classpublicfunction Unpack(_pc :PChar; _iLen :Integer) :integer;privateFpcBuf :PChar;FiBufLen :Integer; // 緩沖區(qū)中 有效數(shù)據(jù)的長(zhǎng)度FaryColumnType :array of Integer;FaryColumnName :array of string;FaryaryRecord :array of array of Integer; // 指向各個(gè)Record的指針publicfunction GetFieldType(_iColumnIdx :integer) :Integer;function GetFieldTypeName(_iColumnIdx :integer) :string;function GetFieldName(_iColumnIdx :integer) :string;privateFfield :TdrRecord; // 這個(gè)屬性有且只有一個(gè)publicfunction GetRecord(_iRowIdx, _iColumnIdx :integer):TdrRecord;property Rec[_iRow, _iCol :Integer] :TdrRecord read GetRecord;publicfunction GetRowCount :Integer;function GetColumnCount :Integer;property RowCount: integer read GetRowCount;property ColumnCount: integer read GetColumnCount;end;// ***TfuncPush = procedure(_pc :PChar; _iLen :integer) of Object;TfuncCallback = procedure(_pc :PChar; _iLen :integer) of Object;TfuncCallback_Buf = procedure(_buffer :TdrBuffer) of Object;TcallbackWnd = classpublicconstructor Create;publicFhWnd :HWND;FdwErrNo :DWORD;privateprocedure CreateWindow;public // 打包 信息function PackSocket(_pc :PChar; _iLen :integer) :integer;procedure PackBlock(_pc :PChar; _iLen :integer);publicFfuncPush :TfuncPush;FfuncClients :TfuncCallback; // 拆包 信息 FfuncSocket :TfuncCallback;FfuncBlock :TfuncCallback;FfuncSQL :TfuncCallback_Buf;end;function ProcWindow(_hWnd :HWND; _uMsg :UINT; _wParam :WPARAM; _lParam :LPARAM):longint;stdcall;function ErrorNo2Str(_dwErrNo :DWORD):string;procedure BufferBlockUsage(_iOpType :Integer; var _str :string);varg_callbackWnd :TcallbackWnd = nil; // 需要 自己新建g_bufferPool :TdrBufferPool = nil; // 需要 自己新建implementationusesformMain;varg_drRecvBuffer :TdrRecvBuffer = nil;// 需要 自己新建g_tcpClient :TdrTcpClient = nil; // 需要 自己新建(動(dòng)態(tài)創(chuàng)建,不是在initialization下面創(chuàng)建)g_bufferSql :TdrBuffer = nil;//g_bufferPush :TdrBuffer = nil; // ***g_strDestIp :string;g_iDestPort :integer;//g_tcpClient :TdrTcpClient = nil; // 需要 自己新建(動(dòng)態(tài)創(chuàng)建,不是在initialization下面創(chuàng)建)// ***procedure LogConsole(_str :string); var pc :PChar;iLen :Integer; beginiLen := Length(_str);GetMem(pc, iLen);PostMessage(g_callbackWnd.FhWnd, WM_LOG_CONSOLE, WParam(iLen), LParam(pc)); end;function LogFile(_str :string) :integer; var hFile :THandle;strFileName :string;dwWritten :DWORD;lb :LongBool; beginResult := 0;strFileName := ParamStr(0)+'.'+FormatDateTime('yyyymmdd', now)+'.log';hFile := CreateFile(PChar(strFileName), GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_NEW, 0, 0);if (hFile = INVALID_HANDLE_VALUE) thenbeginResult := GetLastError;Exit;end;lb := Windows.SetEndOfFile(hFile);if (not lb) thenbeginResult := GetLastError;CloseHandle(hFile);Exit;end;dwWritten := 0;lb := Windows.WriteFile(hFile, _str[1], Length(_str), dwWritten, nil);if (not lb) thenbeginResult := GetLastError;CloseHandle(hFile);Exit;end;CloseHandle(hFile); end;function FieldTypeName_f(_iFieldType :Integer; var _strFieldTypeName :string) :Integer; begincase _iFieldType ofDR_LONGNVARCHAR : _strFieldTypeName := 'DR_LONGNVARCHAR';DR_NCHAR : _strFieldTypeName := 'DR_NCHAR';DR_NVARCHAR : _strFieldTypeName := 'DR_NVARCHAR';DR_ROWID : _strFieldTypeName := 'DR_ROWID';DR_BIT : _strFieldTypeName := 'DR_BIT';DR_TINYINT : _strFieldTypeName := 'DR_TINYINT';DR_BIGINT : _strFieldTypeName := 'DR_BIGINT';DR_LONGVARBINARY : _strFieldTypeName := 'DR_LONGVARBINARY';DR_VARBINARY : _strFieldTypeName := 'DR_VARBINARY';DR_BINARY : _strFieldTypeName := 'DR_BINARY';DR_LONGVARCHAR : _strFieldTypeName := 'DR_LONGVARCHAR';DR_NULL : _strFieldTypeName := 'DR_NULL';DR_CHAR : _strFieldTypeName := 'DR_CHAR';DR_NUMERIC : _strFieldTypeName := 'DR_NUMERIC';DR_DECIMAL : _strFieldTypeName := 'DR_DECIMAL';DR_INTEGER : _strFieldTypeName := 'DR_INTEGER';DR_SMALLINT : _strFieldTypeName := 'DR_SMALLINT';DR_FLOAT : _strFieldTypeName := 'DR_FLOAT';DR_REAL : _strFieldTypeName := 'DR_REAL';DR_DOUBLE : _strFieldTypeName := 'DR_DOUBLE';DR_VARCHAR : _strFieldTypeName := 'DR_VARCHAR';DR_BOOLEAN : _strFieldTypeName := 'DR_BOOLEAN';DR_DATALINK : _strFieldTypeName := 'DR_DATALINK';DR_DATE : _strFieldTypeName := 'DR_DATE';DR_TIME : _strFieldTypeName := 'DR_TIME';DR_TIMESTAMP : _strFieldTypeName := 'DR_TIMESTAMP';DR_OTHER : _strFieldTypeName := 'DR_OTHER';DR_JAVA_OBJECT : _strFieldTypeName := 'DR_JAVA_OBJECT';DR_DISTINCT : _strFieldTypeName := 'DR_DISTINCT';DR_STRUCT : _strFieldTypeName := 'DR_STRUCT';DR_ARRAY : _strFieldTypeName := 'DR_ARRAY';DR_BLOB : _strFieldTypeName := 'DR_BLOB';DR_CLOB : _strFieldTypeName := 'DR_CLOB';DR_REF : _strFieldTypeName := 'DR_REF';DR_SQLXML : _strFieldTypeName := 'DR_SQLXML';DR_NCLOB : _strFieldTypeName := 'DR_NCLOB';else_strFieldTypeName := 'Unknown('+inttostr(_iFieldType)+')';end; end;procedure GetMacByIP(_iIp :integer; var _strMac :string); var adapterInfo, pInfo : PIPAdapterInfo;dwSize : DWORD;iRes : Integer;ipAddrStr :TIPAddrString;pIpAddrStr :PIPAddrString;i :Integer;iIp :Integer;bFind :Boolean; beginbFind := false;dwSize := 0;GetAdaptersInfo(nil, dwSize);GetMem(adapterInfo, dwSize);iRes := GetAdaptersInfo(adapterInfo, dwSize);If (iRes <> ERROR_SUCCESS) ThenbeginMessageBoxA(0,'獲取IP信息失敗', '錯(cuò)誤', MB_OK or MB_ICONERROR);exit;end;pInfo := adapterInfo;repeat// IP地址ipAddrStr := pInfo.IPAddressList;iIp := inet_addr(ipAddrStr.IPAddress);if (_iIp = iIp) thenbeginbFind := True;_strMac := '';for i:=1 to pInfo.AddressLength dobegin_strMac := _strMac + IntToHex(pInfo.Address[i], 2);if (i <> pInfo.AddressLength) then_strMac := _strMac + ':';end;Break;end;pIpAddrStr := ipAddrStr.Next;while pIpAddrStr<>nil dobeginiIp := inet_addr(ipAddrStr.IPAddress);if (_iIp = iIp) thenbeginbFind := True;_strMac := '';for i:=1 to pInfo.AddressLength dobegin_strMac := _strMac + IntToHex(pInfo.Address[i], 2);if (i <> pInfo.AddressLength) then_strMac := _strMac + ':';end;Break;end;pIpAddrStr := pIpAddrStr.Next;end;if (bFind) then Break;pInfo := pInfo^.Next;until (pInfo = nil);FreeMem(adapterInfo); end;procedure BufferBlockUsage(_iOpType :Integer; var _str :string); beginif (_iOpType = OP_TYPE_SQL) then_str := 'SQL語(yǔ)句'else if (_iOpType = OP_TYPE_PUSH) then_str := 'TCP推送'else if (_iOpType = OP_TYPE_MANAGE) then_str := '管理數(shù)據(jù)'else if (_iOpType = OP_TYPE_MANAGE_CLIENTS) then_str := '管理(所有客戶端IP/Port)'else if (_iOpType = OP_TYPE_MANAGE_SOCKET_RES) then_str := '管理(某客戶端socket信息)'else if (_iOpType = OP_TYPE_MANAGE_BLOCK_RES) then_str := '管理(某客戶端內(nèi)存塊信息)'else if (_iOpType = OP_TYPE_RECV) then_str := 'TCP接收緩沖'; end;function MAKELANGID(_p, _s :word) :DWORD; beginResult := (_s shl 10) or (_p); end;function ErrorNo2Str(_dwErrNo :DWORD):string; constLANG_NEUTRAL = $0;SUBLANG_DEFAULT = $01; var buf :array[0..255] of Char; beginZeroMemory(@buf[0], Length(buf));Windows.FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_IGNORE_INSERTS,nil,_dwErrNo, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),buf,Length(buf),nil);Result := buf; end;{ TdrBufferPool }constructor TdrBufferPool.create; begin//inherited Create;Flist := TList.Create;FlistAll := TList.Create;FhEvent := CreateEvent(nil, False, true, nil); end;destructor TdrBufferPool.destroy;//override; beginif Assigned(Flist) thenFlist.Free;inherited; end;function TdrBufferPool.NewBlock(_iLen: Integer): TdrBuffer; var iYuShu :Integer; beginiYuShu := _iLen mod BUFFER_BLOCK;Result := TdrBuffer.Create;if (_iLen<>0)and(iYuShu = 0) thenResult.FiTotalLen := _iLenelseResult.FiTotalLen := (_iLen div BUFFER_BLOCK + 1) * BUFFER_BLOCK;GetMem(Result.Fpc, Result.FiTotalLen);Result.FiValidBeginOffset := 0;Result.FiValidLen := 0;FlistAll.Add(Result); end;function TdrBufferPool.DelBlock(_buffer :TdrBuffer) :Integer; var iIdx :Integer; beginResult := 0;iIdx := FlistAll.IndexOf(_buffer);FlistAll.Delete(iIdx);if (iIdx = -1) thenResult := -1; end;function TdrBufferPool.AquireBlock(_dwType :DWORD; _iLen: Integer): TdrBuffer; var iAquireLen, i, iIdx, iYuShu :Integer;buffer :TdrBuffer; beginResult := nil;WaitForSingleObject(FhEvent, INFINITE);tryif (Flist.Count = 0) thenResult := NewBlock(_iLen)elsebeginiIdx := -1;iYuShu := _iLen mod BUFFER_BLOCK;if (_iLen<>0)and(iYuShu = 0) theniAquireLen := _iLenelseiAquireLen := (_iLen div BUFFER_BLOCK + 1) * BUFFER_BLOCK;for i:=0 to Flist.Count-1 dobeginbuffer := TdrBuffer(Flist.Items[i]);if iAquireLen <= buffer.FiTotalLen thenbeginiIdx := i;break;end;end;if (iIdx = -1) thenResult := NewBlock(_iLen)elsebeginResult := TdrBuffer(Flist.Items[iIdx]);Flist.Delete(iIdx);end;Result.FiValidBeginOffset := 0;Result.FiValidLen := 0;end;Result.FdwType := _dwType;PostMessage(g_callbackWnd.FhWnd, WM_TCP_RECV, 1, _dwType);Result.FdwLastTick := GetTickCount;finallySetEvent(FhEvent);end; end;function TdrBufferPool.ReleaseBlock(_buffer: TdrBuffer): Integer; constBUFFER_BLOCK_MAX_LEN = 1024 * 1024 * 500; // >=這個(gè)數(shù)的內(nèi)存,采取直接釋放內(nèi)存緩沖區(qū)的操作方式 var i :Integer;buffer0, buffer1 :TdrBuffer; beginPostMessage(g_callbackWnd.FhWnd, WM_TCP_RECV, 2, _buffer.FdwType);_buffer.FdwType := 0;Result := 0;WaitForSingleObject(FhEvent, INFINITE);tryif (_buffer.FiTotalLen >= BUFFER_BLOCK_MAX_LEN) then // >=這個(gè)數(shù)的內(nèi)存,采取直接釋放內(nèi)存緩沖區(qū)的操作方式beginDelBlock(_buffer);FreeMem(_buffer.Fpc, _buffer.FiTotalLen);_buffer.Free;Exit;end;if (Flist.Count = 0) thenbeginFlist.Add(_buffer);Exit;end;buffer0 := TdrBuffer(Flist.Items[0]);if (_buffer.FiTotalLen <= buffer0.FiTotalLen) thenbeginFlist.Insert(0, _buffer);Exit;endelsebeginfor i:=1 to Flist.Count-1 dobeginbuffer0 := TdrBuffer(Flist.Items[i-1]);buffer1 := TdrBuffer(Flist.Items[i]);if (_buffer.FiTotalLen > buffer0.FiTotalLen)and(_buffer.FiTotalLen <= buffer1.FiTotalLen) thenbeginFlist.Insert(i, _buffer);Exit;end;end;Flist.Add(_buffer);end;finallySetEvent(FhEvent);end; end;{ TdrRecvBuffer }constructor TdrRecvBuffer.Create; beginFlist := TList.Create;FhEvent := CreateEvent(nil, False, false, nil); end;destructor TdrRecvBuffer.destroy;//override; beginif Assigned(Flist) thenFlist.Free;if (FhEvent<>0) thenCloseHandle(FhEvent);inherited; end;function TdrRecvBuffer.BufferAuqire(out _pc: PChar; out _iLen: integer): integer; var buffer, bufferNew :TdrBuffer;iCnt1, iCntUsed :Integer; beginResult := -1;if (Flist.Count = 0) thenbeginbufferNew := g_bufferPool.AquireBlock(OP_TYPE_RECV, 0);Flist.Add(bufferNew);Result := Flist.Count - 1;_pc := bufferNew.Fpc;_iLen := bufferNew.FiTotalLen;endelsebeginbuffer := TdrBuffer(Flist.Items[Flist.Count - 1]);if (buffer.FiValidBeginOffset + buffer.FiValidLen) > buffer.FiTotalLen thenraise Exception.CreateFmt('TdrRecvBuffer.BufferAuqire 緩沖區(qū)錯(cuò)誤(1) : %d, %d, %d',[buffer.FiValidBeginOffset, buffer.FiValidLen, buffer.FiTotalLen])else if (buffer.FiValidBeginOffset + buffer.FiValidLen) = buffer.FiTotalLen thenbeginbufferNew := g_bufferPool.AquireBlock(OP_TYPE_RECV, 0);Flist.Add(bufferNew);Result := Flist.Count - 1;_pc := bufferNew.Fpc;_iLen := bufferNew.FiTotalLen;endelse// if (buffer.FiValidBeginOffset + buffer.FiValidLen) < buffer.FiTotalLen thenbeginiCntUsed := buffer.FiValidBeginOffset + buffer.FiValidLen;_pc := @buffer.Fpc[iCntUsed];_iLen := buffer.FiTotalLen - iCntUsed;Result := Flist.Count - 1;end;end; end;function TdrRecvBuffer.BufferReleaseAll :integer; beginwhile Flist.Count > 0 dobeging_bufferPool.ReleaseBlock(TdrBuffer(Flist.Items[0]));Flist.Delete(0);end; end;function TdrRecvBuffer.BufferRecv(_iRecv: Integer; _iBlockIdx: integer): Integer; var iCntUsed :Integer;buffer :TdrBuffer; beginResult := 0;Inc(FiTotalLen, _iRecv);buffer := TdrBuffer(Flist.Items[_iBlockIdx]);Inc(buffer.FiValidLen, _iRecv);if (buffer.FiValidBeginOffset + buffer.FiValidLen) > buffer.FiTotalLen thenraise Exception.CreateFmt('TdrRecvBuffer.BufferRecv 緩沖區(qū)錯(cuò)誤(1) : %d, %d, %d',[buffer.FiValidBeginOffset, buffer.FiValidLen, buffer.FiTotalLen]); end;function TdrRecvBuffer.BufferHandle: Integer; // 處理單個(gè) TCP包 var bufferCopy, buffer :TdrBuffer;iRtn, iPktIsNeed :Integer;iPktLen, iPktIdx, iPktType :Integer;iPktLen01 :Integer;iBlockIdx, iBlockDropEndIdx :Integer;iCopyOffset, i, iCopyLen :Integer;bNeedBreak :Boolean; beginResult := 0;if (FiTotalLen < TCP_PACKET_HEADER_LEN) then // 一個(gè)TCP包都沒有接收完畢beginResult := 1;Exit;end;if (FiFirstPktLen <> 0) and (FiTotalLen < FiFirstPktLen) thenbeginResult := 2;Exit;end;iRtn := TcpPktHeader(iPktLen, iPktIdx, iPktType);FiFirstPktLen := iPktLen;if (FiTotalLen < iPktLen) then // 一個(gè)TCP包都沒有接收完畢beginResult := 3;Exit;end;FiFirstPktLen := 0;iPktIsNeed := TcpPktIsNeed(iPktIdx, iPktType);// *** (1) *** 緩沖區(qū)的分配/獲取bufferCopy := nil;if (iPktIsNeed > 0) thenbufferCopy := g_bufferPool.AquireBlock(iPktType, iPktLen);// *** (2) *** 緩沖區(qū)內(nèi)容填充iCopyOffset := 0;iBlockIdx := 0;iPktLen01 := iPktLen;iBlockDropEndIdx := -1;while (iPktLen01 > 0) dobeginbNeedBreak := false;if (iBlockIdx >= Flist.Count) thenraise Exception.CreateFmt('TdrRecvBuffer.BufferHandle 緩沖區(qū)錯(cuò)誤(1) : %d, %d', [iBlockIdx, Flist.Count]);buffer := TdrBuffer(Flist.Items[iBlockIdx]);if (buffer.FiValidBeginOffset + buffer.FiValidLen) > buffer.FiTotalLen thenraise Exception.CreateFmt('TdrRecvBuffer.BufferHandle 緩沖區(qū)錯(cuò)誤(2) : %d, %d, %d, %d',[iBlockIdx, buffer.FiValidBeginOffset, buffer.FiValidLen, buffer.FiTotalLen])else if (buffer.FiValidBeginOffset + buffer.FiValidLen) = buffer.FiTotalLen thenbeginif iBlockDropEndIdx <> (iBlockIdx-1) thenraise Exception.CreateFmt('TdrRecvBuffer.BufferHandle 緩沖區(qū)錯(cuò)誤(3) : %d, %d, %d', [iBlockIdx, iBlockDropEndIdx, iBlockIdx]);iBlockDropEndIdx := iBlockIdx;endelse// if (buffer.FiValidBeginOffset + buffer.FiValidLen) < buffer.FiTotalLen thenbNeedBreak := True;if (not bNeedBreak) thenbegin // 不是 某TCP包中的最后一塊內(nèi)存塊的話,內(nèi)存塊的尾端肯定是占滿的if (buffer.FiValidBeginOffset + buffer.FiValidLen) <> buffer.FiTotalLen thenraise Exception.CreateFmt('TdrRecvBuffer.BufferHandle 緩沖區(qū)錯(cuò)誤(4) : %d, %d, %d, %d',[iBlockIdx, buffer.FiValidBeginOffset, buffer.FiValidLen, buffer.FiTotalLen]);end;// 緩沖區(qū)數(shù)據(jù) 復(fù)制// 三部曲:(1)計(jì)算iCopyLen (2)CopyMemory (3)計(jì)算3個(gè)數(shù)值iCopyLen := 0;if (iBlockIdx = 0) thenbeginiCopyLen := Math.IfThen(iPktLen01 > buffer.FiValidLen, buffer.FiValidLen, iPktLen01);if (bufferCopy <> nil) thenCopyMemory(@bufferCopy.Fpc[iCopyOffset], @buffer.Fpc[buffer.FiValidBeginOffset], iCopyLen);Dec(iPktLen01, iCopyLen);Inc(buffer.FiValidBeginOffset, iCopyLen); // 緩沖區(qū)指針移動(dòng) Dec(buffer.FiValidLen, iCopyLen);endelsebeginif buffer.FiValidBeginOffset <> 0 thenraise Exception.CreateFmt('TdrRecvBuffer.BufferHandle 緩沖區(qū)錯(cuò)誤(5) : %d, %d', [iBlockIdx, buffer.FiValidBeginOffset]);iCopyLen := Math.IfThen(iPktLen01 > buffer.FiValidLen, buffer.FiValidLen, iPktLen01);if (bufferCopy <> nil) thenCopyMemory(@bufferCopy.Fpc[iCopyOffset], @buffer.Fpc[0], iCopyLen);Dec(iPktLen01, iCopyLen);Inc(buffer.FiValidBeginOffset, iCopyLen); // 緩沖區(qū)指針移動(dòng) Dec(buffer.FiValidLen, iCopyLen);end;Inc(bufferCopy.FiValidLen, iCopyLen);Inc(iCopyOffset, iCopyLen);// ***if (iCopyOffset > bufferCopy.FiTotalLen) thenraise Exception.CreateFmt('TdrRecvBuffer.BufferHandle 緩沖區(qū)錯(cuò)誤(6) : %d, %d, %d', [iBlockIdx, iCopyOffset, bufferCopy.FiTotalLen]);if (bNeedBreak) thenbeginif (iPktLen01 <> 0) thenraise Exception.CreateFmt('TdrRecvBuffer.BufferHandle 緩沖區(qū)錯(cuò)誤(7) : %d, %d', [iBlockIdx, buffer.FiValidBeginOffset]);break;end;Inc(iBlockIdx);end; // while// *** (3) *** 緩沖區(qū) 分發(fā) TcpPktDispatch(bufferCopy);// 掃尾處理 Dec(FiTotalLen, iPktLen);if iBlockDropEndIdx > -1 thenfor i:=0 to iBlockDropEndIdx dobeging_bufferPool.ReleaseBlock(TdrBuffer(Flist.Items[0]));Flist.Delete(0);end; end;function TdrRecvBuffer.BufferHandleAll: Integer; // 處理所有已經(jīng)接收到的 TCP包 var iRtn : integer; beginResult := 0;while FiTotalLen > (TCP_PACKET_HEADER_LEN) dobeginiRtn := BufferHandle;if (iRtn > 0) thenbreak;end; end;function TdrRecvBuffer.TcpPktHeader(out _iPktLen, _iPktIdx, _iPktType: Integer): Integer; // 始終默認(rèn)是 [0]的緩沖區(qū)塊 var aryByte12 :array[0..11] of Char;buffer :TdrBuffer;iCntLeft :Integer;pi :PInteger; beginResult := 0;buffer := TdrBuffer(Flist.Items[0]);if (buffer.FiValidLen >= TCP_PACKET_HEADER_LEN) thenbeginpi := @buffer.Fpc[buffer.FiValidBeginOffset + 0]; _iPktLen := pi^;pi := @buffer.Fpc[buffer.FiValidBeginOffset + 4]; _iPktIdx := pi^;pi := @buffer.Fpc[buffer.FiValidBeginOffset + 8]; _iPktType:= pi^;endelsebeginif (Flist.Count = 1) thenraise Exception.CreateFmt('TdrRecvBuffer.TcpPktHeader 緩沖區(qū)錯(cuò)誤(1) : %d', [Flist.Count]);iCntLeft := TCP_PACKET_HEADER_LEN - buffer.FiValidLen;CopyMemory(@aryByte12[0], @buffer.Fpc[buffer.FiValidBeginOffset], buffer.FiValidLen);buffer := TdrBuffer(Flist.Items[1]);if (buffer.FiValidBeginOffset <> 0)or(buffer.FiValidLen < iCntLeft) thenraise Exception.CreateFmt('TdrRecvBuffer.TcpPktHeader 緩沖區(qū)錯(cuò)誤(2) : %d, %d, %d',[buffer.FiValidBeginOffset, buffer.FiValidLen, iCntLeft]);CopyMemory(@aryByte12[0], @buffer.Fpc[0], iCntLeft);pi := @aryByte12[0]; _iPktLen := pi^;pi := @aryByte12[4]; _iPktIdx := pi^;pi := @aryByte12[8]; _iPktType:= pi^;end; end;function TdrRecvBuffer.TcpPktIsNeed(_iPktIdx, _iPktType :integer):Integer; beginResult := 0;if (_iPktType = OP_TYPE_SQL) then // 主動(dòng)的SQL語(yǔ)句請(qǐng)求beginif (_iPktIdx = FiPktIdx) thenResult := 1;endelse if (_iPktType = OP_TYPE_PUSH) then // TCP服務(wù)端推送消息beginResult := 1;endelse if (_iPktType and OP_TYPE_MANAGE) <> 0 then // 管理beginResult := 1;end; end;procedure TdrRecvBuffer.TcpPktDispatch(_buffer :TdrBuffer); var pi :PInteger;iPktLen, iPktIdx, iPktType :Integer; beginpi := @_buffer.Fpc[4]; iPktIdx := pi^;pi := @_buffer.Fpc[8]; iPktType:= pi^;if (iPktType = OP_TYPE_SQL) then // 主動(dòng)的SQL語(yǔ)句請(qǐng)求beginif (iPktIdx = FiPktIdx) thenSetEvent(FhEvent);endelse if (iPktType = OP_TYPE_PUSH) then // TCP服務(wù)端推送消息beginPostMessage(g_callbackWnd.FhWnd, WM_TCP_PUSH, 0, LParam(_buffer));endelse if (iPktType and OP_TYPE_MANAGE) <> 0 then // 管理beginif DWORD(iPktType) = OP_TYPE_MANAGE_CLIENTS then // 所有客戶端的信息PostMessage(g_callbackWnd.FhWnd, WM_TCP_CLIENTS, 0, LParam(_buffer))else if DWORD(iPktType) = OP_TYPE_MANAGE_SOCKET_REQ thenPostMessage(g_callbackWnd.FhWnd, WM_CLIENT_SOCKET_MSG_REQ, 0, LParam(_buffer))else if DWORD(iPktType) = OP_TYPE_MANAGE_SOCKET_RES thenPostMessage(g_callbackWnd.FhWnd, WM_CLIENT_SOCKET_MSG_RES, 0, LParam(_buffer))else if DWORD(iPktType) = OP_TYPE_MANAGE_BLOCK_REQ thenPostMessage(g_callbackWnd.FhWnd, WM_CLIENT_BLOCK_MSG_REQ, 0, LParam(_buffer))else if DWORD(iPktType) = OP_TYPE_MANAGE_BLOCK_RES thenPostMessage(g_callbackWnd.FhWnd, WM_CLIENT_BLOCK_MSG_RES, 0, LParam(_buffer))else if DWORD(iPktType) = OP_TYPE_MANAGE_SQL thenPostMessage(g_callbackWnd.FhWnd, WM_MANAGE_SQL, 0, LParam(_buffer))elsebeginend;end; end;{ TdrTcpClient }function TdrTcpClient.RecvTimeoutSet: Integer; var iRecvTimeout, iRtn :Integer; beginResult := 0;iRecvTimeout := 1; // 毫秒iRtn := setsockopt(Fskt, SOL_SOCKET, SO_RCVTIMEO, PChar(@iRecvTimeout), sizeof(integer));if SOCKET_ERROR = iRtn thenbeginResult := GetLastError;FiErrorNo := Result;end; end;function TdrTcpClient.RecvTimeoutCancel: Integer; var iRecvTimeout, iRtn :Integer; beginResult := 0;iRecvTimeout := 0; // 毫秒iRtn := setsockopt(Fskt, SOL_SOCKET, SO_RCVTIMEO, PChar(@iRecvTimeout), sizeof(integer));if SOCKET_ERROR = iRtn thenbeginResult := GetLastError;FiErrorNo := Result;end; end;procedure TdrTcpClient.Execute; var pcRecv :PChar;iLenRecv :Integer;iRecvBlockIdx :integer;iRecv, iRtn :Integer; begin//inherited; g_drRecvBuffer.BufferReleaseAll;FiStatus := 1;while True dobeginiRecvBlockIdx := g_drRecvBuffer.BufferAuqire(pcRecv, iLenRecv);iRecv := recv(Fskt, pcRecv^, iLenRecv, 0);if (iRecv = 0) then // 連接優(yōu)雅(gracefully)關(guān)閉beginFiErrorNo := 0;break;endelse if (iRecv < 0) thenbeginFiErrorNo := GetLastError;break;endelse// if (iRecv > 0) thenbeging_drRecvBuffer.BufferRecv(iRecv, iRecvBlockIdx);g_drRecvBuffer.BufferHandleAll;PostMessage(g_callbackWnd.FhWnd, WM_TCP_RECV, 0, iRecv);end; // ZC: 用timeout操作的時(shí)候,在數(shù)據(jù)讀完之后 有明顯感覺的卡頓現(xiàn)象(大概有1s左右)...于是,放棄使用timeout讀數(shù)據(jù) // iRtn := Recv01; // if (iRtn <= 0) then // break; // g_drRecvBuffer.BufferHandleAll;end;closesocket(Fskt);FiStatus := -1;// 線程執(zhí)行完畢(退出)//raise Exception.CreateFmt('socket線程退出 : %d', [FiErrorNo]); end;function TdrTcpClient.Recv01: Integer; var pcRecv :PChar;iLenRecv :Integer;iRecvBlockIdx :integer;iRecv :Integer; beginResult := 0;if RecvTimeoutSet<>0 thenbeginResult := GetLastError;Exit;end;while true dobeginiRecvBlockIdx := g_drRecvBuffer.BufferAuqire(pcRecv, iLenRecv);iRecv := recv(Fskt, pcRecv^, iLenRecv, 0);if (iRecv = 0) then // 連接優(yōu)雅(gracefully)關(guān)閉beginResult := -1;FiErrorNo := 0;endelse if (iRecv < 0) thenbeginFiErrorNo := GetLastError;if WSAETIMEDOUT <> FiErrorNo thenbeginResult := -2;endelsebeginResult := 1;end;break;endelse// if (iRecv > 0) thenbeging_drRecvBuffer.BufferRecv(iRecv, iRecvBlockIdx);if (iRecv <> iLenRecv) thenbeginResult := 2;Break;end;end;end;if RecvTimeoutCancel <> 0 thenResult := GetLastError; end;function TdrTcpClient.Send01(_pbyte: PByte; _iLen: integer): Integer; var iRtn :Integer; beginResult := 0;iRtn := send(Fskt, _pbyte^, _iLen, 0);if iRtn = SOCKET_ERROR thenResult := GetLastError; end;class function TdrTcpClient.Conn :integer; var skt :TSocket;bNeedCreate :boolean; beginResult := 0;if (length(g_strDestIp)=0)or(g_iDestPort=0) thenbeginraise Exception.Create('服務(wù)器IP/Poer 未設(shè)置');Exit;end;bNeedCreate := false;if (g_tcpClient = nil) thenbNeedCreate := trueelsebeginif (g_tcpClient.FiStatus = 0) thenbeginResult := -1;Exit;endelse if (g_tcpClient.FiStatus = -1) thenbeginbNeedCreate := True;g_tcpClient.Free;end;end;if (bNeedCreate) thenbeginskt := TdrTcpClient.ConnectDest;g_tcpClient := TdrTcpClient.Create(false);g_tcpClient.Fskt := skt;end; end;class procedure TdrTcpClient.SendSQL(_str: string); var iPktLen, iPktIdx, iPktType :Integer;bytesSend :array[0..255] of byte;iRtn :Integer; beginif Conn < 0 thenraise Exception.Create('TCP接收線程正在初始化,請(qǐng)稍后再試...');Inc(g_drRecvBuffer.FiPktIdx);iPktLen := TCP_PACKET_HEADER_LEN + Length(_str);iPktIdx := g_drRecvBuffer.FiPktIdx;iPktType := OP_TYPE_SQL;CopyMemory(@bytesSend[0], @iPktLen, 4); // TCP包頭 --(1) 總長(zhǎng)CopyMemory(@bytesSend[4], @iPktIdx, 4); // TCP包頭 --(2) 序號(hào)CopyMemory(@bytesSend[8], @iPktType, 4); // TCP包頭 --(3) 類型CopyMemory(@bytesSend[12], PChar(_str), Length(_str)); // TCP包 內(nèi)容 iRtn := g_tcpClient.Send01(@bytesSend[0], iPktLen);if (iRtn <> 0) thenraise Exception.CreateFmt('發(fā)送消息異常 : (%d)%s', [iRtn, ErrorNo2Str(iRtn)]);WaitForSingleObject(g_drRecvBuffer.FhEvent, INFINITE); end;class procedure TdrTcpClient.SendBytes(_pc :PChar; _iLen :Integer); var iRtn :Integer; beginif Conn < 0 thenraise Exception.Create('TCP接收線程正在初始化,請(qǐng)稍后再試...');iRtn := g_tcpClient.Send01(@_pc[0], _iLen);if (iRtn <> 0) thenraise Exception.CreateFmt('發(fā)送消息異常 : (%d)%s', [iRtn, ErrorNo2Str(iRtn)]); end;class function TdrTcpClient.ConnectDest :TSocket; var wsadata1 :WSADATA;addrSrv :SOCKADDR_IN;iRtn :Integer;skt :TSocket;dwErrorNo :DWORD; beginResult := 0;WSAStartup(MAKEWORD(1,1), wsadata1);skt := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (skt <= 0) thenbegindwErrorNo := GetLastError;raise Exception.CreateFmt('%s %d', ['套接字創(chuàng)建異常:', dwErrorNo]);end;addrSrv.sin_family := AF_INET;addrSrv.sin_port := htons(g_iDestPort);addrSrv.sin_addr.S_addr := inet_addr(PChar(g_strDestIp));iRtn := connect(skt, addrSrv, sizeof(addrSrv));if(iRtn <> 0) thenbegindwErrorNo := GetLastError;raise Exception.CreateFmt('%s %d %s', ['服務(wù)器連接異常:', dwErrorNo, ErrorNo2Str(dwErrorNo)]);end;Result := skt; end;class procedure TdrTcpClient.SetIpPort(_strDestIp: string; _iDestPort: integer); beging_strDestIp := _strDestIp;g_iDestPort := _iDestPort; end;class function TdrTcpClient.Status: Integer; beginif (g_tcpClient = nil) thenResult := -100elseResult := g_tcpClient.FiStatus; end;class procedure TdrTcpClient.SendHeartBeat; var pc :array[0..12] of Char;iPktLen, iPktIdx, iPktType :Integer; beginiPktLen := 12;iPktIdx := 0;iPktType := OP_TYPE_HEARTBEAT;CopyMemory(@pc[0], @iPktLen, 4);CopyMemory(@pc[4], @iPktIdx, 4);CopyMemory(@pc[8], @iPktType, 4);SendBytes(pc, iPktLen); end;{ TcallbackWnd }function ProcWindow(_hWnd :HWND;_uMsg :UINT;_wParam :WPARAM;_lParam :LPARAM):longint;stdcall; var buffer :TdrBuffer;pc :PChar; beginResult := 0; // 用戶已經(jīng)處理if (_uMsg = WM_TCP_PUSH) thenbeginif Assigned(g_callbackWnd.FfuncPush) thenbegin// 得到 緩沖區(qū)buffer := TdrBuffer(_lParam);// 業(yè)務(wù)邏輯處理g_callbackWnd.FfuncPush(@buffer.Fpc[TCP_PACKET_HEADER_LEN], buffer.FiValidLen - TCP_PACKET_HEADER_LEN);// 釋放緩沖區(qū) g_bufferPool.ReleaseBlock(buffer);end;endelse if (_uMsg = WM_TCP_CLIENTS) thenbeginif Assigned(g_callbackWnd.FfuncClients) thenbeginbuffer := TdrBuffer(_lParam);g_callbackWnd.FfuncClients(@buffer.Fpc[TCP_PACKET_HEADER_LEN], buffer.FiValidLen - TCP_PACKET_HEADER_LEN);g_bufferPool.ReleaseBlock(buffer);end;endelse if (_uMsg = WM_CLIENT_SOCKET_MSG_REQ) thenbeginbuffer := TdrBuffer(_lParam);g_callbackWnd.PackSocket(@buffer.Fpc[TCP_PACKET_HEADER_LEN], buffer.FiValidLen - TCP_PACKET_HEADER_LEN);g_bufferPool.ReleaseBlock(buffer);endelse if (_uMsg = WM_CLIENT_BLOCK_MSG_REQ) thenbeginbuffer := TdrBuffer(_lParam);g_callbackWnd.PackBlock(@buffer.Fpc[TCP_PACKET_HEADER_LEN], buffer.FiValidLen - TCP_PACKET_HEADER_LEN);g_bufferPool.ReleaseBlock(buffer);endelse if (_uMsg = WM_CLIENT_SOCKET_MSG_RES) thenbeginif Assigned(g_callbackWnd.FfuncSocket) thenbeginbuffer := TdrBuffer(_lParam);g_callbackWnd.FfuncSocket(@buffer.Fpc[TCP_PACKET_HEADER_LEN], buffer.FiValidLen - TCP_PACKET_HEADER_LEN);g_bufferPool.ReleaseBlock(buffer);end;endelse if (_uMsg = WM_CLIENT_BLOCK_MSG_RES) thenbeginif Assigned(g_callbackWnd.FfuncBlock) thenbeginbuffer := TdrBuffer(_lParam);g_callbackWnd.FfuncBlock(@buffer.Fpc[TCP_PACKET_HEADER_LEN], buffer.FiValidLen - TCP_PACKET_HEADER_LEN);g_bufferPool.ReleaseBlock(buffer);end;endelse if (_uMsg = WM_MANAGE_SQL) thenbeginbuffer := TdrBuffer(_lParam);if Assigned(g_callbackWnd.FfuncSQL) theng_callbackWnd.FfuncSQL(buffer);g_bufferPool.ReleaseBlock(buffer);endelse if (WM_TCP_RECV = _uMsg) thenbeginif (_wParam = 0) thenfrmMain.Memo1.Lines.Add('Recv : '+inttostr(_lParam))else if (_wParam = 1) thenfrmMain.Memo1.Lines.Add('Allocate buffer block for : 0x'+inttohex(_lParam, 8))else if (_wParam = 2) thenfrmMain.Memo1.Lines.Add('Release buffer block from : 0x'+inttohex(_lParam, 8))else if (_wParam = 3) thenfrmMain.Memo1.Lines.Add('Space for unicode string : '+inttostr(_lParam))else if (_wParam = 4) thenfrmMain.Memo1.Lines.Add('Space for ansi string : '+inttostr(_lParam))else if (_wParam = 5) thenfrmMain.Memo1.Lines.Add('UTF-8 string space is : '+inttostr(_lParam));endelse if (WM_LOG_CONSOLE = _uMsg) thenbeginpc := PChar(_lParam);frmMain.Memo1.Lines.Add(PChar(_lParam));FreeMem(pc, _wParam);endelse if (_uMsg = WM_TIMER) thenbeginif (1 = _wParam) thenbeginif (g_tcpClient<>nil)and(g_tcpClient.FiStatus = 1) thenTdrTcpClient.SendHeartBeat;end;endelse if (_uMsg = WM_DESTROY) thenbeginDestroyWindow(_hwnd);PostQuitMessage(0);endelse Result := DefWindowProc(_hWnd, _uMsg, _wParam, _lParam); end;constructor TcallbackWnd.Create; beginCreateWindow;//SetTimer(FhWnd, 1, 1000 * 10, nil); end;procedure TcallbackWnd.CreateWindow; var wndcls :WNDCLASS;hInstance :THandle; beginhInstance := Windows.GetModuleHandle(nil);ZeroMemory(@wndcls, sizeof(wndcls));wndcls.cbClsExtra := 0;wndcls.cbWndExtra := 0;wndcls.hbrBackground := HBRUSH(GetStockObject(WHITE_BRUSH)); // 背景畫刷wndcls.hCursor := LoadCursor(0, IDC_CROSS);wndcls.hIcon := LoadIcon(0, IDI_ERROR); // 窗口圖標(biāo)wndcls.hInstance := hInstance;wndcls.lpfnWndProc := @ProcWindow;wndcls.lpszClassName:= 'DrTcpCallbackWnd';wndcls.lpszMenuName := nil;wndcls.style := CS_HREDRAW or CS_VREDRAW;Windows.RegisterClass(wndcls);FhWnd := CreateWindowEx(WS_EX_CLIENTEDGE,wndcls.lpszClassName,wndcls.lpszClassName,WS_OVERLAPPEDWINDOW,100, 100,400, 300,0,0, //g_hMenu, hInstance,0);if (FhWnd = 0) thenFdwErrNo := GetLastError;// ShowWindow(hWnd1, SW_SHOWNORMAL); UpdateWindow(FhWnd); end;function TcallbackWnd.PackSocket(_pc :PChar; _iLen :integer) :integer; var sockAddr :TSockAddr;iNameLen :Integer;dwErrNo :DWORD;strMac, strIP :string;iLenIp, iLenMac, iLenMsg :Integer;pc :array[0..255] of Char;iPktLen, iPktIdx, iPktType :Integer; beginResult := 0;iNameLen := SizeOf(sockAddr);if SOCKET_ERROR = getsockname(g_tcpClient.Fskt, sockAddr, iNameLen) thenbegindwErrNo := GetLastError;Result := dwErrNo;Exit;end;strIP := inet_ntoa(sockAddr.sin_addr);strMac := '';GetMacByIP(sockAddr.sin_addr.S_addr, strMac);iLenIp := 4 + length(strIP);iLenMac:= 4 + length(strMac);iLenMsg := 4 + iLenIp + iLenMac;iPktLen := TCP_PACKET_HEADER_LEN + iLenMsg + _iLen;iPktIdx := 0;iPktType:= OP_TYPE_MANAGE_SOCKET_RES;CopyMemory(@pc[0], @iPktLen, 4);CopyMemory(@pc[4], @iPktIdx, 4);CopyMemory(@pc[8], @iPktType, 4);// ***CopyMemory(@pc[TCP_PACKET_HEADER_LEN], @iLenMsg, 4);CopyMemory(@pc[TCP_PACKET_HEADER_LEN + 4], @iLenIp, 4);CopyMemory(@pc[TCP_PACKET_HEADER_LEN + 8], PChar(strIP), iLenIp - 4);CopyMemory(@pc[TCP_PACKET_HEADER_LEN + 4 + iLenIp], @iLenMac, 4);CopyMemory(@pc[TCP_PACKET_HEADER_LEN + 4 + iLenIp + 4], PChar(strMac), iLenMac - 4);// ***CopyMemory(@pc[TCP_PACKET_HEADER_LEN+iLenMsg], _pc, _iLen);TdrTcpClient.SendBytes(@pc[0], iPktLen); end;procedure TcallbackWnd.PackBlock(_pc :PChar; _iLen :integer); var iPktLen, iPktIdx, iPktType :Integer;iIdx :Integer;buffer :TdrBuffer;mem :TMemoryStream;iLenMsg :Integer;pc :PChar;dwTick :DWORD; beginmem := TMemoryStream.Create;tryiPktLen := TCP_PACKET_HEADER_LEN;iPktIdx := 0;iPktType:= OP_TYPE_MANAGE_BLOCK_RES;mem.Write(iPktLen, 4);mem.Write(iPktIdx, 4);mem.Write(iPktType, 4);iLenMsg := 8;mem.Write(iLenMsg, 4);dwTick := GetTickCount;mem.Write(dwTick, 4);iIdx := 0;while iIdx < g_bufferPool.ListAll.Count dobeginbuffer := TdrBuffer(g_bufferPool.ListAll.Items[iIdx]);mem.Write(buffer.FiTotalLen, 4);mem.Write(buffer.FiValidBeginOffset, 4);mem.Write(buffer.FiValidLen, 4);mem.Write(buffer.FdwType, 4);mem.Write(buffer.FdwLastTick, 4);Inc(iLenMsg, 20);Inc(iIdx);end;iPktLen := TCP_PACKET_HEADER_LEN + iLenMsg + _iLen;iPktIdx := 0;iPktType:= OP_TYPE_MANAGE_BLOCK_RES;pc := PChar(mem.Memory);CopyMemory(@pc[0], @iPktLen, 4);CopyMemory(@pc[4], @iPktIdx, 4);CopyMemory(@pc[8], @iPktType, 4);CopyMemory(@pc[TCP_PACKET_HEADER_LEN], @iLenMsg, 4); mem.Write(_pc^, _iLen);TdrTcpClient.SendBytes(mem.Memory, iPktLen);finallymem.Free;end; end;{ TdrDataSet }function TdrDataSet.Unpack(_pc :PChar; _iLen :Integer) :integer; var iTotalLen, iColumnCnt, iRowCnt :Integer;i, iOffset, iLenColumnName, iRowIdx, iColIdx :Integer;iLenRecord :Integer; beginResult := 0;FpcBuf := _pc;FiBufLen := _iLen;CopyMemory(@iTotalLen, @_pc[0], 4);if (iTotalLen <> _iLen) thenbeginResult := -1;Exit;end;CopyMemory(@iColumnCnt, @_pc[4], 4);CopyMemory(@iRowCnt, @_pc[8], 4);SetLength(FaryColumnType, iColumnCnt);SetLength(FaryColumnName, iColumnCnt);SetLength(FaryaryRecord, iRowCnt, iColumnCnt);// 列類型for i:=0 to (iColumnCnt-1) doCopyMemory(@FaryColumnType[i], @_pc[12 + i * 4], 4);iOffset := 12 + iColumnCnt * 4;// 列名稱for i:=0 to (iColumnCnt-1) dobeginCopyMemory(@iLenColumnName, @_pc[iOffset], 4);SetLength(FaryColumnName[i], iLenColumnName);CopyMemory(@((FaryColumnName[i])[1]), @_pc[iOffset + 4], iLenColumnName);Inc(iOffset, 4 + iLenColumnName);end;// [2]、字段值(長(zhǎng)度 + 內(nèi)容)for iRowIdx:=0 to iRowCnt-1 dofor iColIdx:=0 to iColumnCnt-1 dobeginCopyMemory(@iLenRecord, @_pc[iOffset], 4);FaryaryRecord[iRowIdx, iColIdx] := iOffset + 4;Inc(iOffset, 4 + iLenRecord);end; end;function TdrDataSet.GetRecord(_iRowIdx, _iColumnIdx: integer): TdrRecord; beginif not Assigned(Ffield) thenFfield := TdrRecord.Create(Self, _iRowIdx, _iColumnIdx)elsebeginFfield.FiRowIdx := _iRowIdx;Ffield.FiColumnIdx := _iColumnIdx;end;Ffield.FenXi;Result := Ffield; end;function TdrDataSet.GetFieldType(_iColumnIdx: integer): Integer; beginResult := FaryColumnType[_iColumnIdx]; end;function TdrDataSet.GetFieldTypeName(_iColumnIdx: integer): string; beginFieldTypeName_f(GetFieldType(_iColumnIdx), Result); end;function TdrDataSet.GetFieldName(_iColumnIdx: integer): string; beginResult := FaryColumnName[_iColumnIdx]; end;function TdrDataSet.GetRowCount: Integer; beginResult := Length(FaryaryRecord); end;function TdrDataSet.GetColumnCount: Integer; beginResult := Length(FaryColumnType); end;{ TdrRecord }constructor TdrRecord.Create(_dataset: TdrDataSet; _iRowIdx, _iColumnIdx: Integer); beginFdataset := _dataset;FiRowIdx := _iRowIdx;FiColumnIdx := _iColumnIdx; end;procedure TdrRecord.FenXi; var iOffset :Integer; beginiOffset := Fdataset.FaryaryRecord[FiRowIdx, FiColumnIdx];FpcRecord := @Fdataset.FpcBuf[iOffset]; end;function TdrRecord.asByteArray(_pByte: PByte; out _iLen: Integer): Integer; beginCopyMemory(@_iLen, FpcRecord-4, 4);if (_pByte <> nil) thenCopyMemory(_pByte, FpcRecord, _iLen); end;function TdrRecord.asInteger: Integer; beginCopyMemory(@Result, FpcRecord, 4); end;function TdrRecord.asSingle: Single; beginCopyMemory(@Result, FpcRecord, SizeOf(Single)); end;function TdrRecord.asDouble: Double; beginCopyMemory(@Result, FpcRecord, SizeOf(Double)); end;function TdrRecord.asString: string; var iLen :Integer;iFieldType :Integer;d :Double;iUnicodeLen, iAnsiLen :Integer;pwc :PWideChar;pc :PChar; beginiFieldType := GetFieldType;case iFieldType ofDR_NUMERIC :beginCopyMemory(@iLen, FpcRecord - 4, 4);CopyMemory(@d, FpcRecord, iLen);Result := FloatToStr(d);end;DR_LONGNVARCHAR, DR_NCHAR, DR_NVARCHAR, DR_LONGVARCHAR, DR_CHAR, DR_VARCHAR :beginpwc := nil;pc := nil;tryCopyMemory(@iLen, FpcRecord - 4, 4);//PostMessage(g_callbackWnd.FhWnd, WM_TCP_RECV, 5, iLen);if (iLen = 0) thenbeginResult := 'Empty string .';Exit;end;SetLength(Result, iLen);CopyMemory(@Result[1], FpcRecord, iLen);{iUnicodeLen := MultiByteToWideChar(CP_UTF8, 0, FpcRecord, iLen, nil, 0);GetMem(pwc, iUnicodeLen * 2);MultiByteToWideChar(CP_UTF8, 0, FpcRecord, iLen, pwc, iUnicodeLen);iAnsiLen := WideCharToMultiByte(CP_ACP, 0, pwc, iUnicodeLen, nil, 0, nil, nil);GetMem(pc, iAnsiLen + 1);WideCharToMultiByte(CP_ACP, 0, pwc, iUnicodeLen, pc, iAnsiLen, nil, nil);pc[iAnsiLen] := Char(0);Result := pc; }finallyif (pwc <> nil) then FreeMem(pwc, iUnicodeLen * 2);if (pc <> nil) then FreeMem(pc, iAnsiLen + 1);end;end;else FieldTypeName_f(iFieldType, Result);end; end;function TdrRecord.GetFieldType: Integer; beginResult := Fdataset.GetFieldType(FiColumnIdx); end;function TdrRecord.GetFieldTypeName: string; beginResult := Fdataset.GetFieldTypeName(FiColumnIdx); end;function TdrRecord.GetFieldName: string; beginResult := Fdataset.GetFieldName(FiColumnIdx); end;initializationg_bufferPool := TdrBufferPool.create;g_drRecvBuffer := TdrRecvBuffer.Create;g_callbackWnd := TcallbackWnd.Create;g_strDestIp := '';g_iDestPort := 0;finalizationif Assigned(g_bufferPool) then g_bufferPool.Free;if Assigned(g_drRecvBuffer) then g_drRecvBuffer.Free;end.

?

3、

?

轉(zhuǎn)載于:https://www.cnblogs.com/CodeHouseZ/p/6144149.html

總結(jié)

以上是生活随笔為你收集整理的TCP中间件_Delphi_client的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

色综合天天 | 五月天色婷婷丁香 | 麻豆91在线 | 免费三级大片 | av福利在线免费观看 | 99久久精品国产亚洲 | 一区二区三区中文字幕在线 | 中文资源在线播放 | 视频一区视频二区在线观看 | 亚洲国产精品第一区二区 | 欧美一级片免费在线观看 | 欧美一区二区在线刺激视频 | 国产专区在线视频 | 波多野结衣在线播放一区 | 国产中文字幕免费 | av超碰免费在线 | 精品国产午夜 | 极品久久久久 | 国产系列精品av | 国产视频一二区 | 日韩精品一区二区三区中文字幕 | 四虎永久免费在线观看 | 91色蜜桃| 久久久国产精品亚洲一区 | 国产免费观看高清完整版 | 中文字幕传媒 | 久久免费毛片视频 | 黄色精品一区二区 | 国产精品观看 | 免费黄色在线网址 | 色婷婷激情电影 | 在线免费av播放 | 欧美日韩国产综合网 | 91香蕉视频污在线 | 日韩精品一区二区三区高清免费 | 久久午夜视频 | 欧美在线视频一区二区三区 | 国产 日韩 中文字幕 | 国产玖玖视频 | 日韩精品视频网站 | 国产精品 亚洲精品 | 蜜臀av网址 | 日韩在线观看视频中文字幕 | 中文字幕免费高清在线 | 日韩欧美国产视频 | 久久久久久黄色 | 一本色道久久综合亚洲二区三区 | 国产日韩精品一区二区三区 | 正在播放日韩 | 国产一级特黄毛片在线毛片 | 成年人毛片在线观看 | 91麻豆产精品久久久久久 | 亚洲涩涩涩涩涩涩 | 亚洲aaa级 | 国产999精品久久久久久麻豆 | 中文字幕色在线 | a黄色片在线观看 | 国产裸体无遮挡 | 中文字幕色播 | 国产一区免费在线观看 | 亚洲精品久久久久中文字幕二区 | 日韩免费在线视频 | 色播激情五月 | 91精品国产91久久久久久三级 | 国产资源免费在线观看 | 国产在线精品二区 | 欧美精品国产综合久久 | 午夜精品久久久久久 | 五月婷婷开心 | 精品久久久久久综合日本 | 在线观看国产日韩欧美 | 国产美女黄网站免费 | 亚洲女人天堂成人av在线 | 天天干中文字幕 | a天堂在线看 | 97在线观看视频国产 | 久久综合精品国产一区二区三区 | 婷婷色网站 | 狠狠色伊人亚洲综合成人 | 福利区在线观看 | 免费a视频在线观看 | 奇米网网址 | 麻豆极品| 国产明星视频三级a三级点| 黄色美女免费网站 | 欧洲精品亚洲精品 | 精品久久久久久久久中文字幕 | 在线 日韩 av | 激情五月婷婷 | 97小视频| 超碰国产在线 | 国产69精品久久99不卡的观看体验 | 午夜国产影院 | 国产免费高清视频 | 91av在线免费看 | 国产91精品一区二区麻豆网站 | 成人免费观看电影 | 日韩欧美大片免费观看 | 一区二区三区国 | 日批在线看 | 久久视频在线观看中文字幕 | 国产精品欧美日韩在线观看 | 国产一区在线视频播放 | 高清久久久久久 | 日韩中文字幕在线看 | 成人免费av电影 | 99热国产在线观看 | 97色在线视频| 人人添人人澡人人澡人人人爽 | 亚洲精品国产品国语在线 | 天堂av网址 | 日韩欧美电影网 | 在线观看视频一区二区三区 | 日韩a在线 | 久久不卡日韩美女 | 午夜.dj高清免费观看视频 | 色噜噜在线观看 | 蜜桃av观看 | 精品一区二区在线免费观看 | 国产黄在线看 | 免费麻豆 | 日本中文字幕视频 | 日日爱999 | 日韩欧美在线免费 | 日韩激情小视频 | 久久三级毛片 | 亚洲开心色 | 国产成人专区 | 国产精品久久久久久久久久了 | 在线播放视频一区 | 中文字幕在线观看91 | 国产精品情侣视频 | 色wwwww | av一级一片| 欧美在线观看视频免费 | 国产免费久久 | 手机成人av | 午夜资源站 | 成人一级片视频 | 亚洲精品在线资源 | 久久久久亚洲精品成人网小说 | 国产精品久久精品国产 | 天天搞天天 | 久久免费视频精品 | 午夜视频一区二区三区 | 亚洲精品国产精品久久99 | 精品国产乱码一区二区三区在线 | 久久精品一区二区三区中文字幕 | 日韩精品视频第一页 | 97理论片| 日韩在线视 | 国产精品美女久久久久久久久 | www欧美色 | 麻豆播放 | 午夜av片 | 日本三级香港三级人妇99 | 中文字幕日韩免费视频 | 天天综合视频在线观看 | 日韩亚洲国产中文字幕 | 97国产超碰在线 | 992tv在线观看 | 91在线播放视频 | 亚洲第一伊人 | 成人精品福利 | 在线国产小视频 | av福利资源| 欧美日韩国产综合网 | 亚洲视频一| 欧美日本啪啪无遮挡网站 | 国产一级片免费视频 | 久久视频在线观看 | 久久天天躁夜夜躁狠狠85麻豆 | 日韩综合一区二区三区 | 91精品国产高清 | 一区二区中文字幕在线观看 | 国产亚洲精品精品精品 | www.夜夜爱 | 成年美女黄网站色大片免费看 | 国产成人中文字幕 | 久久久国产成人 | 久久久www成人免费毛片 | 天天干天天在线 | 亚洲成人家庭影院 | 国产精品二区在线观看 | 国产精品久久久久久久久久久久午 | 天天摸天天操天天舔 | 亚洲男男gaygay无套同网址 | 麻豆视频一区二区 | 99精品在线视频播放 | 久久夜夜爽 | 久久激情五月丁香伊人 | 不卡的av电影在线观看 | 日韩视频免费看 | 国产人免费人成免费视频 | 日韩在线精品一区 | 91最新视频在线观看 | 国产精品久久久久久久久久久久午夜 | 亚洲精品一区二区在线观看 | 国产传媒中文字幕 | 天天操天天色天天 | 精品国精品自拍自在线 | 天天综合导航 | 午夜精品三区 | 国产区精品区 | 久草在线免费看视频 | 在线 你懂 | 天天综合视频在线观看 | 97国产精品视频 | 一区二区久久 | 久久视频网址 | 91av免费观看 | 亚洲在线a| 成人久久久久久久久 | 国产精品久久99综合免费观看尤物 | 中文字幕第一页在线播放 | 国产最新91 | 在线观看你懂的网站 | 最新日韩中文字幕 | 久久这里有精品 | 国产黄a三级三级 | 99亚洲国产精品 | 天天鲁天天干天天射 | 91麻豆精品国产自产在线游戏 | 日韩一区二区免费播放 | 成年人免费观看在线视频 | 日韩免费中文 | 国产一区欧美在线 | 国语自产偷拍精品视频偷 | 久久国产精品精品国产色婷婷 | 人人澡人人爽欧一区 | 91传媒视频在线观看 | 五月婷婷丁香在线观看 | 成人在线视频一区 | 精品视频在线看 | 国产精品久久久久久久久久 | av电影不卡在线 | 亚洲永久字幕 | 最新日韩在线 | 天天操天天是 | 丁香婷婷综合激情五月色 | 久久久 激情| 免费毛片aaaaaa | 国产精品一区二区久久精品爱微奶 | av在线最新 | 久久久久成人精品亚洲国产 | 在线观看中文字幕av | 免费在线观看中文字幕 | 欧美精品一区二区蜜臀亚洲 | 色资源二区在线视频 | 欧美在线视频一区二区三区 | 91热爆在线观看 | 看国产黄色片 | av免费观看网站 | a黄色片在线观看 | 中文字幕在线观看第二页 | 2018亚洲男人天堂 | 亚洲一区日韩 | 黄色一区三区 | 免费观看版 | 国产精品免费一区二区 | 国产精品爽爽久久久久久蜜臀 | 国产精品www | 操夜夜操 | 久久久精品国产一区二区电影四季 | 色瓜| www日韩在线| 在线视频电影 | 免费成视频| 久久国产精品一国产精品 | 日韩高清黄色 | 午夜av免费看 | 久久日本视频 | 久久午夜电影院 | 国产精品美女免费 | 亚洲综合涩 | 九九在线免费视频 | 日韩精品在线看 | 日韩资源在线播放 | 亚洲黄色激情小说 | 午夜视频在线观看一区二区三区 | 日本最新一区二区三区 | 一区二区国产精品 | 97超碰在线久草超碰在线观看 | 国产91精品在线观看 | 亚洲人人射 | 亚洲欧美激情插 | 国产精品久久99综合免费观看尤物 | 久草免费在线观看 | a在线一区 | 色婷婷中文| 91精品91 | 超级碰视频 | 91精品国产九九九久久久亚洲 | 日韩美女高潮 | 91精品老司机久久一区啪 | 在线观看免费视频你懂的 | 亚洲国产日韩欧美 | 在线电影播放 | 国产二级视频 | 97视频免费播放 | 天堂av观看 | 日日狠狠 | 久久综合狠狠综合 | 久久久久久久久影视 | 欧美久久久久 | 91精品国产入口 | 久久国产精品99久久久久久丝袜 | 久草久热 | 久草视频在线资源 | 国产精品久久久久久久久久久久 | 日韩三级中文字幕 | 免费黄色在线网址 | 午夜精品视频免费在线观看 | 天天天操天天天干 | 国产日韩亚洲 | 国产在线色 | 99久久精品久久亚洲精品 | 99亚洲精品在线 | 美女中文字幕 | 日韩一级成人av | 久久黄色免费 | 91正在播放 | 久久欧美综合 | 不卡的av电影| 极品国产91在线网站 | 日韩av高潮 | 久久精品网站免费观看 | 久久久久在线观看 | 欧美,日韩| 国产精品久久久久久久毛片 | 亚洲国产精品激情在线观看 | 久久成人一区二区 | ,午夜性刺激免费看视频 | av不卡免费在线观看 | 顶级bbw搡bbbb搡bbbb | 亚洲毛片在线观看. | 国产一区二区久久精品 | 91片在线观看 | 91夫妻自拍| 91最新在线 | 久久久三级视频 | 国产又粗又猛又色又黄网站 | 久久久久久毛片精品免费不卡 | 干天天| 99久久久成人国产精品 | 久久久久久久久网站 | 69人人| 久久国产亚洲精品 | 久久99亚洲网美利坚合众国 | 日韩精品短视频 | 成人在线免费观看网站 | 国产精品自在欧美一区 | 国产中文在线字幕 | 欧美一级片在线免费观看 | a久久久久久 | 国产精品久久久久久久7电影 | 福利av影院 | www日| 免费av在线播放 | 91九色网址| 在线观看你懂的网站 | 国产中文字幕在线免费观看 | 日本乱码在线 | 日韩欧美视频在线观看免费 | 美女国内精品自产拍在线播放 | 日韩字幕 | 成人黄色在线观看视频 | 九九免费视频 | 四虎成人在线 | av网站在线观看播放 | 国内精品久久久久影院一蜜桃 | 欧美一级片免费观看 | 99精品偷拍视频一区二区三区 | 天天干天天弄 | 91麻豆精品国产91久久久无限制版 | 欧美日韩在线精品 | www.天天射.com | 成人小视频在线观看免费 | 97免费在线视频 | 91色视频 | 亚洲少妇xxxx | 超碰日韩在线 | 黄色大片网 | 亚洲在线日韩 | 久久久久久久免费看 | 免费看的黄色小视频 | 天天爽天天射 | 国产精品久久久一区二区三区网站 | 人人澡澡人人 | 精品久久久久久一区二区里番 | 久久另类小说 | 日韩美女免费线视频 | 久日精品| 五月天久久综合网 | 免费高清在线视频一区· | 99久久精品久久久久久清纯 | 久久综合久久鬼 | 永久黄网站色视频免费观看w | 91免费观看| 久久,天天综合 | 亚洲国产精品久久久久婷婷884 | 色www精品视频在线观看 | 国产精品久久久av | 91九色蝌蚪在线 | 国产探花 | 成人av在线直播 | 黄色片免费在线 | 日韩av不卡在线观看 | 狠狠色婷婷丁香六月 | 国产黄色在线观看 | 视频在线亚洲 | 午夜在线资源 | 九九久久免费视频 | 国产精品欧美久久久久天天影视 | 青草视频在线播放 | 一区二区中文字幕在线 | 18做爰免费视频网站 | 日韩精品久久久 | 999热视频| 中文字幕在线看视频 | 久久亚洲婷婷 | 国产最顶级的黄色片在线免费观看 | 国产午夜三级一二三区 | 亚洲欧美成人 | 婷婷视频 | 国产一级久久久 | 国产精品久久久久久久免费观看 | 亚洲免费观看在线视频 | 色网免费观看 | 色综合天天干 | 国产精品一区二区久久精品 | 国产精品成人一区二区三区吃奶 | 亚洲免费视频观看 | 2023天天干 | 久久深夜福利免费观看 | 国产一级二级在线 | 婷婷成人亚洲综合国产xv88 | 日韩成人精品一区二区三区 | 黄色一级大片在线免费看国产一 | 国产精品尤物 | 亚洲人成综合 | 99久久久久国产精品免费 | 亚洲精品国产精品99久久 | 九九久久国产 | 久久久黄色免费网站 | 亚洲日韩精品欧美一区二区 | 亚洲美女视频在线观看 | 国产精品 日本 | 国产精品专区在线观看 | 欧美日韩国产欧美 | www色 | 婷婷国产视频 | 国产精品福利小视频 | 91视频电影 | 久久久久99精品国产片 | 密桃av在线 | 国产福利免费在线观看 | 欧美午夜久久久 | 欧美国产日韩在线观看 | 天堂在线成人 | 国产精品久久久久久婷婷天堂 | 一区二区中文字幕在线观看 | 91你懂的 | 性色视频在线 | 色在线高清 | av天天干 | 久久免费国产电影 | 狠狠色噜噜狠狠 | 99re8这里有精品热视频免费 | 麻豆久久一区二区 | 亚洲一区二区天堂 | 91精品视频免费看 | 黄色的视频网站 | 精品久久久免费视频 | 午夜黄网| 日韩一区二区三区不卡 | 久久草在线视频国产 | 四虎影视成人精品国库在线观看 | 日本精品一区二区三区在线播放视频 | 91视频成人免费 | 国产拍揄自揄精品视频麻豆 | 日韩在线观看不卡 | 久久69精品久久久久久久电影好 | a久久免费视频 | 深爱婷婷激情 | 久草在线资源免费 | 免费精品人在线二线三线 | 欧美性色黄 | 亚洲欧美激情精品一区二区 | 日韩中文字幕免费在线播放 | 黄色91免费观看 | 久久刺激视频 | 91人人爽人人爽人人精88v | 日本久久片 | 中文字幕丝袜一区二区 | 天天综合天天综合 | 在线免费观看欧美日韩 | 久久人人看 | 天天天在线综合网 | 在线观看麻豆av | 日韩性xxxx| 爱色婷婷| 天堂av在线网 | 日韩久久久久 | 六月色丁香 | 玖玖爱在线观看 | 深爱激情久久 | 深爱激情婷婷网 | 日韩av成人在线 | 日韩高清一二三区 | 九色自拍视频 | 天天干天天干天天射 | 久久精品99北条麻妃 | 欧美电影黄色 | 久久免费黄色 | 久久激情日本aⅴ | 最新国产精品久久精品 | 国产精品美女www爽爽爽视频 | 99精品在线直播 | 久久久久综合网 | 久久久久免费视频 | 日韩欧美在线影院 | 国产午夜小视频 | 国产精品欧美久久久久无广告 | 综合久久2023 | 丝袜美腿一区 | 97超碰在线久草超碰在线观看 | 日韩中文字幕第一页 | 天天爽夜夜爽精品视频婷婷 | 91精品国产综合久久福利不卡 | 在线观看国产日韩 | 久久久久久久久久伊人 | 久久国产福利 | av不卡中文字幕 | 久久伊人五月天 | 久草免费在线观看 | 免费观看的黄色片 | 国产精品婷婷午夜在线观看 | 中文字幕精品三级久久久 | 91久久在线观看 | 五月天亚洲精品 | 西西444www大胆高清图片 | 日韩精品免费在线观看视频 | 国产色拍拍拍拍在线精品 | 国产午夜精品免费一区二区三区视频 | 亚洲精品国产精品国 | 人人爽人人爽人人 | 国产大尺度视频 | 国产精品美女久久久久久久久久久 | 免费黄色a网站 | 欧美精品国产综合久久 | 这里只有精彩视频 | 美女精品网站 | 国产成人精品一区二区三区免费 | 狠狠色丁香久久婷婷综 | 伊人资源站 | 免费国产一区二区视频 | 日韩久久久久久久久久久久 | 国产一区二区在线看 | 久久综合色天天久久综合图片 | 日本成人黄色片 | 国产黄色av影视 | 在线99热 | 欧美三级免费 | 久久99国产精品自在自在app | 国产一级电影网 | 国产人成在线视频 | 国产精品一区二区三区四区在线观看 | 国产一级一片免费播放放a 一区二区三区国产欧美 | 中文字幕 成人 | 天天翘av | 国产精品久久久毛片 | 久久九九九九 | 天天操天天爱天天爽 | 日韩一区二区三区高清免费看看 | 日韩理论在线 | 日日草av| 久久久夜色 | 五月天国产精品 | 亚洲高清在线观看视频 | 天天摸天天弄 | 最近在线中文字幕 | 女人18片 | 手机成人av | 日韩最新中文字幕 | 九色91视频| 日韩欧美视频在线播放 | av手机在线播放 | 在线观看激情av | 久久久久久久毛片 | 久久99热精品这里久久精品 | 99视频一区二区 | 色婷婷 亚洲 | 色91av| 五月婷婷操 | 91免费观看视频在线 | 黄色美女免费网站 | www.五月天婷婷 | 亚洲精品国产欧美在线观看 | 久草五月 | 国产 字幕 制服 中文 在线 | 久久伦理 | 91久久久久久久一区二区 | 丁香花中文字幕 | 亚洲成av人影院 | 成人午夜毛片 | 97碰在线| 99视频精品全部免费 在线 | a黄色片在线观看 | 日韩成人免费电影 | 国产精品毛片一区二区 | 欧美大码xxxx | japanesexxxhd奶水 国产一区二区在线免费观看 | 国产精品嫩草影视久久久 | 午夜视频一区二区 | 99久久久国产精品免费观看 | 免费观看视频黄 | 在线观看日韩精品 | 天天草av| 国产成人免费在线观看 | 国产成人一区二区三区 | 亚洲免费在线视频 | 91色偷偷 | 九九爱免费视频 | 国产免码va在线观看免费 | 精品一二三四视频 | 日躁夜躁狠狠躁2001 | 一级免费看 | 久久国产综合视频 | 九色视频网 | 99久久99精品 | 日韩69视频| 日日夜精品 | www视频免费在线观看 | 夜夜操天天操 | 日本黄色免费观看 | 国产成人精品一区二区三区 | 91视频免费 | 国产精品久久久久久久妇 | 中文国产字幕在线观看 | 亚洲成av人影片在线观看 | 国产一区二区免费看 | 天天视频色版 | 在线观看日韩免费视频 | 在线观看涩涩 | 久久久www成人免费精品 | 少妇bbw搡bbbb搡bbbb | 久久综合久久鬼 | 91中文在线 | 色综合a| 亚洲人成在线电影 | 激情亚洲综合在线 | 久久综合综合久久综合 | 国产h在线播放 | 国产亚洲精品bv在线观看 | 日韩av在线影视 | 国产精品一区二区av日韩在线 | 国语自产偷拍精品视频偷 | 欧美黑人性猛交 | 国产精品理论片 | 99久久精品国产系列 | 免费av一级电影 | 精品黄色在线观看 | 激情偷乱人伦小说视频在线观看 | 欧美在线日韩在线 | 久久国内精品视频 | 国产精品毛片一区视频播 | www.亚洲精品在线 | 成人h动漫精品一区二 | 日韩有色 | 中文字幕在线观看日本 | 成人av免费在线播放 | 国产婷婷久久 | 天天草天天干天天射 | 中文av字幕在线观看 | 国产精品久久一区二区三区不卡 | av解说在线 | 久久不卡免费视频 | 午夜视频久久久 | 国产精品亚 | 九草视频在线 | 免费成人在线观看 | 国产人在线成免费视频 | 亚洲精品婷婷 | 最近日本mv字幕免费观看 | 亚洲理论影院 | 欧美日一级片 | 欧美视频www | 免费看高清毛片 | 成人高清av在线 | 免费av网站在线 | 日韩久久一区 | 日韩高清免费电影 | 最新午夜电影 | 免费网站色 | 在线免费看黄网站 | 国产精品久久久久亚洲影视 | 成人日批视频 | 天天艹天天干天天 | 四虎国产视频 | 99视频在线免费播放 | v片在线播放 | 首页av在线 | 国产日韩欧美视频在线观看 | 四川bbb搡bbb爽爽视频 | 国产黄色一级片 | 亚洲国产精品人久久电影 | 日韩精品在线观看av | 国产视频在线观看免费 | 成人精品福利 | 四虎在线免费观看视频 | 国产成人三级一区二区在线观看一 | 日韩在线三区 | 99这里都是精品 | 亚洲精品字幕在线 | 久久久久久久久久久久久久免费看 | 黄色小说免费观看 | 九九免费精品视频在线观看 | 丁香六月综合网 | 天天操比 | 岛国大片免费视频 | 久久久久在线视频 | 热re99久久精品国产99热 | 日本性生活一级片 | 久香蕉| 一区二区三区视频 | 精品99在线视频 | 亚洲伦理电影在线 | 色综合天天综合网国产成人网 | 91大神精品视频 | 丁香婷婷在线 | 天天av天天 | 日本不卡一区二区 | 青青河边草观看完整版高清 | 国产精品不卡在线 | 日本丶国产丶欧美色综合 | 男女激情片在线观看 | 精品在线一区二区三区 | 亚洲日本一区二区在线 | 99视频精品 | 色婷婷色 | 欧美性极品xxxx做受 | 日韩r级电影在线观看 | 超碰夜夜 | 国产日韩高清在线 | 久久综合婷婷国产二区高清 | 国产精品九九九九九九 | 午夜精品久久久久久久久久久久久久 | 天天插天天 | 免费av大全 | 成人网页在线免费观看 | 黄色小说视频网站 | 中文乱码视频在线观看 | 欧美精品v国产精品 | 永久黄网站色视频免费观看w | 精品国自产在线观看 | 亚洲视频精选 | 在线中文日韩 | 日本黄色大片免费 | 97视频在线免费 | 五月开心网 | 日韩免费在线网站 | 草久在线观看 | 免费一级日韩欧美性大片 | 亚洲精品一区二区久 | 91色九色 | 久久精品一区二区三区国产主播 | 在线视频欧美精品 | 久久激情影院 | 天天干夜夜| 色91av| 韩国在线一区二区 | 狠狠干天天色 | 欧美地下肉体性派对 | 国产一区二区不卡在线 | 亚洲国产电影在线观看 | 日日夜夜免费精品 | 成人影片在线播放 | 92av视频 | 国产精品久久久久久久久大全 | www178ccom视频在线| 欧美伦理一区二区三区 | 一区二区三区在线视频观看58 | 在线电影 你懂得 | 色伊人网 | 在线观看深夜福利 | 欧洲精品码一区二区三区免费看 | 亚洲精品久久久久999中文字幕 | 欧美精品亚洲精品日韩精品 | 五月婷av | 九九热在线视频 | 国产亚洲精品久久久久久移动网络 | 国产 一区二区三区 在线 | 欧美色就是色 | 极品久久久久久久 | 最新99热 | 三级性生活视频 | 婷婷国产v亚洲v欧美久久 | 婷婷六月综合亚洲 | 最新中文字幕 | 中文字幕91在线 | 人人爱爱人人 | 国产在线成人 | 日韩专区视频 | 国产手机视频在线播放 | 在线黄色毛片 | 69视频永久免费观看 | 免费中文字幕在线观看 | 久久久久观看 | 狠狠躁日日躁狂躁夜夜躁av | 天天艹日日干 | 精品福利视频在线 | 在线观看小视频 | 久久激情影院 | 麻豆 91 在线| 中文在线a∨在线 | 亚洲国产福利视频 | 成人免费av电影 | 婷婷 综合 色 | 玖玖在线精品 | 久碰视频在线观看 | 久久久久国产精品视频 | 日韩激情一二三区 | 亚洲视频 在线观看 | 国产区久久 | 九九九免费视频 | 色网站在线 | 国产精彩视频一区 | 国产精品成人自拍 | 日韩精品不卡 | 久久久影院官网 | 美女在线黄 | 91在线日本 | 成人黄色影片在线 | 在线观看成人国产 | 一区二区理论片 | 亚洲丁香久久久 | 91香蕉国产在线观看软件 | 色天天中文 | 久久久精品国产一区二区 | 国产中文字幕av | 超碰人人91 | 久久国内视频 | 色婷婷久久久综合中文字幕 | 公开超碰在线 | 国产二区av| 九九九热精品免费视频观看 | 天天草天天干天天射 | 亚洲天堂毛片 | 在线观看中文字幕 | 黄色片视频在线观看 | 亚洲精选视频在线 | 粉嫩一区二区三区粉嫩91 | 亚洲 中文 在线 精品 | 国产精品一区二区62 | 久久国产精品免费 | 91色一区二区三区 | 日本系列中文字幕 | 色免费在线 | 在线看av的网址 | 国产成人区 | 久草在线免费看视频 | 91大神一区二区三区 | 久久久久久国产精品999 | 97超碰成人在线 | 亚洲精品综合欧美二区变态 | 18国产精品白浆在线观看免费 | 免费在线观看日韩 | 粉嫩av一区二区三区免费 | 香蕉视频国产在线观看 | 欧美色综合天天久久综合精品 | 操操日日 | 97日日碰人人模人人澡分享吧 | 片网址 | 亚洲伦理中文字幕 | 四虎永久免费在线观看 | 久久99热久久99精品 | 欧美大香线蕉线伊人久久 | 日日干视频 | 欧美日韩成人 | 69亚洲视频 | 欧美色综合久久 | 97成人免费 | 成人av高清| 涩av在线| 久久女教师 | 精品人人爽 | 亚洲国产免费网站 | 日韩在线高清视频 | 人人爱人人爽 | 一区二区三区在线免费播放 | 成人丁香花 | 天天天综合 | 免费在线电影网址大全 | 久久综合精品一区 | 国产视频一区二区在线播放 | 国产h在线观看 | 日韩视频在线不卡 | 国产精品一级视频 | 一区二区三高清 | 奇米影视在线99精品 | 免费观看国产视频 | 久久久久久久久毛片精品 | 国产91aaa| 久久国产网站 | 在线观看视频91 | 久久夜色精品亚洲噜噜国4 午夜视频在线观看欧美 | 免费一级特黄毛大片 | 国产男女免费完整视频 | 日韩一区二区三区不卡 | 狠狠狠色丁香婷婷综合激情 | 一区二区av | 国产精品免费久久久久影院仙踪林 | 久久久久久久久久久电影 | 国产在线精 | 亚洲精品国产成人av在线 | 国产精品久久久久久吹潮天美传媒 | 国产精品免费麻豆入口 | 天天综合视频在线观看 | 天堂在线视频免费观看 | 欧美 日韩 国产 中文字幕 | 欧美成人手机版 | 欧美激情视频一区 | 丁香导航| 麻豆国产网站入口 | 国产精品尤物视频 | 狠狠躁18三区二区一区ai明星 | 国产精品videoxxxx | 亚洲乱码国产乱码精品天美传媒 | 日韩网站在线观看 | 精品久久久久久亚洲综合网 | 999一区二区三区 | 亚洲天堂精品视频 | 黄网站色欧美视频 | 91网站观看 | 亚洲精品一区二区三区在线观看 | 久久超级碰 | 中文av资源站 | 久热电影 | 国产亚洲高清视频 | 久艹在线免费观看 | 成人免费大片黄在线播放 | 国产免费激情久久 | 黄色一级免费 | 亚洲精品视频大全 | 天天曰天天 | 日本中文字幕观看 | 在线免费观看欧美日韩 | 综合网在线视频 | 97精品超碰一区二区三区 | 美女黄网久久 | 国产香蕉视频 | 国产看片免费 | www.伊人网 | 国产精品美女久久久久久久久久久 | 九九天堂| 国产美女精彩久久 | 国产美女视频黄a视频免费 久久综合九色欧美综合狠狠 | 福利久久久 | 久草在线视频资源 | 色综合中文综合网 | 天天摸天天干天天操天天射 | 国产日韩在线视频 | 最近免费在线观看 | 久久九九网站 | 日日激情 | 成人a视频在线观看 | 日韩在线小视频 | 一二三区在线 | 亚洲欧洲精品久久 | 国产精品高潮呻吟久久久久 | 狠狠操在线 | 国产香蕉97碰碰久久人人 | 国产精品美女久久久久久久 | 国产一区二区视频在线播放 | 久久成人18免费网站 | 久久高清免费观看 | 一区二区视频免费在线观看 | 免费看污网站 | 麻豆小视频在线观看 | 国产精品大片免费观看 | 成 人 黄 色 免费播放 | 日韩视频一区二区在线观看 | 天天射一射 | 成人在线免费视频 | 国产高清精| 成人sm另类专区 | 日日爽天天 | 午夜精品在线看 | 久久影视一区 | 亚洲综合在线观看视频 | 91一区在线观看 | 久久免费视频网站 | 天天干夜夜爱 | 成 人 黄 色 免费播放 | 天天色成人网 | 国产成人a亚洲精品v | 99999精品 |