首先我把UDP无连接协议的套接字调用时序图表示出来
在我把在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;
|
请发表评论