服务端用TServerSocket,客户端用TTcpClient。结构体在客户端和服务端都是这样定义的:  {Socket通讯结构体}
  Socket_Rec = packed record
    MsgType: String[2]; {命令字}
    MsgLen: Word;       {协议体长度}
    Msg: array of Byte; {协议内容}
  end;
  {定义指针}
  TSocket_Rec = ^Socket_Rec;  {实际要传输的数据}
  RefreshLink_Rec = packed record
    TheType      : Integer;    
    ClientIP     : string[15]; 
  end;
服务端:var
  Info: Socket_Rec;
  bodyInfo, bodyInfoRep: RefreshLink_Rec;
  LastTest: TSocket_Rec;....procedure TForm1.ServerSocketMainClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
  BufferLen,Len: Integer;
begin
  BufferLen := Socket.ReceiveLength;
  {接受}
  Socket.ReceiveBuf(Info,BufferLen);
  Move(Info.Msg,bodyInfo,Info.MsgLen);{只是接受,接受到的数据另做它用,这里就不写了}  {组织发送数据}
  bodyInfoRep.TheType := 2;
  bodyInfoRep.ClientIP := '192.168.2.2';  {发送}
  Len := SizeOf(Socket_Rec)-1+SizeOf(bodyInfoRep);
  GetMem(LastTest,Len);
  LastTest.MsgType := 'BA';
  LastTest.MsgLen := SizeOf(bodyInfoRep);
  Move(bodyInfoRep,LastTest.Msg,SizeOf(bodyInfoRep));
  Socket.SendBuf(LastTest^,Len);
  FreeMem(LastTest);
客户端:var
  Info: Socket_Rec;
  bodyInfo, bodyInfoRep: RefreshLink_Rec;
  LastTest: TSocket_Rec;....
procedure TForm1.btn1Click(Sender: TObject);
var
  Len: Integer;
  chr: array[0..9]of Char;
begin
  if not ClientSocket1.Active then
  begin
    ClientSocket1.RemoteHost := '192.168.0.136';
    ClientSocket1.RemotePort := '1013';
    ClientSocket1.Active := True;
  end;  {组织发送数据}
  bodyInfo.TheType := 1;
  bodyInfo.ClientIP := '192.168.0.136';  {发送}
  GetMem(LastTest,SizeOf(Socket_Rec)-1+SizeOf(bodyInfo));
  LastTest.MsgType := 'AA';
  LastTest.MsgLen := SizeOf(bodyInfo);
  Move(bodyinfo,LastTest.Msg,SizeOf(bodyInfo));
  ClientSocket1.SendBuf(LastTest^,SizeOf(Socket_Rec)-1+SizeOf(bodyInfo));
  FreeMem(LastTest);  {接收}
  ClientSocket1.ReceiveBuf(Info,100);
  Move(Info.Msg,bodyInfoRep,Info.MsgLen);
  memo1.line.add(bodyInfoRep.ClientIP);
end;客户端发送和接受都没有问题,但就是客户端程序关闭的时候报内存错误。
我把ReceiveBuf和SendBuf的内容改成array[0..10]of char试验了一下,就一切正常,说明是发送内容上的问题,请教高手指点。

解决方案 »

  1.   

    你的 array of Byte; 在哪分配的大小啊?
      

  2.   

    静态数组和动态数组内存分配是不一样的,静态数组时内存是连续分配的,而动态则未必!!!
    动态数组最好用setlength(a,100), 释放setlength(a,0);
      

  3.   

    {组织发送数据}
      bodyInfo.TheType := 1;
      bodyInfo.ClientIP := '192.168.0.136';  {发送}
      GetMem(LastTest,SizeOf(Socket_Rec)-1+SizeOf(bodyInfo));
      LastTest.MsgType := 'AA';
      LastTest.MsgLen := SizeOf(bodyInfo);
      Move(bodyinfo,LastTest.Msg,SizeOf(bodyInfo));
      ClientSocket1.SendBuf(LastTest^,SizeOf(Socket_Rec)-1+SizeOf(bodyInfo));
      FreeMem(LastTest);
      
     LastTest.Msg 的大小呢?
      

  4.   

    对了 记录指针 最好 new(p), dispose(p);静态数组和动态数组内存分配是不一样的,静态数组时内存是连续分配的,而动态则未必!!! 
    动态数组最好用setlength(a,100), 释放setlength(a,0); a:=nil;
    new(TSocket_Rec);
    .......
    setlength(TSocket_Rec.Msg,0); TSocket_Rec.Msg:=nil;
    dispose(TSocket_Rec);
      

  5.   

    LastTest.Msg实际上是个保存了bodyInfo结构的Byte数组啊,它的大小就是SizeOf(bodyInfo)
      

  6.   

    array of Byte并没有通过setlength去分配大小,而是直接GetMem分配一块内存,然后把结构给Move进去
      

  7.   

    这代码……先问你几个问题
      Socket_Rec = packed record
        MsgType: String[2]; {命令字}
        MsgLen: Word;       {协议体长度}
        Msg: array of Byte; {协议内容}
      end;
    1. SizeOf(MsgType)、SizeOf(Msg)、SizeOf(Sockt_Rec)分别都是多少?
    答案是3、4、92.
    var foo: Socket_Rec;
    begin
      SetLeng(foo.Msg, 100);
    end;
    现在假设 @foo 的地址是 $00123400,你认为通过上面的代码能知道 @foo.Msg[0] 的地址是多少么?如果可以知道的话,应该是多少?在你的代码中,出错的原因是在清理 Socket_Rec 结构的时候,rtl 企图自动释放 Msg 占用的内存,但是它的内容早就不知道是什么东西了,而不是一个正确的 array of Byte ,释放一个野指针当然很容易出错了
    有两种办法声明你的Socket_Rec,可以让你容易获得Msg的地址,同时不会产生多余的问题:  Socket_Rec1 = packed record
        MsgType: String[2]; {命令字}
        MsgLen: Word;       {协议体长度}
        Msg: array[0..0] of Byte; {协议内容}
      end;
      { or }
      Socket_Rec2 = packed record
        MsgType: String[2]; {命令字}
        MsgLen: Word;       {协议体长度}
        Msg: end of record; {协议内容}
      end;SizeOf(Socket_Rec1)、SizeOf(Socket_Rec2)分别是6、5
      

  8.   

    刚才Socket_Rec2中的Msg手误写错了,应该是
      Msg: record end;
      

  9.   

    解决了,Seamour兄说的在理,我把
      
    {Socket通讯结构体}
      Socket_Rec = packed record
        MsgType: String[2]; {命令字}
        MsgLen: Word;       {协议体长度}
        Msg: array of Byte; {协议内容}
      end;改成
      
    {Socket通讯结构体}
      Socket_Rec = packed record
        MsgType: String[2]; {命令字}
        MsgLen: Word;       {协议体长度}
        Msg: array [0..0] of Byte; {协议内容}
      end;就好了,谢谢各位