用udp协议可以发送到公网,但无法收到公网发回的信息(100分)

  • 主题发起人 emitsong
  • 开始时间
E

emitsong

Unregistered / Unconfirmed
GUEST, unregistred user!
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdUDPBase, IdUDPServer,
IdAntiFreezeBase, IdAntiFreeze,IdSocketHandle;

type
TForm1 = class(TForm)
UDPServer: TIdUDPServer;
Memo1: TMemo;
Button1: TButton;
Memo2: TMemo;
IdAntiFreeze1: TIdAntiFreeze;
Edit1: TEdit;
Edit2: TEdit;
procedure UDPServerUDPRead(Sender: TObject; AData: TStream;
ABinding: TIdSocketHandle);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.UDPServerUDPRead(Sender: TObject; AData: TStream;
ABinding: TIdSocketHandle);
var
DataStringStream: TStringStream;
s: String;
begin
DataStringStream := TStringStream.Create('');
try
DataStringStream.CopyFrom(AData, AData.Size);
Memo2.Lines.Add('Received "' + DataStringStream.DataString + '" from ' + ABinding.PeerIP + ' on port ' + IntToStr(ABinding.PeerPort));
s := 'Replied from ' + UDPServer.LocalName + ' to "' + DataStringStream.DataString + '"';
ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, s[1], Length(s));
finally
DataStringStream.Free;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
s:string;
begin
edit1.txt:=//公网ip 202.10.12.3
edit1.txt:=//公网接收端口9090
s:=memo1.text;
UDPServer.Binding.SendTo(edit1.Text,strtoint(edit2.text),s[1],Length(s));
end;

end.
 
同样的程序放在公网服务器上和客户端(本地ip,端口9090)
仅有一次成功返回了,那次,网关服务器给我分配的端口正好是9090
后来分配的端口不是9090就再也收不到回复的信息了
我想跟nat建立的握手有关
希望高手指点,基本的通讯原理我都了解
 
看是不是代理服务器的原因?
QQ就是用UDP的,你可以把服务器放在公网上,你用Client和他连接,应该没有问题
 
服务器本来就在公网,否则也没必要讨论了,局域网一点问题都没有
 
那就怪了,QQ也是用UDP,他就可以收到消息啊,你看你的一些设置是不是错了?
还有QQ的接受端的端口是固定的,你把你的Client的Port到一个固定端口试试
 
张无忌, 象你这样想,是错误的,qq自定义的udp协议,直接对ip层设置记录路由的过程,当然出得去进的来
如果这么容易,大家都来开发qq了
 
金涛就做过一个可以使2个网吧的机器互相通讯的东东,
没有你想的那么麻烦,他用的办法和我说的差不多,
而且我写过几个伪造UDP头的小软件,对UDP的一些具体
配置有写基本的了解,真的没有你说的那么麻烦。
 
:张无忌,你使用的是什么udp控件,还是直接用winsock
 
用的是winsock
 
张无忌,有没有源码给我参考一下,主要是能发能收就可以了
 
我现在就可以写,不过你得等一会,[:D]
 
to 张无忌,me to:小弟也学习一下~

em:doll-paul@263.net

谢谢~
 
张无忌, 我等到花儿谢了
 
你的公司有防火墙之类吧?这样数据只能出去不能回来的.

QQ用的是SOCKET5,要有个服务器的.
有服务器的话TCP协议也可以的.
A(局部网电脑)---->服务器D(有固定IP地址)<-------B(局部网电脑)
服务器D甚至可以只做一个工作,就是同时有类似D的多个服务器,D只负责把A和B连接到上面

A(局部网电脑)--->B(服务器)--->INTENET
C(局部网电脑)--->D(服务器)--->INTENET
如果想实现A与C直接连接,而且不用服务器,那么只能采用端口映射原理.
不过,很可惜的是只支持UDP协议.我测试过,UDP传输成功了,但是速度一直不理想,头痛.
 
我写的这个能收,你看看
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, NMUDP;

type
TForm1 = class(TForm)
NMUDP1: TNMUDP;
Edit1: TEdit;
Edit2: TEdit;
Label1: TLabel;
Label2: TLabel;
Button1: TButton;
Memo1: TMemo;
Edit3: TEdit;
Label3: TLabel;
procedure NMUDP1DataReceived(Sender: TComponent; NumberBytes: Integer;
FromIP: String; Port: Integer);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure senddata(datastr:string;toip:string);
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.senddata(datastr:string;toip:string);
var
mystream:tmemorystream;
begin
NMUDP1.RemoteHost:=toip;
mystream:=tmemorystream.Create;
try
mystream.Write(datastr[1],length(datastr));
nmudp1.SendStream(mystream);
finally
mystream.Free;
end;
end;

procedure TForm1.NMUDP1DataReceived(Sender: TComponent;
NumberBytes: Integer; FromIP: String; Port: Integer);
var
mystream:tmemorystream;
tmpstr:string;
begin
mystream:=tmemorystream.Create;
try
nmudp1.ReadStream(mystream);
setlength(tmpstr,numberbytes);
mystream.Read(tmpstr[1],numberbytes);
memo1.Lines.add(fromip+'/'+inttostr(Port)+' : '+tmpstr);
edit1.Text:= fromip;
edit3.Text:=inttostr(Port);
finally
mystream.Free;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
nmudp1.RemotePort:=strtoint(edit3.Text);
senddata(edit2.Text,edit1.Text);
end;

end.
 
to:jintao
如果想实现A与C直接连接,而且不用服务器,那么只能采用端口映射原理.

又没有代码给我参考一下,【久闻大名,如果我没记错我们是老乡(湖北)】
 
接受答案了.
 
顶部