首先我把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;
http://blog.sina.com.cn/s/blog_562349090101dizl.html