//交叉链接,同题的,呵呵 :)http://www.csdn.net/expert/topic/1026/1026938.xml?temp=.10693//以下是本人的实现,只能传输2K数据流,大于2k发送不成功,为什么?
//也可自己实现,贴出源代码,谢先...unit Unit1;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ComCtrls, ExtCtrls, NMUDP;type
TForm1 = class(TForm)
Memo1: TMemo;
Splitter1: TSplitter;
Splitter2: TSplitter;
Memo2: TMemo;
StatusBar1: TStatusBar;
Btn_Send: TButton;
Button2: TButton;
NMUDP1: TNMUDP;
OpenDialog1: TOpenDialog;
procedure Button2Click(Sender: TObject);
procedure NMUDP1StreamInvalid(var handled: Boolean; Stream: TStream);
procedure NMUDP1InvalidHost(var handled: Boolean);
procedure NMUDP1Status(Sender: TComponent; status: String);
procedure Btn_SendClick(Sender: TObject);
procedure NMUDP1DataSend(Sender: TObject);
procedure NMUDP1DataReceived(Sender: TComponent; NumberBytes: Integer;
FromIP: String; Port: Integer);
procedure Memo1KeyPress(Sender: TObject; var Key: Char);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementationconst
bufsize = 1024 * 3; //2048, 3072, 4096{$R *.DFM}procedure TForm1.Button2Click(Sender: TObject);
begin
Close;
end;procedure TForm1.NMUDP1StreamInvalid(var handled: Boolean;
Stream: TStream);
begin
StatusBar1.Panels[0].Text := 'Invalid Stream: Stream contains no data';
end;procedure TForm1.NMUDP1InvalidHost(var handled: Boolean);
var
S: String;
begin
S := NMUDP1.RemoteHost;
if InputQuery('Invalid host', 'Specify valid hostname: ', S) then
begin
NMUDP1.RemoteHost := S;
handled := TRUE;
end;
end;procedure TForm1.NMUDP1Status(Sender: TComponent; status: String);
begin
StatusBar1.Panels[1].Text := status;
end;procedure TForm1.Btn_SendClick(Sender: TObject);
var
i,count: Integer;
s: string;
SendStream: TMemoryStream;
MyStream: TMemoryStream;
leftsize,sendsize: Longint;
//buf: array[0..bufsize-1] of char;
begin
SendStream := TMemoryStream.Create;
MyStream := TMemoryStream.Create; Memo1.SetFocus; try
if OpenDialog1.Execute then
Memo1.Lines.LoadFromFile(OpenDialog1.FileName); s:= Memo1.Lines.text;
if s = '' then
begin
MessageDlg('Invalid message! Please Add it...',mtError,[mbOK],0);
exit;
end; NMUDP1.RemoteHost := '127.0.0.1';
NMUDP1.ReportLevel := Status_Basic;
NMUDP1.RemotePort := 6668;
Nmudp1.LocalPort := 6668; MyStream.LoadFromFile(OpenDialog1.FileName);
Mystream.Position := 0;
leftsize := Mystream.Size;
//leftsize := length(s); if leftsize > bufsize then
begin
count := leftsize div bufsize; //´ò°ü³Éÿ°ü2048Bytes ʱµÄ´ò°ü´ÎÊý
for i := 1 to count do
begin
//sendsize := bufsize;
sendstream.Write(s[1],bufsize);
NMUDP1.SendStream(sendstream);
leftsize := Mystream.Seek((bufsize * i), soFromBeginning);
if leftsize = 0 then
break;
end; //end of [for i := 1 to count do]
end
else
begin
sendsize := leftsize;
SendStream.Write(s[1],sendsize);
NMUDP1.SendStream(sendstream);
end; finally
Sendstream.Free;
Mystream.Free;
end;end;procedure TForm1.NMUDP1DataSend(Sender: TObject);
begin
StatusBar1.Panels[2].Text := 'Data From Memo1 to Memo2 Sent...';
end;procedure TForm1.NMUDP1DataReceived(Sender: TComponent;
NumberBytes: Integer; FromIP: String; Port: Integer);
var
recStream,resultstream: TMemoryStream;
buf: array[0..10000] of char;
begin
recStream := TMemoryStream.Create;
resultstream := TMemoryStream.Create;
try
NMUDP1.ReadStream(recStream);
recstream.Position := 0; //ÖÃÇ°
recstream.ReadBuffer(buf,NumberBytes); //read data from recstream to buf;
if NumberBytes > bufsize then
begin
resultstream.WriteBuffer(buf,bufsize);
//resultstream.Position := 0;
Memo2.Lines.LoadFromStream(resultstream);
Statusbar1.Panels[3].Text := 'Data received '+IntToStr(NumberBytes)+' bytes from '
+FromIP+' on port '+IntToStr(Port);
numberbytes := numberbytes - bufsize;
end
else //NumberBytes <= bufsize
begin
resultstream.WriteBuffer(buf,numberbytes);
resultstream.Position := 0;
Memo2.Lines.LoadFromStream(resultstream);
Statusbar1.Panels[3].Text := 'Data received '+IntToStr(NumberBytes)+' bytes from '
+FromIP+' on port '+IntToStr(Port);
end;
finally
recStream.Free;
end;
end;procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char);
begin
if key = #13 then
self.Btn_SendClick(self);
end;end.//end of program
//也可自己实现,贴出源代码,谢先...unit Unit1;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ComCtrls, ExtCtrls, NMUDP;type
TForm1 = class(TForm)
Memo1: TMemo;
Splitter1: TSplitter;
Splitter2: TSplitter;
Memo2: TMemo;
StatusBar1: TStatusBar;
Btn_Send: TButton;
Button2: TButton;
NMUDP1: TNMUDP;
OpenDialog1: TOpenDialog;
procedure Button2Click(Sender: TObject);
procedure NMUDP1StreamInvalid(var handled: Boolean; Stream: TStream);
procedure NMUDP1InvalidHost(var handled: Boolean);
procedure NMUDP1Status(Sender: TComponent; status: String);
procedure Btn_SendClick(Sender: TObject);
procedure NMUDP1DataSend(Sender: TObject);
procedure NMUDP1DataReceived(Sender: TComponent; NumberBytes: Integer;
FromIP: String; Port: Integer);
procedure Memo1KeyPress(Sender: TObject; var Key: Char);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementationconst
bufsize = 1024 * 3; //2048, 3072, 4096{$R *.DFM}procedure TForm1.Button2Click(Sender: TObject);
begin
Close;
end;procedure TForm1.NMUDP1StreamInvalid(var handled: Boolean;
Stream: TStream);
begin
StatusBar1.Panels[0].Text := 'Invalid Stream: Stream contains no data';
end;procedure TForm1.NMUDP1InvalidHost(var handled: Boolean);
var
S: String;
begin
S := NMUDP1.RemoteHost;
if InputQuery('Invalid host', 'Specify valid hostname: ', S) then
begin
NMUDP1.RemoteHost := S;
handled := TRUE;
end;
end;procedure TForm1.NMUDP1Status(Sender: TComponent; status: String);
begin
StatusBar1.Panels[1].Text := status;
end;procedure TForm1.Btn_SendClick(Sender: TObject);
var
i,count: Integer;
s: string;
SendStream: TMemoryStream;
MyStream: TMemoryStream;
leftsize,sendsize: Longint;
//buf: array[0..bufsize-1] of char;
begin
SendStream := TMemoryStream.Create;
MyStream := TMemoryStream.Create; Memo1.SetFocus; try
if OpenDialog1.Execute then
Memo1.Lines.LoadFromFile(OpenDialog1.FileName); s:= Memo1.Lines.text;
if s = '' then
begin
MessageDlg('Invalid message! Please Add it...',mtError,[mbOK],0);
exit;
end; NMUDP1.RemoteHost := '127.0.0.1';
NMUDP1.ReportLevel := Status_Basic;
NMUDP1.RemotePort := 6668;
Nmudp1.LocalPort := 6668; MyStream.LoadFromFile(OpenDialog1.FileName);
Mystream.Position := 0;
leftsize := Mystream.Size;
//leftsize := length(s); if leftsize > bufsize then
begin
count := leftsize div bufsize; //´ò°ü³Éÿ°ü2048Bytes ʱµÄ´ò°ü´ÎÊý
for i := 1 to count do
begin
//sendsize := bufsize;
sendstream.Write(s[1],bufsize);
NMUDP1.SendStream(sendstream);
leftsize := Mystream.Seek((bufsize * i), soFromBeginning);
if leftsize = 0 then
break;
end; //end of [for i := 1 to count do]
end
else
begin
sendsize := leftsize;
SendStream.Write(s[1],sendsize);
NMUDP1.SendStream(sendstream);
end; finally
Sendstream.Free;
Mystream.Free;
end;end;procedure TForm1.NMUDP1DataSend(Sender: TObject);
begin
StatusBar1.Panels[2].Text := 'Data From Memo1 to Memo2 Sent...';
end;procedure TForm1.NMUDP1DataReceived(Sender: TComponent;
NumberBytes: Integer; FromIP: String; Port: Integer);
var
recStream,resultstream: TMemoryStream;
buf: array[0..10000] of char;
begin
recStream := TMemoryStream.Create;
resultstream := TMemoryStream.Create;
try
NMUDP1.ReadStream(recStream);
recstream.Position := 0; //ÖÃÇ°
recstream.ReadBuffer(buf,NumberBytes); //read data from recstream to buf;
if NumberBytes > bufsize then
begin
resultstream.WriteBuffer(buf,bufsize);
//resultstream.Position := 0;
Memo2.Lines.LoadFromStream(resultstream);
Statusbar1.Panels[3].Text := 'Data received '+IntToStr(NumberBytes)+' bytes from '
+FromIP+' on port '+IntToStr(Port);
numberbytes := numberbytes - bufsize;
end
else //NumberBytes <= bufsize
begin
resultstream.WriteBuffer(buf,numberbytes);
resultstream.Position := 0;
Memo2.Lines.LoadFromStream(resultstream);
Statusbar1.Panels[3].Text := 'Data received '+IntToStr(NumberBytes)+' bytes from '
+FromIP+' on port '+IntToStr(Port);
end;
finally
recStream.Free;
end;
end;procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char);
begin
if key = #13 then
self.Btn_SendClick(self);
end;end.//end of program
我摘一段bcb的代码给你
char *Buffer=new char[2048];//正好2kB
int tBuffSize = Stream->Size;
int BuffsNum=tBuffSize/pBuffsize;
for(int i=0;i<=BuffsNum;i++)
{
if (tBuffSize>pBuffSize)
{
Stream1->Read(Buffer,2048);
NMUDP1->SendBuffer(Buffer,pBuffSize,pBuffSize);
tBuffSize=tBuffSize-2048;
}else{
Stream->Read(Buffer,tBuffSize);
NMUDP1->SendBuffer(Buffer,tBuffSize,tBuffSize);
tBuffSize=0;
}
}
delete Buffer;
delete Stream;
{
Stream1->Read(Buffer,2048);
NMUDP1->SendBuffer(Buffer,pBuffSize,pBuffSize);
tBuffSize=tBuffSize-2048;
}
这段中,能保证一个2K包发完后,再取下一个2k包么?
好像我上次用Delphi写过同样的逻辑,不行吧?
期待...
//其中,bufsize = 2048;procedure TForm1.Btn_TransClick(Sender: TObject);
var
tmp,My,send: TMemoryStream;
i,count: Integer;
leftsize: Integer;
//sendsize: longint;
s: string;
begin
tmp := TMemorystream.Create;
My := TMemorystream.Create;
Send := TMemorystream.Create; if Opendialog1.Execute then
My.LoadFromFile(Opendialog1.FileName);
Memo1.Lines.LoadFromStream(My);
s := Memo1.Lines.Text; leftsize := my.Size;
my.Position := 0;
try
if leftsize > bufsize then
begin
count := leftsize div bufsize;
for i := 1 to count do
begin
send.CopyFrom(my,bufsize);
NMUDP1.SendStream(send);
NMUDP1.ReadStream(tmp);
Memo2.Lines.LoadFromStream(tmp);
leftsize := length(s) - bufsize * i;
my.Seek((bufsize * i),soFromBeginning);
end;
end
else //leftsize <= bufsize
begin
send.CopyFrom(my,leftsize);
NMUDP1.SendStream(send);
NMUDP1.ReadStream(tmp);
Memo2.Lines.LoadFromStream(tmp);
end;
finally
tmp.Free;
send.Free;
my.Free;
end;
end;
????
上面一句话很是难解,因为你每次减掉的只需一个bufsize就可以了,因此
leftsize := length(s) - bufsize ;可能是正解对不起,由于实在是太久没用delphi了,可能是我错,请原谅
即:leftsize := leftsize - bufsize ;
而且你的for循环结束后也没有执行剩余部分的发送,令人迷惑。
我想这样看看,不过我这里没有delphi环境,所以没法试 leftsize := my.Size;
my.Position := 0;
i:=0;
try
While leftsize > bufsize do
begin
send.CopyFrom(my,bufsize);
NMUDP1.SendStream(send);
NMUDP1.ReadStream(tmp);
Memo2.Lines.LoadFromStream(tmp);
leftsize := leftsize - bufsize ;
INC(i);
my.Seek((bufsize * i),soFromBeginning);
end;
if leftsize>0 then
begin
send.CopyFrom(my,leftsize);
NMUDP1.SendStream(send);
NMUDP1.ReadStream(tmp);
Memo2.Lines.LoadFromStream(tmp);
end;
Finnally ........ 如果,你可以从当前位置开始移动,就可以不要i变量了
我的机子上最大为5M左右,与硬件或操作系统有关吧?
UDP没试过如果用UDP协议,那么你只能把文件分开然后部分的传送
当一部分接受完后,就向对方要求下一部分的数据,直到全部接受完毕用ServerSocket和ClientSocket的话如果文件不大于1M的话,发送段只需发送一次就行了
而接受端则要不停的接受直到接受完毕
这么做有一个缺点就是发送出去的东西所占的内存在Socket关闭前不能释放
如果要传输几百兆的东西,就得不断的断开、连接以释放内存。至于接受完毕的标志,你可以在发送端真正发送数据之前,先把要发送的数据的
大小发送给接受端,那么接受端就可以依次为依据看是否接受完毕。
我想用UDP传送实时数据吧。
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
NMUDP, StdCtrls, Buttons, ExtCtrls, ComCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
Memo2: TMemo;
StatusBar1: TStatusBar;
Splitter1: TSplitter;
SendBtn: TBitBtn;
NMUDP1: TNMUDP;
OpenDialog1: TOpenDialog;
procedure NMUDP1StreamInvalid(var handled: Boolean; Stream: TStream);
procedure NMUDP1InvalidHost(var handled: Boolean);
procedure NMUDP1Status(Sender: TComponent; status: String);
procedure SendBtnClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
const bufsize = 1024 * 2;
{$R *.DFM}
procedure TForm1.NMUDP1StreamInvalid(var handled: Boolean;
Stream: TStream);
begin
showmessage('Invalid Stream: Stream contains no data');
end;
procedure TForm1.NMUDP1InvalidHost(var handled: Boolean);
var
S: String;
begin
S := NMUDP1.RemoteHost;
if InputQuery('Invalid host', 'Specify valid hostname: ', S) then
begin
NMUDP1.RemoteHost := S;
handled := TRUE;
end;
end;
procedure TForm1.NMUDP1Status(Sender: TComponent; status: String);
begin
statusbar1.SimpleText := 'Status: ' + status;
end;
//***********************************************************************************
//******* this procedure include 'send' amd ' receive' two actions with UDP ******
//*** Const type: ******************************************************************
//*** bufsize = 2 * 1024 *********************************************************
//*** variant type: *****************************************************************
//*** My: Source Stream(Memo1's text) ***************************************
//*** Send: the stream being to sent *****************************************
//*** temp: the temporary stream being to received ****************************
//*** i: circulation Integer variant **************************************
//*** leftsize: the total left size being to sent *********************************
//*** buf: buffer variant(2048 bytes) ****************************************
//***********************************************************************************
procedure TForm1.SendBtnClick(Sender: TObject);
var
My,send: TMemoryStream;
tmp: TmemoryStream;
i: Integer;
//count: Integer;
leftsize: Integer;
buf: array[0..bufsize] of char;
begin
My := TMemorystream.Create;
Send := TMemorystream.Create;
tmp := TMemorystream.Create;
if Opendialog1.Execute then
My.LoadFromFile(Opendialog1.FileName);
Memo1.Lines.LoadFromStream(My);
//send.SetSize(bufsize);
//tmp.SetSize(bufsize);
leftsize := my.Size;
//count := leftsize div bufsize;
my.Position := 0;
i:=0;
try
While (leftsize > bufsize) do
begin
leftsize := leftsize - bufsize ;
//showmessage('My.position: ' + Inttostr(my.Position)); //......
send.CopyFrom(my,bufsize);
my.Seek(0,sofromcurrent); // .Position := bufsize * i;
//showmessage('My.position: ' + Inttostr(my.Position)); //......
//my.Position := bufsize * (i+1);
send.Position := bufsize * i;
NMUDP1.SendStream(send);
NMUDP1.ReadStream(tmp);
send.Clear;
tmp.Read(buf,bufsize);
Memo2.Lines.Add(buf); // .LoadFromStream(tmp);
//showmessage(Memo2.Lines.Text); //.......
tmp.Clear;
INC(i);
end;
//showmessage('My.position: ' + Inttostr(my.Position)); //.......
if (leftsize > 0) and (leftsize <= bufsize)then
begin
send.SetSize(leftsize);
//showmessage('My.position: ' + Inttostr(my.Position));
send.CopyFrom(my,leftsize);
//showmessage('send.position: ' + Inttostr(send.Position)); //......
//showmessage('My.position: ' + Inttostr(my.Position)); //......
send.Position := 0;
NMUDP1.SendStream(send);
NMUDP1.ReadStream(tmp);
send.Clear;
tmp.Read(buf,bufsize);
Memo2.Lines.Add(buf); // .LoadFromStream(tmp);
tmp.Clear;
end;
Finally
tmp.Free;
send.Free;
my.Free;
end;
StatusBar1.Panels[0].Text := 'Source bytes: ' + Inttostr(length(Memo1.Lines.Text)) +
' bytes; Total received bytes: ' + IntTostr(length(Memo2.Lines.Text)) + ' bytes.';
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.Clear;
Memo2.Clear;
NMUDP1.RemoteHost := 'LOCALHOST';
NMUDP1.ReportLevel := STATUS_BASIC;
NMUDP1.RemotePort := 5667;
NMUDP1.LocalPort := 5667;
end;
end.********************************************************************
我想应该是算法有问题吧,跟踪过,不得解阿.
求助了各位
直接发(>2k的内容)就可以了,client直接收即可
其实我最近上次的代码已基本正确,只不过不能把发送与接收事件同时写在同一过程中,这点很重要,其实当时我把它们写在一起,是为了测试求方便,其实想想这种态度很不好 :)
其实我最近上次的代码已基本正确,只不过不能把发送与接收事件同时写在同一过程中,这点很重要,其实当时我把它们写在一起,是为了测试求方便,其实想想这种态度很不好 :)