//交叉链接,同题的,呵呵 :)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

解决方案 »

  1.   

    QQ:6376875E-mail:[email protected]
      

  2.   

    不为什么,因为了NMUDP发送的数据不能超过2kB.如果你要发送送超过2KB的数据的话,只有自己把它分隔好。
      我摘一段bcb的代码给你
      

  3.   

    TFileStream *Stream = new TFileStream(Edit5->Text,fmOpenRead);
    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;
      

  4.   

    to jianlinlong(楚 潇) if (tBuffSize>pBuffSize)
      {
        Stream1->Read(Buffer,2048);
        NMUDP1->SendBuffer(Buffer,pBuffSize,pBuffSize);
        tBuffSize=tBuffSize-2048;
       }
    这段中,能保证一个2K包发完后,再取下一个2k包么?
    好像我上次用Delphi写过同样的逻辑,不行吧?
      

  5.   

    to sandraphh(我在云端)我始终相信这里有高手的。
    期待...
      

  6.   

    对于udp协议来说,它的一次的传送字节就是不能超过两k,所以你必须自己在发送端完成对流的分割,对于怎么分割,我建议你去找别的贴子,我记得以前有关于怎么在局域网中传输别的计算机的屏幕截屏图片的,例子很简单,也很实用,你参考一下吧,无论是读还是写,请注意指针的位置就可以了。
      

  7.   

    //下面这段为什么传输大于2K文本为何不可?(2k以内通过)
    //其中,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;
      

  8.   

    leftsize := length(s) - bufsize * i;
            
    ????
    上面一句话很是难解,因为你每次减掉的只需一个bufsize就可以了,因此
    leftsize := length(s) - bufsize ;可能是正解对不起,由于实在是太久没用delphi了,可能是我错,请原谅
      

  9.   

    sorry, 好像是错了,不过你的length(s)还是不好,我建议直接使用leftsize
    即: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变量了
      

  10.   

    要是用ServerSocket和ClientSocket一次最多可以传输大于不止2k的数据
    我的机子上最大为5M左右,与硬件或操作系统有关吧?
    UDP没试过如果用UDP协议,那么你只能把文件分开然后部分的传送
    当一部分接受完后,就向对方要求下一部分的数据,直到全部接受完毕用ServerSocket和ClientSocket的话如果文件不大于1M的话,发送段只需发送一次就行了
    而接受端则要不停的接受直到接受完毕
    这么做有一个缺点就是发送出去的东西所占的内存在Socket关闭前不能释放
    如果要传输几百兆的东西,就得不断的断开、连接以释放内存。至于接受完毕的标志,你可以在发送端真正发送数据之前,先把要发送的数据的
    大小发送给接受端,那么接受端就可以依次为依据看是否接受完毕。
      

  11.   

    to wisenowa(127.0.0.1)
    我想用UDP传送实时数据吧。
      

  12.   

    下面是实现基于UDP包数据流发送源码。还存在一个问题就是大于2K包会存在一部分数据丢失现象,2K之内要点击两次才能发送成功,不知为什么。跟踪了N次。恳求解答,谢谢!********************************************************************unit Unit1;
    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.********************************************************************
      

  13.   

    to HHBB
    我想应该是算法有问题吧,跟踪过,不得解阿.
    求助了各位
      

  14.   

    各位还是使用id的udp吧,也不麻烦的。完全可以发送>2k的内容,建议尝试一下。
    直接发(>2k的内容)就可以了,client直接收即可
      

  15.   

    在各位的协助下,特别要指出的是lvxq(吕歌)大哥,通过E-Mail联系,基本实现UDP数据包的发送与接收问题,在此表示感谢!
    其实我最近上次的代码已基本正确,只不过不能把发送与接收事件同时写在同一过程中,这点很重要,其实当时我把它们写在一起,是为了测试求方便,其实想想这种态度很不好 :)
      

  16.   

    在各位的协助下,特别要指出的是lvxq(吕歌)大哥,通过E-Mail联系,基本实现UDP数据包的发送与接收问题,在此表示感谢!
    其实我最近上次的代码已基本正确,只不过不能把发送与接收事件同时写在同一过程中,这点很重要,其实当时我把它们写在一起,是为了测试求方便,其实想想这种态度很不好 :)