程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 基於Delphi API寫的UDP通訊類

基於Delphi API寫的UDP通訊類

編輯:Delphi

基於Delphi API寫的UDP通訊類,可以廣播和單播,類作者:王彥鵬。這個類是作者2007年的時候寫的,代碼裡基本沒什麼注釋,有需要的朋友自己摸索下,懂Delphi的應該可以看懂。

unit TUdp_Class;
interface
uses
  Classes,Windows,WinSock;
type
  TRecv= procedure (RIP:string;buf:pchar;Bufsize:integer) of object;
  TRecvExpand= procedure (RIP:string;Port:integer;buf:pchar;Bufsize:integer) of object;
  TUdp = class(TThread)
  private
    WSocket:TSocket;
    FActive:Boolean;
    FPort,FSendPort:integer;
    Addr: TSockAddr;
    FSockAddrIn : TSockAddrIn;
    FOnRecv:TRecv;
    FOnRecvExpand:TRecvExpand;
    Rtl:TRTLCriticalSection;
    procedure SetPort(Value:integer);
    procedure SetOnRecv(value:TRecv);
    procedure SetOnRecvExpand(value:TRecvExpand);
    function GetCurPort:integer;
    { Private declarations }
  protected
    procedure Execute; override;
  public                    
    constructor Create;
    destructor Destroy; override;
    function SendBuf(Host:string;Buf:pchar;BufSize:integer;Broadcast:boolean=false):integer;
    Function GetLocalIP():string;
  published
    property Port:integer read FPort write SetPort default 0;
    property SendPort:integer read FSendPort write FSendPort default 0;
    property OnRecv:TRecv read FOnRecv write SetOnRecv;
    property OnRecvExpand:TRecvExpand read FOnRecvExpand write SetOnRecvExpand;
    property CurPort:Integer read GetCurPort;
  end;
implementation
uses SysUtils;
{ TUdp }
constructor TUdp.Create();
var wsadata: Twsadata;
begin
  InitializeCriticalSection(rtl);
  if wsastartup($2, wsadata) <> 0 then
  begin
    Raise Exception.Create(SysErrorMessage(GetLastError));
  end
  else
    WSocket:=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
  if WSocket= INVALID_SOCKET then
    Raise Exception.Create(SysErrorMessage(GetLastError))
  else
    inherited create(true);
end;
destructor TUdp.Destroy;
begin
  closesocket(WSocket);
  wsacleanup();
  DeleteCriticalSection(Rtl);
  inherited;
end;
procedure TUdp.Execute;
var
  buf: pchar;
  Len: integer;
  FDS:TFDSet;
  TimeOut:TimeVal;
begin
  buf := AllocMem(10240);
  timeout.tv_sec := 0;
	timeout.tv_usec := 10;
  FSockAddrIn.SIn_Port := htons(FPort);
  while not Terminated do
  begin
    EnterCriticalSection(rtl);
    fillchar(Fds,sizeof(Fds),0);
    FD_SET(WSocket ,fds);
    len:=select(0,@fds,nil,nil,@TimeOut);
    if len>0 then
    begin
      len:=sizeof(FSockAddrIn);
      fillchar(buf[0],10240,0);
      len := recvfrom(WSocket, buf[0], 10240, 0,FSockAddrIn,len);
      if (len<>0) and (len<>-1) then
      begin
        if Assigned(fonRecv) then
          FOnRecv(inet_ntoa(FSockAddrIn.sin_addr) ,buf,len);
        if Assigned(fOnRecvExpand) then
          FOnRecvExpand(inet_ntoa(FSockAddrIn.sin_addr),htons(FSockAddrIn.sin_port),buf,len);
      end;
    end;
    LeaveCriticalSection(rtl);
    sleep(10);
  end;
  freemem(buf);
  closesocket(WSocket);
end;


function TUdp.GetCurPort: integer;
begin
  Result:=htonl(FSockAddrIn.SIn_Port);
end;

function TUdp.GetLocalIP(): string;
var
    HostEnt: PHostEnt;
    Ip: string;
    addr: pchar;
    Buffer: array [0..63] of char;
    GInitData: TWSADATA;
begin
  Result := '';
  try
    WSAStartup(2, GInitData);
    GetHostName(Buffer, SizeOf(Buffer));
    HostEnt := GetHostByName(buffer);
    if HostEnt = nil then Exit;
    addr := HostEnt^.h_addr_list^;
    ip := Format('%d.%d.%d.%d', [byte(addr [0]),
          byte (addr [1]), byte (addr [2]), byte (addr [3])]);
    Result :=Ip;
  finally
    WSACleanup;
  end;
end;

function TUdp.SendBuf(Host: string; Buf:pchar; BufSize: integer;Broadcast:boolean=false  ): integer;
var optval:integer;
begin
  if Broadcast then
  begin
    optval:= 1;
    if setsockopt(WSocket,SOL_SOCKET,SO_BROADCAST,pchar(@optval),sizeof(optval)) = SOCKET_ERROR then
       Raise Exception.Create(SysErrorMessage(GetLastError))
    else
    begin
      FSockAddrIn.SIn_Family := AF_INET;
      FSockAddrIn.SIn_Port := htons(FSendPort);
      FSockAddrIn.SIn_Addr.S_addr := INADDR_BROADCAST;
      result:=sendto(WSocket,buf[0],BufSize,0,FSockAddrIn,sizeof(FSockAddrIn));
    end;
  end
  else
  begin
    FSockAddrIn.SIn_Family := AF_INET;
    FSockAddrIn.SIn_Port := htons(FSendPort);
    FSockAddrIn.SIn_Addr.S_addr :=inet_addr(pchar(host));
    result:=sendto(WSocket,buf[0],BufSize,0,FSockAddrIn,sizeof(FSockAddrIn));
  end;
end;

procedure TUdp.SetOnRecv(value: TRecv);
begin
  if @FOnRecv = @value then
    exit;
  FOnRecv:=value;
  Addr.sin_family := AF_INET;
  addr.sin_addr.S_addr := INADDR_ANY;
  addr.sin_port := htons(FPort);
  if Bind(WSocket, addr, sizeof(addr)) <> 0  then
    Raise Exception.Create(SysErrorMessage(GetLastError));
  Resume;
end;

procedure TUdp.SetOnRecvExpand(value:TRecvExpand);
begin
  if @FOnRecvExpand = @value then
    exit;
  FOnRecvExpand:=value;
  Addr.sin_family := AF_INET;
  addr.sin_addr.S_addr := INADDR_ANY;
  addr.sin_port := htons(FPort);
  if Bind(WSocket, addr, sizeof(addr)) <> 0  then
    Raise Exception.Create(SysErrorMessage(GetLastError));
  Resume;
end;

procedure TUdp.SetPort(Value: integer);
begin
  if FPort =Value then
    exit;
  if FActive then
    Suspend;
  FPort:=Value;
end;
end.
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved