比如我在server和client定义一个StructHeaderRec记录包括信息CmdID(表示命令约定,server和client通过这个来识别执行什么),...(其它相关信息);(客户使用c实现,服务端使用delphi,目前测试都使用delphi)
//协议 
type
    TStructHeaderRec = packed Record
      Magic: Integer; //包的标记
      CmdID: Integer;  //命令编号
      LPARAM: Integer; //扩展参数
      MPARAM: Integer; //扩展参数
      DataLen: Integer;//长度
      Err: Integer;    //错误编号
    end;
定义一个客户记录
 type
    TCustomerRec = packed Record
      CustomerID: String[250];
      CustomerName: String[250];
    end;
定义一个商品记录
  type
    TProductRec = packed Record
      ProductID: String[250];
      ProductName: String[250];
    end;
.....如果在client发送客户信息使用
IdTCPClient.WriteBuffer(StructBodyRec,SizeOf(StructBodyRec),true);
IdTCPClient.WriteBuffer(CustomerRec,SizeOf(CustomerRec),true);如果在client发送商品信息使用
IdTCPClient.WriteBuffer(StructBodyRec,SizeOf(StructBodyRec),true);
IdTCPClient.WriteBuffer(ProducRec,SizeOf(ProducRec),true);在server端
procedure TServerForm.IdTCPServerExecute(AThread: TIdPeerThread);
var
  StructBody: TStructBodyRec;
  CustomerRec: TCustomerRec;
  ProductRec: TProductRec;
begin  AThread.Connection.ReadBuffer(StructBody.StructHeader, sizeof(StructBody.StructHeader));  if StructBody.StructHeader.Magic <> MagicFlag then Exit;  case StructBody.StructHeader.CmdID of
    1001:
    begin
      AThread.Connection.ReadBuffer(CustomerRec, sizeof(CustomerRec));
      CustomerRec.CustomerName := getCustomer(CustomerRec.CustomerID);
      AThread.connection.WriteBuffer(CustomerRec,SizeOf(CustomerRec),true);
    end;
    1002:
    begin
      AThread.Connection.ReadBuffer(ProductRec, sizeof(ProductRec));
      ProductRec.ProductName := getProductID(ProductRec.ProductID );
      AThread.connection.WriteBuffer(ProductID ,SizeOf(ProductID ),true);
    end;  else
    AThread.Connection.WriteLn('未知命令!');
  end;
end;按上面写没有什么问题,但是如果client在执行
IdTCPClient.WriteBuffer(StructBodyRec,SizeOf(StructBodyRec),true);
之后失败,头发送到了服务端,后面数据没有成功,我担心这个问题
IdTCPClient.WriteBuffer(CustomerRec,SizeOf(CustomerRec),true);如果我定义成
定义一个客户记录
 type
    TCustomerRec = packed Record
      StructHeaderRec : TStructHeaderRec ;
      CustomerID: String[250];
      CustomerName: String[250];
    end;
定义一个商品记录
  type
    TProductRec = packed Record
      StructHeaderRec : TStructHeaderRec ;
      ProductID: String[250];
      ProductName: String[250];
    end;在client使用
IdTCPClient.WriteBuffer(CustomerRec,SizeOf(CustomerRec),true);
但是我在server端不知道怎么先取出StructHeaderRec 结构,我的目的是想先取出CmdID,然后在分析数据处理;因为在服务端有很多这样业务要处理,请高手指点;最好给代码,谢谢了
  

解决方案 »

  1.   

    你每次都要发送TStructHeaderRec,那么就把这个头跟其他TCustomerRec之类合并为一个结构体
    然后一起发送过去
    server接收到流后先按TStructHeaderRec的大小读出,看看是接受什么流,确定之后在读流后面部分就行了,这样就不会说只发了一个头过去,不过你要tcp的一般都不会了
      

  2.   

    to constantine(飘遥的安吉儿)
      关键我现在不知道怎么实现 "server接收到流后先按TStructHeaderRec的大小读出,看看是接受什么流,确定之后在读流后面部分" 请多指教,
      

  3.   

    先发一个长度过去,按LENGTH+VALUE的方式处理
      

  4.   

    to proteus(聪聪) 
      以前没有搞过这方面,希望能给出实现代码,
      

  5.   

    这样定义type
        TStructHeaderRec = packed Record
          Magic: Integer; //包的标记
          CmdID: Integer;  //命令编号
          LPARAM: Integer; //扩展参数
          MPARAM: Integer; //扩展参数
          DataLen: Integer;//长度
          Err: Integer;    //错误编号
        end;
    定义一个客户记录
     type
        TCustomerRec = packed Record
          CustomerID: String[250];
          CustomerName: String[250];
        end;
    定义一个商品记录
      type
        TProductRec = packed Record
          ProductID: String[250];
          ProductName: String[250];
        end;
    type TMyRec = packed record
         handle : TStructHeaderRec;
         case integer of
           0 :  (CustomerRec : TCustomerRec);
           1 :  (ProductRec : TProductRec);
         .......end;
    每次发送发送与接收 TMyRec 接收后判断其内容标识作相应的处理就可以了~~~ 
      

  6.   

    楼主的担心不无道理, 象你这段代码中的 AThread.Connection.ReadBuffer(CustomerRec, sizeof(CustomerRec)); 在执行时, 你怎么敢肯定当时的Buffer里面已经有足够多的数据呢(数量>sizeof(CustomerRec))?象网络通讯这种处理异步数据传输的代码, 必须要等接收到足够的数据才能进行处理, 所以,在ReadBuffer之前肯定需要增加一个已接收数据量的判断,否则你的代码就属于“标准Microsoft风格代码”,存在着诸多Bug,过不久就需要发布一个对应的Service Pack。