讨论Udp的工作原理(怎样实现OICQ聊天的程序)(300分)

  • 主题发起人 主题发起人 wjh_wy
  • 开始时间 开始时间
连接自然是TCP,UDP不需要连接的。有socks代理,TCP一样能实现不同局域网内通讯。
SYNAPSE确实支持UDP ASSOCIATE,可以双向通讯,可能是你使用的问题,无论是TCP或UDP,在这种情况下都需要一个握手服务器取得对方的实际地址。
 
to 乡村月光
你的QQ多少,或者加我也行
另外,能否写个这样的例子给我,用SYNAPSE
A是客户端,B是服务器,都采用UDP的协议通讯,A通过SOCKS5代理也就是UDP ASSOCIATE发送一个文本给B,B收到后返回该文本的长度给A,这个例子应该很简单吧,麻烦你了
 
TO 乡村月光
能不能发我一份呀。
 
我要也一个 sunjunfeng3@163.com
 
to 乡村月光
兄弟,很多人都在等你呢,帮帮大家吧
 
我以前测试的时候写过一个程序,在两台机器上运行可以相互发消息。发送和接收的消息都保存在一个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(n) + '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.
 
to 乡村月光
我刚刚测试过你的代码,当没用设置SOCKS代理时没问题,设置了代理后没法回复,我用的是WINGATE3,你测试下如何,如果你那可以,麻烦你把代码和执行程序都打包给我,谢谢
 
使用代理服务器时,需要先使用代理服务的一方发一条消息,另一方收到后要用列表中显示的地址和端口回复!但无论如何自动回复应该是成功的,即你发出消息后消息前面的-号如果变成了+号,就证明是成功的。
我以前测试过没问题的,这里现在没办法测试,网关禁止了UDP,这也是我后来不用UDP的原因。如果你需要完整的代码和执行程序,请留下email,我QQ是21449301或29953513,不过很少上:)
 
to 乡村月光
你代码我还没有试,我等你把源码发给我再试,我这里有比较好的测试环境,希望一起讨论。
QQ:39306255
 
to 乡村月光

qq:7310159
mail:yangying_2000@163.com
 
邮件已发
 
to 乡村月光
mail:wjh_wy@163.com
 
E-Mail:smallshi@163.com
QQ:15932551
宁柯你就发到我的E-Mail吧,顺便问一下你的QQ号,有问题想请教大侠您
 
[red]请大家不要再叫宁柯发源代码好吗,他的源码在这里:[/red]http://www.eFile.com.cn/eFile/jxcjsh/Demos/Chat.rar
 
to:宁柯
能否给我一份?
douzheng@sina.com
谢谢!
 
to:宁柯
能否给我一份?
go_Huang@hotmail.com
谢谢!
 
to:宁柯
能否给我一份?
g27384955@hotmail.com
谢谢!
 
to:宁柯
能否给我一份?
lmoop@tom.com
谢谢!
 

Similar threads

D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
后退
顶部