关于UDP传输的结构体中string长度type
  TxtData=record
  cmd:string;
  S:string;
end;xt:TxtData;IdUDPServer1.SendBuffer(serverIP,1001,xt,sizeof(xt));
   谁能解决他的长度问题 不喜欢多包 不太容易控制  不喜欢规定他长度 最大254不够用 谁给个最佳解决方案

解决方案 »

  1.   

    这样干不行吧,sizeof长度肯定不对,要用数组type
        TxtData=record
        cmd:array[1..24] of Char;
        S:array[1..1024] of Char;
    end; 
      

  2.   

    我是想这样不限制长度 不是行不行 我原定义的是S:string[254];1024也不够用 
      

  3.   

    没看明白delphi的IDUDP中的send()怎么构造string特别长的
      

  4.   

    可以继续使用这种定义:
    type
        TxtData=record
        cmd:string;
        S:string;
    end; 只是需要自己写一个打包过程而已。function PackData(const Data: TxtData): string;
    var
      N1, N2: cardinal;
    begin
      N1 := Length(Data.cmd);
      N2 := Length(Data.S);
      SetLength(Result, SizeOf(N1) + N1 + SizeOf(N2) + N2);
      move(N1, Result[1], SizeOf(N1));
      move(TxtData.cmd[1], Result[SizeOf(N1) + 1], N1);
      move(N2, Result[SizeOf(N1) + N1 + 1], SizeOf(N2));
      move(TxtData.S[1], Result[SizeOf(N1) + N1 + SizeOf(N2) + 1], N2);
    end;然后
    IdUDPServer1.Send(serverIP,1001, PackData(xt)); 接收端需要一个解包过程,大同小异,你自己写吧。:)
      

  5.   

    补充一下,建议报命令采用 cardinal 类型,这样处理包命令简单。
    如:
    const
      CMD_LOGIN = $00000001;
      CMD_LOGOUT= $00000002;
    ...
    type
        TxtData=record
        cmd: cardinal;
        s: string;
    end; function   PackData(const   Data:   TxtData):   string;
    var
      len: cardinal;
    begin
        len := Length(Data.s);
        SetLength(Result,SizeOf(cardinal)+len);
        move(Data.cmd,Result[1],SizeOf(cardinal));
        move(len,Result[SizeOf(cardinal)+1],SizeOf(cardinal));
        move(Data.cmd[1],Result[SizeOf(cardinal)*2+1,len);
    end; 
      

  6.   

    不对 我不是要send出一个string
    我是要SendBuffer一个包含N个String类型N(未知数)长度的结构体啊 不能局限在254啊 
      

  7.   

    UDP是有包长限制的,过大的UDP包,有可能收不到,或者严重丢包。
    楼主提到的返回String并不是不能使用SendBuffer.
    var
      StrSend:String;
      
      StrSend := PackData(xt); 
      SendBuffer(IP,
                 Port,
                 PChar(StrSend)(*这里面根据需要,具体看参数,如果不是PChar类型,而可以用PChar(StrSend)^或者StrSend[1]代替*),
                 Length(StrSend));
      

  8.   

    不管你定义多大的包,最好的做法还是在包头部记录整个包的长度,因为你收到时会有包粘连的情况,你分隔后最后的一个包可能让断开了,要在下一次收到时进行合并。完全胡说。UDP 没有所谓的粘包问题,  UDP 最大长度65535- iphead  不超过这个长度,网络够通畅, 对方的接受buff 够大就可以收到了。ip层会自动把分片后的数据合并,不必担心。
      

  9.   

    Send 返回的值应该是指发送的长度吧. 就是说 Send('1234567890')可能返回5,即只发送了5个字节的数据出去,其它有没有发送成功.当你在调用Send 的时候Windows会将内容保存在一个缓冲区中,如果你发送的足够快,就会发让缓冲区满了,
    假设缓冲区的大小是1000个字节,连续发送每次300字节,第四次就只发出去了100字节.返回值就是100收的时候,可能收到了多个数据但只有一次Receive事件.至于最下层的发送分片是在读取了缓冲区后在发送时进行的,是更低层的驱动完成的.当然我们很多情况下发送时
    for....
    begin
    send();
    sleep(1000);
    end这样完成的,要是将sleep去掉,有很大机率会出现一个Receive事件收到多个包和Send 时有部分数据没有发送.
      

  10.   

    不管你定义的结构中有多少个串或者其他类型,都可以打包到一个string中。
    Delphi的string可以存任意数据,最大可以到2GB(32-bit下),可以直接当buffer来使用。
      

  11.   

    说什么呢 一个解决方案也没有 赶上作总结了type 
        TxtData=record 
        cmd:string; 
        S:string; 
    end; xt:TxtData; IdUDPServer1.SendBuffer(serverIP,1001,xt,sizeof(xt)); 大家别管UDP报最大多大 这个技术我有解决方案我问的是我的结构体中string不能固定再254 太小 不采用多包的情况下解决这个问题 记住是sendbuffer  别整到send(string)去 这个send是笨鸟才用的 
      

  12.   

    还有我传的是结构体 不是一个单独的string 服了喲
      

  13.   

    笨鸟,不是都告诉你了吗?:)
    send就是调用sendbuffer实现的,两者没有本质的区别。
    你非要用sendbuffer,假设s是string,s[1]就是buffer的首地址。
      

  14.   

    我传的是结构体 我的产品源码结构体不是上面代码那么简单的 老send什么 有毛病啊 我要解决string长度问题 你老提那个做什么
      

  15.   

    我用简单的代码来问问题 不展露产品复杂的结构源码 老让我send什么 答非所问 有毛病
      

  16.   

    我混你那几分?好笑。
    不管你的结构多复杂,都可以打包到一个buffer中,至于这个buffer用string、array还是getmem一块空间,都是一回事,没有本质的区别。
    你要实现不固定大小的动态结构,就肯定要采用类似的方法,就我所知,目前还没有哪种语言支持你想要的那种结构。
    你既然“这么多经验”,连这么简单的问题都解决不了吗?:)
      

  17.   

    不用你讲这些 我都知道 我问的是有没有解决string长度方法 你还听不懂人语 你心里有问题 说话满斗气的
      

  18.   

    楼主的态度有问题,请将注意力放在解决问题上面,大家都是冲着帮你解决问题的态度来的,---------------------------首先基础概念就有问题, 象这样的定义,不明白你怎么能传递的对???type 
        TxtData=record 
        cmd:string; 
        S:string; 
    end; xt:TxtData; IdUDPServer1.SendBuffer(serverIP,1001,xt,sizeof(xt));
    String根本上来说只是一个指针,一个指针是4 个字节长度,所以你的 sizeof(xt)在32位的计算机上永远都是8SendBuffer 只是传递一个连接的内存块,不管你里面保存的是什么,当然要给定的是起始的位置和传递的字节数.String 是Delphi 自己定义的数据类型,而SOCKET通信都是接字节来传递的,所以要用SOCKET最好用字符串数组
    如果你的接受端不是DELPHI开发的,最好在定义结构的时候加上Pack Record
    用结构体来保存要传递的数据只是方便你赋值操作罢了,对于一些变长的传递会不好操作.最好的办法是用一个对象封装,TxtData=record 
    private
      FID:String;
      FTitle:String;
    public  function GetData(var AP:Pointer):Integer;
    published
      property ID:String read FID write FID;
      property Title:String read FTitle write FTitle;
    end;//得到值的指针和长度,注意,用完后要释放AP
    function TxtData.GetData(var AP: Pointer): Integer;
    var
      ACMD:String;
      AStr:String;
      PInt:PInteger;
      Len:Integer;
      xd:TxtData;
    begin
      Len:=Length(FID)+Length(FTitle)+Sizeof(Integer)*3;
      AP:=GetMemory(Len);  PInt:=AP;
      PInt^:=Len; //保存总长度  PInt:=Pointer(Integer(PInt)+Sizeof(Integer));
      PInt^:=Length(FID); //保存第一个字符串长度  PInt:=Pointer(Integer(PInt)+Sizeof(Integer));
      CopyMemory(PInt,@FID[1],Length(FID));//保存第一个字符串内容  PInt:=Pointer(Integer(PInt)+Length(FID));
      PInt^:=Length(FTitle); //保存第二个字符串长度  PInt:=Pointer(Integer(PInt)+Sizeof(Integer));
      CopyMemory(PInt,@FTitle[1],Length(FTitle));//保存第二个字符串内容 // FreeMemory(AP);
      Result:=Len;
    end;//从收到的值中恢复
    procedure TxtData.SetData(const AP: Pointer; Len: Integer);
    var
      PInt:PInteger;
      i:Integer;
      xd:TxtData;
    begin
      PInt:=AP;
     // Len:=Integer(PInt);
      CopyMemory(@xd,AP,Len);
      i:=PInteger(PInt)^;//得到总长度  PInt:=Pointer(Integer(PInt)+Sizeof(Integer));
      i:=PInteger(PInt)^;//得到第一个字符串长度
      SetLength(FID,i);  PInt:=Pointer(Integer(PInt)+Sizeof(Integer));
      CopyMemory(@FID[1],PInt,Length(FID));//得到第一个字符串内容
      PInt:=Pointer(Integer(PInt)+Length(FID));
      i:=PInteger(PInt)^;
      SetLength(FTitle,i);//得到第二个字符串长度  PInt:=Pointer(Integer(PInt)+Sizeof(Integer));
      CopyMemory(@FTitle[1],PInt,Length(FTitle));//得到第二个字符串内容
    end;
      

  19.   

    楼主,你都知道?你知道个鸟!
    从你9楼的发言你是个什么水平大家也都看出来了。
    就你这种自以为是的态度+一个不开窍的榆木脑袋,你是彻底没前途的。
    早告诉你了,结构中的成员要不固定大小和位置,只能先打包到一个buffer中再发送,至于这个buffer用string、array还是getmem一块空间,都是一回事,没有本质的区别。 没有你异想天开的那种自适应record类型。
    听懂了没有?
    真是个TMD毫无灵气、冥顽不化的笨鸟。:)
    另,To ZyxIp,
    在record中private是无效的,所有成员仍然能从外部直接访问。
    就这个笨蛋的问题来看,除了在发送前动态建立结构,也没什么更好的办法,要不就是定义一个足够大的固定结构+压缩发送。
      

  20.   

    你知道个鸟 我什么水平关你鸟事 你他妈的 我寻个string的死点子你他妈的老强调你妈的毛你的方法 这就看出我的水平? 你真不要脸另外谢谢ZyxIp 
      

  21.   

    我就爱钻研这个srting的牛角尖我就不爱用别的类型 你他妈的老放屁毛
      

  22.   

    TxtData=record 这个是写错了。应该是 TxtData=class 
      

  23.   

    笨鸟,你懂不懂打包到string也能用sendbuffer呀?
    10楼都给你讲解了,你还是榆木脑袋死不开窍,是不是你妈怀孕的时候吃了死老鼠才生出你这么个钝胎来?
    也不知道哪家倒霉的公司用你这种垃圾开发“通信产品”?
    哈~~~哈~~~哈~~~哈~~~哈~~~
      

  24.   

    傻B 大包到string对我没用 你老提你屁话干嘛 这样方法对我的产品没用你老讲个鸡巴
      

  25.   

    你的脑袋榆木 笨的傻B老叫什么 我倒霉?哪个公司有你不是要倒闭了 可笑的东西另外感谢ZyxIp 
      

  26.   

    这个东西有办法的
    就算是不固定的结构也有办法
    但是确实需要组织成String或者Stream
    楼主出口成脏可不太好
    不管怎么说人家也是帮你
      

  27.   

    type 
      TxtData=record 
      cmd:string[100]; //在这里定义长度。
      S:string[100]; 
    end; xt:TxtData; IdUDPServer1.SendBuffer(serverIP,1001,xt,sizeof(xt)); 这样就OK了
      

  28.   

    回的人很多啊,说下sizeof这样的写法返回的永远是8的。TCP,UDP包都是有大小限制的,这个限制是在协议里,你无法改变.所以如果你包大,你只能修改程序去适应udp.
      

  29.   

    看了下 LZ的心态和水平确实有问题.
    不定长度的record不是不可以发送,但是要自己处理下 SendBuff哪有这样的功能啊?
    自己水平那么好为什么不用Socket API的.别人回答你的问题是看得起你,自己还在那里装大爷.
      

  30.   

    楼主一看就是代码工人 string是什么?是一个#0结尾的内存指针.
    SendBuf发送的是什么?字符?数字?自己也不了解机制就瞎说,别人好象教你 你还整2B一个.
    SendBuf是发送内容块里的内容 其中有个参数是指针头,另一个是偏移量.
    SB.我实在看不下去了.record是一个知道结构指针和string一样.string是#0结尾的,record不是
    如果你真的要发送这样的东西,你就要把record.String长度弄出来
    好让Socket知道你要发送多长的东西.
    SB.....