• 在Delphi中关于UDP协议的实现


    首先我把UDP无连接协议的套接字调用时序图表示出来

    Winsocket编程之套接字原理

    在我把在Delphi中使用UDP协议实现数据通讯收发的实现方法总结如下:

    例子描述:下面例子是我的一个实际设备通讯的例子,使用UDP协议在4660端口上发送'F1,00'(16进制,2个字节),在同一个端口上接收到'F1,00,00,00,00,00'((16进制,2个字节))

    1.使用底层函数来实现

    procedure TForm1.FormCreate(Sender: TObject);
    var
    WSAData:TWSAData;
    begin
    edtHost.Text:=192.168.1.222';
    edtPort.Text:='4660';
    //1.初始化Winsock
    if (WSAStartup(MAKEWORD(2,0),WSAData)<>0) then
    begin
    //初始化失败
    memInfo.Lines.Add('Winsock Init Failed');
    exit;
    end
    else
    memInfo.Lines.Add('Socket Start');
    end;
    procedure TForm1.btnFingerClick(Sender: TObject);
    var
    Info:string;
    BufSend,BufRecv:array[0..1024] of byte;
    skt:TSOCKET;
    addr:TSockAddr;
    Re:Integer;
    S:String;
    i:Integer;
    begin

    //=====================数据发送=========================================
    //2.建立socket
    skt:=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
    if(skt=INVALID_SOCKET)then
    begin
    memInfo.Lines.Add('Error:Create socket failed!');
    exit;
    end;
    //3.连接主机
    ZeroMemory(@addr,sizeof(addr));
    addr.sin_family :=AF_INET;
    addr.sin_addr.s_addr :=inet_addr('192.168.1.222');
    addr.sin_port:=htons(4660);
    Re := connect(skt,addr,sizeof(addr));
    if(Re<>0)then
    begin
    memInfo.Lines.Add('Connect to server failed');
    exit;
    end;
    //4.发送信息
    BufSend[0]:=$F1;
    BufSend[1]:=0;
    Re:=send(skt,BufSend,2,0);
    if(Re=SOCKET_ERROR)then
    begin
    memInfo.Lines.Add('Send Data Failed');
    exit;
    end;
    //6.关闭socket
    closesocket(skt);
    //=============接收数据的==================================

    //2.建立socket
    skt:=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
    if(skt=INVALID_SOCKET)then
    begin
    memInfo.Lines.Add('Error:Create socket failed!');
    exit;
    end;
    //3.绑定主机
    ZeroMemory(@addr,sizeof(addr));
    addr.sin_family :=AF_INET;
    addr.sin_addr.s_addr :=inet_addr('192.168.1.106');
    addr.sin_port:=htons(4660);
    Re := Bind(skt,addr,sizeof(addr));
    if(Re<>0)then
    begin
    memInfo.Lines.Add('Connect to server failed');
    exit;
    end;
    //4.接收信息
    Re:=Recv(skt,BufRecv,6,0);
    if(Re=SOCKET_ERROR)then
    begin
    memInfo.Lines.Add('Send Data Failed');
    exit;
    end
    else
    begin
    S:='';
    for i:=0 to Re-1 do
    begin
    S:=S+IntToHex(Integer(BufRecv[i]),2);
    end;
    memInfo.Lines.Add(S);
    end;
    //6.关闭socket
    closesocket(skt);
    end;
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
    //6.释放Winsock
    WSACleanUP();
    end;

    2.使用TUDPSocket组件实现

    TUDPSocket组件是继承于TCustomIPClient的。它被设计为只能当作一个客户端来用

    所以它是不能直接用来接收数据的,要是实现接收必须另外定义一个接收的TIPSocket,重新绑定接口.

    type
    TForm2 = class(TForm)
    UdpSocket1: TUdpSocket;
    Button1: TButton;
    UdpSocket2: TUdpSocket;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    private
    { Private declarations }
    public
    { Public declarations }
    aUDPServer:TIPSocket;
    end;

    var
    Form2: TForm2;

    implementation

    {$R *.dfm}

    procedure TForm2.FormCreate(Sender: TObject);
    var
    addr:sockAddr_In;
    begin
    UdpSocket1.RemoteHost:='192.168.1.222';
    UdpSocket1.RemotePort:='4660';
    UdpSocket1.Open ;

    aUDPServer:=TIPSocket.Create(nil);
    aUDPServer.RemoteHost:='192.168.1.222';
    aUDPServer.RemotePort:='4660';
    aUDPServer.LocalHost:=aUDPServer.LocalHostName;
    aUDPServer.LocalPort:='4660';
    aUDPServer.Protocol:=IPPROTO_UDP;
    aUDPServer.SockType:=stDgram;
    aUDPServer.Active:=true;
    addr:=aUDPServer.GetSocketAddr(aUDPServer.LocalHost,aUDPServer.LocalPort);
    bind(aUDPServer.Handle,addr,sizeof(addr));

    end;

    procedure TForm2.Button1Click(Sender: TObject);
    var
    ReceivedString:string;
    Buff:array[0..1] of byte;
    RevBuf:array[0..1024] of byte;
    RevSize:Integer;
    i:Integer;
    S:string;
    ToAddr:sockAddr_In;
    Len:integer;
    a:in_Addr;
    begin
    Buff[0]:=$F1;
    Buff[1]:=0;
    UdpSocket1.SendBuf(Buff,2);
    ToAddr:=UdpSocket2.GetSocketAddr(UdpSocket2.LocalHost,UdpSocket2.LocalPort);
    bind(UdpSocket2.Handle,ToAddr,sizeof(ToAddr));
    RevSize:=UdpSocket2.ReceiveBuf(RevBuf,6) ;
    S:='';
    for i:=0 to RevSize-1 do
    begin
    S:=S+IntToHex(Integer(RevBuf[i]),2);
    end;
    ShowMessage(S);
    end;
    3.使用TIdUDPClient组件实现

    TIdUDPClient组件中重新绑定了一个Socket,用来专门接收数据,所以本身一个组件就可以实现接收

    procedure TForm1.Button1Click(Sender: TObject);
    var
    ReceivedString:string;
    Buff:array[0..1] of byte;
    RevBuf:array[0..1024] of byte;
    RevSize:Integer;
    i:Integer;
    S:string;
    begin
    Buff[0]:=$F1;
    Buff[1]:=0;
    IdUDPClient1.SendBuffer(Buff,2);
    RevSize:=IdUDPClient1.Binding.Recv(RevBuf,6,0);
    S:='';
    for i:=0 to RevSize-1 do
    begin
    S:=S+IntToHex(Integer(RevBuf[i]),2);
    end;
    ShowMessage(S);
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
    IdUDPClient1.Host:='192.168.1.222';
    IdUDPClient1.Binding.Port:=4660;
    IdUDPClient1.Binding.Bind;
    IdUDPClient1.Active:=True;

    end;
    3.使用TNMUDP组件实现

    这里我发现在第一次运行时,要连续按两次按钮,才能收到数据

    procedure TForm1.BitBtn2Click(Sender: TObject);
    var
    Buf:array[0..1] of char;
    RevBuf :array[0..1024] of char;
    ss:string;
    i:integer;
    Len:Integer;
    begin

    Buf[0]:=char($F1);
    Buf[1]:=char(0);
    NMUDP1.SendBuffer(Buf[0],2);
    NMUDP1.ReadBuffer(RevBuf[0],Len);
    if Len>0 then
    begin
    ss:='';
    for i:=1 to Len do
    begin
    ss:=ss + intToHex(integer(RevBuf[i]),2);
    end;
    ShowMessage(ss);
    end;

    end;

  • 相关阅读:
    BZOJ1901(主席树+树状数组 实现“动态主席树”)
    BZOJ2460: [BeiJing2011]元素(线性基+贪心)
    BZOJ4448: [Scoi2015]情报传递(主席树)
    详解mysql int类型的长度值问题【转】
    数据库设计三范式【转】
    aliyun阿里云Maven仓库地址——加速你的maven构建
    VMware 设备VMnet0 上的网桥暂时关闭。此虚拟机无法与主机或网格中的其他计算机通信【转】
    Maven项目中的pom.xml详解【转】
    直接启动tomcat时为tomcat指定JDK
    Spring自动注入properties文件
  • 原文地址:https://www.cnblogs.com/MaxWoods/p/1774936.html
Copyright © 2020-2023  润新知