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

📄 mudt.pas

📁 DELPHI 封装的UDT类库..可以在DELPHI使用开源的UDT类库.
💻 PAS
字号:
Unit mudt;

Interface

{$INCLUDE mcompile.inc}

 Uses
  SysUtils, Classes, udt,
  {$ifdef KYLIX}
  Libc,
  {$else}
  Windows, Winsock, JwaWinsock2, JwaWS2tcpip,
  {$ENDIF}
  StrUtils, SyncObjs;

 Const
  DEFAULT_PORT = '6000';
  DEFAULT_BUF_LEN = 1048576;

 Type
  TMUDT = Class;

  TMUDTListenThread = Class(TThread)
  Public
   Host: TMUDT;
   Procedure Execute; Override;
  End;

  TMUDTRecvThread = Class(TThread)
  Public
   PeerIP: String;
   PeerPort: String;
   Data: pChar;
   Host: TMUDT;
   socket: UDTSOCKET;
   Procedure Execute; Override;
  End;

  TMUDTOnDataReceived = Procedure (Thread: TMUDTRecvThread; Data: pChar; len: Integer) Of Object;

  TMUDT = Class(TComponent)
  Private
   CS: TCriticalSection;
   FPort: String;
   FPeerIP: String;
   FPeerPort: String;
   FLastError: String;
   FBindLocalPort: Boolean;
   FConnected: Boolean;
   socket: UDTSOCKET;
   servThread: TMUDTListenThread;
   FOnDataReceived: TMUDTOnDataReceived;
   FOnSocketLost: TNotifyEvent; 
  Public
   Property Port: String Read FPort Write FPort;
   Property PeerIP: String Read FPeerIP Write FPeerIP;
   Property PeerPort: String Read FPeerPort Write FPeerPort;
   Property LastError: String Read FLastError;
   Property BindLocalPort: Boolean Read FBindLocalPort Write FBindLocalPort;
   Property Connected: Boolean Read FConnected;
   Property OnDataReceived: TMUDTOnDataReceived Read FOnDataReceived Write FOnDataReceived;
   Property OnSocketLost: TNotifyEvent Read FOnSocketLost Write FOnSocketLost;
   Constructor Create(AOwner: TComponent); Override;
   Destructor Destroy; Override;
   Procedure Connect;
   Function Send(data: pChar; len: Integer): Boolean;
   Procedure Close;
   Function Listen: Boolean;
  End;

Procedure Register;

Implementation

Procedure Register;
 Begin
  RegisterComponents('Kirikawa Kits', [TMUDT]);
 End;

Constructor TMUDT.Create(AOwner: TComponent);
 Begin
  Inherited;
  CS := TCriticalSection.Create;
  FPort := DEFAULT_PORT;
  socket := INVALID_SOCK;
  FBindLocalPort := False;
  FConnected := False;
 End;

Destructor TMUDT.Destroy;
 Begin
  CS.Free;
  Inherited;
 End;

