zoukankan      html  css  js  c++  java
  • Socket怎样传递OLEVariant的多维数组

    webwx (2006-07-06 17:41:00) 
    比如:
    var
    tempVr: OleVariant;
    begin
    tempVr := VarArrayCreate([1..2], varOleStr);
    tempVr[1] := VarArrayOf([1, 2, 3, 4, 5]);
    tempVr[2] := VarArrayOf([6, 7, 8, 9, 10]);
    end;
    象上面的OleVariant的tempVr万能变量就是一个多位数据,怎样能通过Socket传递呢?
    而且还要是TCP的,因为要保证这个万能变量能够正确传递。
    能不能一起讨论一下关于对象传递呢? 呵呵 小弟直接是不懂WinSock编程。只是原理
    比较模糊啊,想练练手。
    蓝叶菱 (2006-07-07 09:18:52) 
    var
    tempVr: OleVariant;
    begin
    tempVr := VarArrayCreate([1,5,1,2], varinteger);//创建一个5列2行的数组
    tempvr[1,1]:=xxxxx;
    tempvr[2,1]:=xxxx;
    tempvr[3,1]:=xxxxx;

    流传输的前期转换
    procedure TForm2.VariantToStream (const v : olevariant;
                                     Stream : TMemoryStream);
    var
    p : pointer;
    begin
    Stream.Position := 0;
    Stream.Size := VarArrayHighBound (v, 1) - VarArrayLowBound(v,  1) + 1;
    p := VarArrayLock (v);
    Stream.Write (p^, Stream.Size);
    VarArrayUnlock (v);
    Stream.Position := 0;
    end;

    procedure TForm2.StreamToVariant (Stream : TMemoryStream; var v : OleVariant);
    var
    p : pointer;
    begin
    v := VarArrayCreate ([0, Stream.Size - 1], varByte);
    p := VarArrayLock (v);
    Stream.Position := 0;
    Stream.Read (p^, Stream.Size);
    VarArrayUnlock (v);
    end;
    SOCKET发送流应该很简单吧。。
    z_cd (2006-07-07 09:20:14) 
    (楼上的封包算法只能对付一维简单数组吧,楼主的多维数组就不行了吧)

    步骤:1.将OleVariant转换成Stream流格式
         2.然后用ClientWinSocket.SendStream或者用Socket API自己写

    其中:OleVariant --> Stream 算法比较复杂,给大家贡献一段比较成熟的代码(能保证万能变量正确封包)如下:

    { WriteOleVariant, ReadOleVariant }
    type
    PIntArray = ^TIntArray;
    TIntArray = array[0..0] of Integer;
    const
    EasyArrayTypes = [varSmallInt, varInteger, varSingle, varDouble, varCurrency,
    varDate, varBoolean, varByte];

    VariantSize: array[0..varByte] of Word  = (0, 0, SizeOf(SmallInt), SizeOf(Integer),
    SizeOf(Single), SizeOf(Double), SizeOf(Currency), SizeOf(TDateTime), 0, 0,
    SizeOf(Integer), SizeOf(WordBool), 0, 0, 0, 0, 0, SizeOf(Byte));
    resourcestring
    SBadVariantType = 'Unsupported variant type: %s';

    procedure WriteOleVariant(const Value: OleVariant; Stream: TStream);

    procedure WriteArray(const Value: OleVariant; Stream: TStream);
    var
       LVarData: TVarData;
       VType: Integer;
       VSize, i, DimCount, ElemSize: Integer;
       LSafeArray: PSafeArray;
       LoDim, HiDim, Indices: PIntArray;
       V: OleVariant;
       P: Pointer;
       {$IFDEF VER140}
       function FindVarData(const V: Variant): PVarData;
       begin
         Result := @TVarData(V);
         while Result.VType = varByRef or varVariant do
           Result := PVarData(Result.VPointer);
       end;
       {$ENDIF}
    begin
       LVarData := FindVarData(Value)^;
       VType := LVarData.VType;
       LSafeArray := PSafeArray(LVarData.VPointer);

       Stream.Write(VType, SizeOf(Integer));
       //if FGetHeader then Inc(FHeaderSize, SizeOf(Integer));
       DimCount := VarArrayDimCount(Value);
       Stream.Write(DimCount, SizeOf(DimCount));
       //if FGetHeader then Inc(FHeaderSize, SizeOf(Integer));
       VSize := SizeOf(Integer) * DimCount;
       GetMem(LoDim, VSize);
       try
         GetMem(HiDim, VSize);
         try
           for i := 1 to DimCount do
           begin
             LoDim[i - 1] := VarArrayLowBound(Value, i);
             HiDim[i - 1] := VarArrayHighBound(Value, i);
           end;
           Stream.Write(LoDim^,VSize);
           Stream.Write(HiDim^,VSize);
           //if FGetHeader then Inc(FHeaderSize, SizeOf(Integer) * 2);
           if VType and varTypeMask in EasyArrayTypes then
           begin
             ElemSize := SafeArrayGetElemSize(LSafeArray);
             VSize := 1;
             for i := 0 to DimCount - 1 do
               VSize := (HiDim[i] - LoDim[i] + 1) * VSize;
             VSize := VSize * ElemSize;
             P := VarArrayLock(Value);
             try
               Stream.Write(VSize, SizeOf(VSize));
               //if FGetHeader then Inc(FHeaderSize, SizeOf(Integer));
               Stream.Write(P^,VSize);
             finally
               VarArrayUnlock(Value);
             end;
           end else
           begin
             //FGetHeader := False;
             GetMem(Indices, VSize);
             try
               for I := 0 to DimCount - 1 do
                 Indices[I] := LoDim[I];
               while True do
               begin
                 if VType and varTypeMask <> varVariant then
                 begin
                   OleCheck(SafeArrayGetElement(LSafeArray, Indices^, TVarData(V).VPointer));
                   TVarData(V).VType := VType and varTypeMask;
                 end else
                   OleCheck(SafeArrayGetElement(LSafeArray, Indices^, V));
                 WriteOleVariant(V, Stream);
                 Inc(Indices[DimCount - 1]);
                 if Indices[DimCount - 1] > HiDim[DimCount - 1] then
                   for i := DimCount - 1 downto 0 do
                     if Indices[i] > HiDim[i] then
                     begin
                       if i = 0 then Exit;
                       Inc(Indices[i - 1]);
                       Indices[i] := LoDim[i];
                     end;
               end;
             finally
               FreeMem(Indices);
             end;
           end;
         finally
           FreeMem(HiDim);
         end;
       finally
         FreeMem(LoDim);
       end;
    end;

    var
    I, VType: Integer;
    W: WideString;
    begin
    VType := VarType(Value);
    if VType and varArray <> 0 then
       WriteArray(Value, Stream)
    else
       case (VType and varTypeMask) of
         varEmpty, varNull:
           Stream.Write(VType, SizeOf(Integer));
         varOleStr:
         begin
           W := WideString(Value);
           I := Length(W);
           Stream.Write(VType, SizeOf(Integer));
           Stream.Write(I,SizeOf(Integer));
           Stream.Write(W[1], I * 2);
           //if FGetHeader then Inc(FHeaderSize, SizeOf(Integer) * 2);
         end;
         varDispatch:
         begin
           raise Exception.CreateResFmt(@SBadVariantType, [IntToHex(VType, 4)]);
         end;
         varVariant:
         begin
           if VType and varByRef <> varByRef then
             raise Exception.CreateResFmt(@SBadVariantType, [IntToHex(VType, 4)]);
           I := varByRef;
           Stream.Write(I, SizeOf(Integer));
           //if FGetHeader then Inc(FHeaderSize, SizeOf(Integer));
           WriteOleVariant(Variant(TVarData(Value).VPointer^), Stream);
         end;
         varUnknown:
           raise Exception.CreateResFmt(@SBadVariantType, [IntToHex(VType, 4)]);
       else
         Stream.Write(VType, SizeOf(Integer));
         //if FGetHeader then Inc(FHeaderSize, SizeOf(Integer));
         if VType and varByRef = varByRef then
           Stream.Write(TVarData(Value).VPointer^, VariantSize[VType and varTypeMask])
         else
           Stream.Write(TVarData(Value).VPointer, VariantSize[VType and varTypeMask]);
       end;
    end;

    type
    TVarFlag = (vfByRef, vfVariant);
    TVarFlags = set of TVarFlag;

    function ReadOleVariant(Stream: TStream): OleVariant;

    function ReadArray(VType: Integer; Stream: TStream): OleVariant;
    var
       //Flags: TVarFlags;
       LoDim, HiDim, Indices, Bounds: PIntArray;
       DimCount, VSize, i: Integer;
       {P: Pointer;}
       V: OleVariant;
       LSafeArray: PSafeArray;
       P: Pointer;
    begin
       VarClear(Result);
       Stream.Read(DimCount, SizeOf(DimCount));
       VSize := DimCount * SizeOf(Integer);
       GetMem(LoDim, VSize);
       try
         GetMem(HiDim, VSize);
         try
           Stream.Read(LoDim^, VSize);
           Stream.Read(HiDim^, VSize);
           GetMem(Bounds, VSize * 2);
           try
             for i := 0 to DimCount - 1 do
             begin
               Bounds[i * 2] := LoDim[i];
               Bounds[i * 2 + 1] := HiDim[i];
             end;
             Result := VarArrayCreate(Slice(Bounds^,DimCount * 2), VType and varTypeMask);
           finally
             FreeMem(Bounds);
           end;
           if VType and varTypeMask in EasyArrayTypes then
           begin
             Stream.Read(VSize, SizeOf(VSize));
             P := VarArrayLock(Result);
             try
               Stream.Read(P^, VSize);
             finally
               VarArrayUnlock(Result);
             end;
           end else
           begin
             LSafeArray := PSafeArray(TVarData(Result).VArray);
             GetMem(Indices, VSize);
             try
               FillChar(Indices^, VSize, 0);
               for I := 0 to DimCount - 1 do
                 Indices[I] := LoDim[I];
               while True do
               begin
                 V := ReadOleVariant(Stream);
                 if VType and varTypeMask = varVariant then
                   OleCheck(SafeArrayPutElement(LSafeArray, Indices^, V)) else
                   OleCheck(SafeArrayPutElement(LSafeArray, Indices^, TVarData(V).VPointer^));
                 Inc(Indices[DimCount - 1]);
                 if Indices[DimCount - 1] > HiDim[DimCount - 1] then
                   for i := DimCount - 1 downto 0 do
                     if Indices[i] > HiDim[i] then
                     begin
                       if i = 0 then Exit;
                       Inc(Indices[i - 1]);
                       Indices[i] := LoDim[i];
                     end;
               end;
             finally
               FreeMem(Indices);
             end;
           end;
         finally
           FreeMem(HiDim);
         end;
       finally
         FreeMem(LoDim);
       end;
    end;

    var
    I, VType: Integer;
    W: WideString;
    //TmpFlags: TVarFlags;
    Flags: TVarFlags;
    begin
    VarClear(Result);
    Flags := [];
    Stream.Read(VType, SizeOf(VType));
    if VType and varByRef = varByRef then
       Include(Flags, vfByRef);
    if VType = varByRef then
    begin
       Include(Flags, vfVariant);
       Result := ReadOleVariant(Stream);    //TmpFlags, Data);
       Exit;
    end;
    if vfByRef in Flags then
       VType := VType xor varByRef;
    if (VType and varArray) = varArray then
       Result := ReadArray(VType, Stream) else
    case VType and varTypeMask of
       varEmpty: VarClear(Result);
       varNull: Result := NULL;
       varOleStr:
       begin
         Stream.Read(I, SizeOf(Integer));
         SetLength(W, I);
         Stream.Read(W[1], I * 2);
         Result := W;
       end;
       varDispatch:
         raise Exception.CreateResFmt(@SBadVariantType, [IntToHex(VType, 4)]);
       varUnknown:
         raise Exception.CreateResFmt(@SBadVariantType, [IntToHex(VType, 4)]);
    else
       TVarData(Result).VType := VType;
       Stream.Read(TVarData(Result).VPointer, VariantSize[VType and varTypeMask]);
    end;
    end;
    delphfans (2006-07-07 09:41:19) 
    var
    tempVr: OleVariant;
    c:array[0..4096] of char;
    size:integer;
    begin
    tempVr := VarArrayCreate([1,12,1,2], varinteger);//创建一个5列2行的数组
    tempvr[1,1]:=23;
    tempvr[2,1]:=23;
    tempvr[3,1]:=23;
    size:=VarArrayHighBound (tempVr, 1) - VarArrayLowBound(tempVr,  1) + 1;
    strmove(c,@tempVr, size);
    IdTCPClient1.Socket.Send(c,size);
    end;
    webwx (2006-07-07 10:35:18) 
    各位仁兄真是高见啊,我会验证的。。。 现在不能给出自己的想法哦。。。 继续。鼓励
    Writer (2006-07-08 12:04:32) 
    不知楼上几位有没考虑到,字符串引用问题。比如你发送的只是字符串指针而不是字符串。复杂就在于置。

  • 相关阅读:
    88. Merge Sorted Array【leetcode】算法,java将两个有序数组合并到一个数组中
    70. Climbing Stairs【leetcode】递归,动态规划,java,算法
    136. Single Number【LeetCode】异或运算符,算法,java
    605. Can Place Flowers种花问题【leetcode】
    175. Combine Two Tables【LeetCode】-LEFT JON 和RIGHT JOIN,两张表关联查询-java -sql入门
    67. Add Binary【LeetCode】
    4.1 yaml配置注入
    2.1容器功能-组件添加
    1.2自动配置
    json乱码问题全配置
  • 原文地址:https://www.cnblogs.com/railgunman/p/1888724.html
Copyright © 2011-2022 走看看