关于接收UDP数据包的问题(50分)

  • 主题发起人 主题发起人 ccoder
  • 开始时间 开始时间
C

ccoder

Unregistered / Unconfirmed
GUEST, unregistred user!
《Delphi高级网络编程》一书的附带源代码中有一个程序是用来演示NMUDP的用法的,
其中的一段代码有点问题:
1 procedure TForm1.NMUDP1DataReceived(Sender: TComponent;
2 NumberBytes: Integer; FromIP: String; Port: Integer);
3 var
4 TXT: PChar;
5 Count: Integer;
6 begin
7 StatusBar1.SimpleText:='Receiving data';
8 GetMem(txt,NUmberBytes+1);
9 ZeroMemory(TXT,NumberBytes+1);
10 NMUDP1.ReadBuffer(TXT^, Count);
11 Memo1.Lines.Add(TXT);
12 FreeMem(Txt);
13 StatusBar1.SimpleText:='data Received';
end;
假设我发送‘1234567890’10个字符
在第10行执行过后,Count的值是10,但TXT里面的值只有前4个才是正确的,后面的就变成了
乱码,我怎么也想不出问题出在哪里。有谁能帮忙解释一下?谢谢
 
这段代码应该不会出现你说的问题.
不过感觉这个Count用得妙名其秒.
直接NMUDP1.ReadBuffer(TXT^,NumberBytes)得了.
而且Count居然还没有赋值,也就是说还是一个随机数,如果为负怎么办?

问题应该出在你的SendBuffer上.请帖你的发送函数.
 

procedure TForm1.btnSendClick(Sender: TObject);
var
txt:pchar;
begin
//valid
if Memo1.Text='' then
begin
StatusBar1.SimpleText:='Nothing to send';
exit;
end;
//infact only 1024 byte can send
GetMem(txt,Length(Memo1.Text)+1);
ZeroMemory(txt,Length(Memo1.Text)+1);
txt:=PChar(Memo1.Text);
//set ip info
NMUDP1.RemoteHost := Edit1.Text;
NMUDP1.RemotePort := StrToInt(Edit2.Text);
//send
NMUDP1.SendBuffer(txt^,Length(Memo1.Text));
end;

procedure TForm1.NMUDP1DataReceived(Sender: TComponent;
NumberBytes: Integer; FromIP: String; Port: Integer);
var
TXT: PChar;
Count: Integer;
begin
StatusBar1.SimpleText:='Receiving data';
GetMem(txt,NUmberBytes+1);
ZeroMemory(TXT,NumberBytes+1);
NMUDP1.ReadBuffer(TXT^, Count);
Memo1.Lines.Add(TXT);
FreeMem(Txt);
StatusBar1.SimpleText:='data Received';
end;
以上是从原光盘拷贝下来的;
在delphi里的帮助说:
Declaration
procedure ReadBuffer(var Buff: array of char; var length: integer);

Description
The ReadBuffer method reads incoming UDP data into a Buffer.

Parameters:
The Buff parameter specifies the buffer to read the data into.
The length parameter is the size of the data to be read.
———————————^^^^^^^^^^
按道理也应该先设置length这个参数,但调试时我发现在ReadBuffer前length是个随机数,
但ReadBuffer后,变成了传过来的字符个数值。而且这个length参数也是变量参数,也就是
ReadBuffer里面不是只读的,可以修改它的值。这是为什么呢?为了效率(引用效率好像
也不会比数值参数好)?还是你给它(ReadBuffer)一个数,告诉它该读多少字符,然后
它又把该参数设为实际得到的字符?但这样又有什么意义呢?我发现不论你传给它的length
是比实际读到的字符大还是小,效果都一样,那个length最终是读到的字符数。
问题好像出在发送时和接受时的Pchar型的缓冲区,你看呢,wheel?
 
>> NMUDP1.SendBuffer(txt^,Length(Memo1.Text));
这里SendBuffer的参数buffer用了PChar型变量,而实际要求的是字符数组变量.

根据我的测试,在Delphi中,当主调函数A使用PChar变量作为实参传递给要求字符数组的被调函数B时。
被调函数B的形参实便被赋值为PChar的第一个字符,仅仅能得到一个Char字符

所以用上面的方法应该是不可行的.
至于为什么会出现前4个字符有效,我估计和AnsiString的默认分配内存空间为4Bytes有关.
但具体的细节我不清楚,而且NMUDP控件也不提供源码。:(
希望有高手能够给一个合理的解释.

可以改为用下面的方法发送:
var
a:array[0..2047] of char;
begin
StrPCopy(a,Memo1.Text);
NMUDP1.SendBuffer(a,Length(Memo1.Text));
end;

关于length的问题,谢谢你的提示,我一直没有注意.居然是这样。
我也觉得很奇怪,待会再看一下,越来越讨厌没有源码的控件了。[:(]
 
我也晕了,估计只能让写这玩意儿的家伙来解释了。
下面是Help里NMUDP的Example:
procedure TForm1.NMUDP1DataReceived(Sender: TComponent; NumberBytes: Integer; FromIP: String; Port: Integer);
var
C: array [1..3] of Char;
I: Integer;
begin
if NumberBytes <= 3 then
begin
NMUDP1.ReadBuffer(C, I);
Memo1.Lines.Add(C+': received '+IntToStr(I)+' bytes from '+FromIP+' on port '+IntToStr(Port));
end
else
Memo1.Lines.Add(IntToStr(I)+' bytes incoming, buffer too small');
end;
感觉这个'I'简单是莫名其妙,感觉无论如何这段代码都讲不通的。
本来兄弟们说NMUDP烂的时候我还替他维护,但这段代码让我太........[:(]
 
谢谢你的解答,呵呵。[:)]
 
感觉这个'I'简单是莫名其妙->NMUDP1.ReadBuffer(C, I);
这里是将NMUDP读到的字符及字节写到C和I中,根据它可以知道收到的字符及字节数.
 
我也遇到过这样的问题,用SENDBUFFER,参数只能是静态数组,否则收到的数据肯定不对
或是用SENDSTREAM,好使得很,我现在都是用SENDSTREAM
 
后退
顶部