Procedure TMUDT.Connect;
 Var
  hints: addrinfo;
  local, peer: pAddrInfo;
  size: Integer;
 Begin
  FillChar(hints, sizeof(addrinfo), #0);
  hints.ai_flags := AI_PASSIVE;
  hints.ai_family := AF_INET;
  hints.ai_socktype := Integer(SOCK_DGRAM);
  If GetAddrInfo(Nil, pChar(FPort), @hints, local) <> 0 Then
   Begin
    FLastError := 'Incorrect network address.';
    Exit;
   End;
  socket := UDT.socket(local^.ai_family, local^.ai_socktype, local^.ai_protocol);
  {$ifdef DELPHI}
  size := 1052;
  UDT.setsockopt(socket, 0, UDT_MSS, @size, 4);
  {$endif}
  If FBindLocalPort Then
   If UDT.bind(socket, local^.ai_addr, local^.ai_addrlen) = UDT.ERROR Then
    Begin
     FLastError := 'Bind failed: ' + StrPas(udt.getlasterror);
     FreeAddrInfo(local);
     Exit;
    End;
  FreeAddrInfo(local);
  If GetAddrInfo(pChar(FPeerIP), pChar(FPeerPort), @hints, peer) <> 0 Then
   Begin
    FLastError := 'Incorrect server/peer address: ' + FPeerIP + '/' + FPeerPort;
    Exit;
   End;
  If UDT.connect(socket, peer^.ai_addr, peer^.ai_addrlen) = UDT.ERROR Then
   Begin
    FLastError := 'Connect: ' + StrPas(UDT.getlasterror);
    FreeAddrInfo(peer);
    Exit;
   End;
  FreeAddrInfo(peer);
  FConnected := True;
 End;

Function TMUDT.Send(data: pChar; len: Integer): Boolean;
 Var
  i: Integer;
 Begin
  Result := False;
  If Not FConnected Then
   Begin
    FLastError := 'Socket not connected yet.';
    Exit;
   End;
  i := UDT.sendmsg(socket, data, len, -1, true);
  If i = UDT.ERROR Then
   Begin
    FLastError := 'Send: ' + StrPas(udt.GetLastError);
    Close;
    Exit;
   End;
  Result := True; 
 End;

Procedure TMUDT.Close;
 Begin
  FConnected := False;
  If socket <> INVALID_SOCK Then UDT.close(socket);
  socket := INVALID_SOCK;
 End;

Function TMUDT.Listen: Boolean;
 Var
  hints: AddrInfo;
  res: pAddrInfo;
 Begin
  Result := True;
  If FConnected Then
   Begin
    FLastError := 'Already connected. Close first or create a new one.';
    Exit;
   End;
  FillChar(hints, SizeOf(AddrInfo), 0);
  hints.ai_flags := AI_PASSIVE;
  hints.ai_family := AF_INET;
  //hints.ai_socktype := Integer(SOCK_STREAM);
  hints.ai_socktype := Integer(SOCK_DGRAM);
  If GetAddrInfo(Nil, pChar(FPort), @hints, res) <> 0 Then
   Begin
    FLastError := 'Illegal port number or port is busy.';
    Exit;
   End;

  socket := UDT.socket(res.ai_family, res.ai_socktype, res.ai_protocol);

  // UDT Options
  //UDT::setsockopt(serv, 0, UDT_CC, new CCCFactory<CUDPBlast>, sizeof(CCCFactory<CUDPBlast>));
  //UDT::setsockopt(serv, 0, UDT_MSS, new int(9000), sizeof(int));
  //UDT::setsockopt(serv, 0, UDT_RCVBUF, new int(10000000), sizeof(int));
  //UDT::setsockopt(serv, 0, UDP_RCVBUF, new int(10000000), sizeof(int));

  If UDT.bind(socket, res.ai_addr, res.ai_addrlen) = UDT.ERROR Then
   Begin
    FLastError := 'bind: ' + UDT.GetLastError;
    FreeAddrInfo(res);
    Exit;
   End;

  FreeAddrInfo(res);

  If UDT.listen(socket, 10) = UDT.ERROR Then
   Begin
    FLastError := 'listen: ' + UDT.getlasterror;
    Exit;
   End;

  FConnected := True;
  servThread := TMUDTListenThread.Create(True);
  servThread.FreeOnTerminate := True;
  servThread.Host := self;
  servThread.Resume;
  Result := True;
 End;

{* TMUDTListenThread *}

Procedure TMUDTListenThread.Execute;
 Var
  clientaddr: sockaddr_storage;
  recver: UDTSOCKET;
  Addrlen: Integer;
  dSockAddr: SockAddr;
  clienthost: Array [0..NI_MAXHOST - 1] Of Char;
  clientservice: Array [0..NI_MAXSERV - 1] Of Char;
  socket: Integer;
  client: TMUDTRecvThread;
 Begin
  Addrlen := SizeOf(clientaddr);
  socket := Host.socket;
  While Not Terminated Do
   Begin
    Move(clientaddr, dSockAddr, SizeOf(dSockAddr));
    recver := UDT.accept(socket, @dSockAddr, @addrlen);
    If recver = UDT.INVALID_SOCK Then
     Begin
      Host.FLastError := StrPas(UDT.GetLastError);
      Host.FConnected := False;
      Break;
     End;
    {$IFDEF DELPHI}
    GetNameinfo(@dSockAddr, addrlen, clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NUMERICHOST Or NI_NUMERICSERV);
    {$ENDIF}
    {$IFDEF KYLIX}
    GetNameinfo(dSockAddr, addrlen, clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NUMERICHOST Or NI_NUMERICSERV);
    {$ENDIF}
    client := TMUDTRecvThread.Create(True);
    client.FreeOnTerminate := True;
    client.socket := recver;
    client.PeerPort := ClientService;
    client.PeerIP := ClientHost;
    client.Host := Host;
    client.Resume;
   End;

  udt.close(socket);
  If Assigned(Host.FOnSocketLost) Then Host.FOnSocketLost(Host);
 End;

{* TMUDTRecvThread *}

Procedure TMUDTRecvThread.Execute;
 Var
  data: pChar;
  size: Integer;
  rs: Integer;
 Begin
  size := DEFAULT_BUF_LEN;
  data := AllocMem(size);
  While Not Terminated Do
   Begin
    rs := UDT.recvmsg(socket, data, size);
    If rs = UDT.ERROR Then
     Begin

      Break;
     End;
    If rs > 0 Then
     If Assigned(Host.FOnDataReceived) Then
      Host.FOnDataReceived(self, data, rs);
   End;

  FreeMem(data, size);
  UDT.close(socket);
 End;

End.

⌨️ 快捷键说明

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