我以前测试的时候写过一个程序,在两台机器上运行可以相互发消息。发送和接收的消息都保存在一个listbox里,接收到的消息以*号开头,发送的消息以-号开头,发出的消息如果对方有回应,前面的-号变成+号。
unit UdpMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, blcksock;
const
WM_TERMINATE = WM_USER + 1;
WM_UDPDOSEND = WM_USER + 2;
WM_UDPRECVED = WM_USER + 51;
type
TUDPRecvThread = class(TThread)
public
procedure Execute; override;
end;
TUDPSendThread = class(TThread)
public
procedure Execute; override;
end;
TUDPForm = class(TForm)
Label1: TLabel;
ListMsg: TListBox;
EdAddrTo: TEdit;
Label2: TLabel;
EdPortTo: TEdit;
Label3: TLabel;
Panel1: TPanel;
Label4: TLabel;
Label5: TLabel;
EdAddrSocks: TEdit;
Label6: TLabel;
EdPortSocks: TEdit;
Label7: TLabel;
EdUserName: TEdit;
Label8: TLabel;
EdPassword: TEdit;
BtnSend: TButton;
Label9: TLabel;
EdMsg: TEdit;
Label10: TLabel;
EdPortLocal: TEdit;
BtnStart: TButton;
BtnExit: TButton;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure BtnSendClick(Sender: TObject);
procedure BtnExitClick(Sender: TObject);
procedure BtnStartClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure OnUDPRecved(var ms: TMessage); message WM_UDPRECVED;
end;
var
UDPForm: TUDPForm;
implementation
{$R *.dfm}
var MsgIn, MsgOut: string;
UDPSock: TUDPBlockSocket;
UDPRecv: TUDPRecvThread;
UDPSend: TUDPSendThread;
Sending: Boolean;
procedure TUDPRecvThread.Execute;
var m, n: Integer;
s: string;
begin
FreeOnTerminate := True;
while not Terminated do
begin
MsgIn := UDPSock.RecvPacket(3000);
if UDPSock.LastError = 0 then
begin
if MsgIn[1] = 'R' then
begin
Delete(MsgIn, 1, 1);
Val(MsgIn, m, n);
if n = 0 then PostMessage(UDPForm.Handle, WM_UDPRECVED, m, 0);
end
else if MsgIn[1] = 'M' then
begin
Delete(MsgIn, 1, 1);
n := Pos('M', MsgIn);
if n > 0 then
begin
s := 'R' + Copy(MsgIn, 1, n - 1);
Delete(MsgIn, 1, n);
MsgIn := '*[' + UDPSock.GetRemoteSinIP + ':' + IntToStr(UDPSock.GetRemoteSinPort)
+ ']' + MsgIn;
UDPSock.SendBufferTo(@s[1], Length(s));
PostMessage(UDPForm.Handle, WM_UDPRECVED, -1, 0);
Suspend;
end;
end;
end;
end;
UDPRecv := nil;
end;
procedure TUDPSendThread.Execute;
var ms: MSG;
begin
FreeOnTerminate := True;
while not Terminated do
begin
GetMessage(ms, 0, 0, 0);
case ms.message of
WM_UDPDOSEND:
begin
if Length(MsgOut) > 0 then with UDPSock, UDPForm do
begin
SocksIp := EdAddrSocks.Text;
SocksPort := EdPortSocks.Text;
SocksUsername := EdUsername.Text;
SocksPassword := EdPassword.Text;
Connect(EdAddrTo.Text, EdPortTo.Text);
SendString(MsgOut);
Sending := False;
end;
end;
WM_TERMINATE: Terminate;
end;
end;
UDPSend := nil;
end;
procedure TUDPForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
BtnExitClick(Sender);
Action := caFree;
end;
procedure TUDPForm.BtnSendClick(Sender: TObject);
var n: Integer;
begin
if Sending then
begin
ShowMessage('上一条消息还未发送完成,请稍候!');
Exit;
end;
Sending := True;
n := ListMsg.Count;
MsgOut := 'M' + IntToStr
+ 'M' + EdMsg.Text;
ListMsg.Items.Append('-[' + EdAddrTo.Text + ':' + EdPortTo.Text + ']' + EdMsg.Text);
PostThreadMessage(UDPSend.ThreadID, WM_UDPDOSEND, 0, 0);
end;
procedure TUDPForm.OnUDPRecved(var ms: TMessage);
var s: string;
begin
if ms.WParam < 0 then
begin
ListMsg.Items.Append(MsgIn);
UDPRecv.Resume;
Exit;
end;
s := ListMsg.Items[ms.WParam];
s[1] := '+';
ListMsg.Items[ms.WParam] := s;
end;
procedure TUDPForm.BtnExitClick(Sender: TObject);
begin
if Assigned(UDPRecv) then UDPRecv.Terminate;
if Assigned(UDPSend) then PostThreadMessage(UDPSend.ThreadID, WM_TERMINATE, 0, 0);
while Assigned(UDPRecv) do Sleep(100);
while Assigned(UDPSend) do Sleep(100);
if Assigned(UDPSock) then
begin
UDPSock.CloseSocket;
UDPSock.Free;
UDPSock := nil;
end;
BtnStart.Enabled := True;
EdMsg.Enabled := False;
BtnSend.Enabled := False;
EdPortLocal.Enabled := True;
BtnExit.Enabled := False;
end;
procedure TUDPForm.BtnStartClick(Sender: TObject);
begin
BtnStart.Enabled := False;
Sending := False;
UDPSock := TUDPBlockSocket.Create;
with UDPSock do Bind(ResolveName(LocalName), EdPortLocal.Text);
UDPRecv := TUDPRecvThread.Create(False);
UDPSend := TUDPSendThread.Create(False);
EdMsg.Enabled := True;
BtnSend.Enabled := True;
EdPortLocal.Enabled := False;
BtnExit.Enabled := True;
end;
procedure TUDPForm.FormCreate(Sender: TObject);
begin
UDPRecv := nil;
UDPSend := nil;
UDPSock := nil;
BtnStart.Enabled := True;
EdMsg.Enabled := False;
BtnSend.Enabled := False;
EdPortLocal.Enabled := True;
BtnExit.Enabled := False;
end;
end.