当我向客户端发送一个字符串(tkString)时,客户端在尝试重建 TValue 时告诉我(在 WMClientRecv 内部)访问冲突,为什么?-_-" 与其他类型的数据一起工作得很好......
例如,整数 (tkEnum)
这是服务器代码(将调用数据发送到客户端)
procedure TServerClass.InvokeMethod(const InvokableMethod: TInvokeableMethod; const MethodArg: TValue);
var
InvokeRec : packed record
Method: Array[0..19] of Char;
ArgRawSize: Integer;
ArgTypeInf: TTypeInfo;
ArgRawData: Array[0..255] of Byte;
end;
begin
// copy method name to record
lstrcpy(InvokeRec.Method, PChar(InvokableMethod));
// copy arg array to record
InvokeRec.ArgRawSize := MethodArg.DataSize;
if (MethodArg.DataSize <> 0) then
begin
MethodArg.ExtractRawData(PByte(@InvokeRec.ArgRawData[0]));
InvokeRec.ArgTypeInf := MethodArg.TypeInfo^;
end;
// send record
ServerSocket.Socket.Connections[idxSocket].SendBuf(PByte(@InvokeRec)^, SizeOf(InvokeRec));
end;
客户将其读取为:
procedure TClientClass.ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
var
Buffer: PByte;
BufLen: Integer;
InvokeRec: TInvokeRec;
begin
BufLen := Socket.ReceiveLength;
Memo1.Lines.Append(Format('%d: Received %d bytes', [Memo1.Lines.Count, BufLen]));
// dump keep-alive from recv buffer
if (BufLen = 64) then
begin
GetMem(Buffer, BufLen);
try
Socket.ReceiveBuf(Buffer^, BufLen);
finally
FreeMem(Buffer, BufLen);
end;
Exit;
end;
Socket.ReceiveBuf(PByte(@InvokeRec)^, BufLen);
SendMessage(Handle, WM_ClientRecv, 0, LPARAM(@InvokeRec));
end;
WMClientRecv 的例程:
procedure TClientClass.WMClientRecv(var Msg: TMessage);
var
// we send to server
ReadRec: TSharedRec;
// we recv from server
InvokeRecPtr: PInvokeRec;
Value: TValue;
begin
InvokeRecPtr := PInvokeRec(Msg.LParam);
case InvokeRecPtr.ArgRawSize of
0:
Value.Empty;
else
TValue.Make(PByte(@InvokeRecPtr.ArgRawData)^, PTypeInfo(@InvokeRecPtr.ArgTypeInf), Value);
end;
InvokableSubclass.ExecMethod(InvokeRecPtr.Method, Value);
end;
和ExceMethod:
procedure TInvokableSubclass.ExecMethod(const vmName: string; const Arg0: TValue);
var
LContext: TRttiContext;
begin
//
FSendMode := TextMode;
//
if (Arg0.DataSize = 0) then
begin
LContext.GetType(TInvokableSubclass).GetMethod(vmName).Invoke(Self, []);
Exit;
end;
LContext.GetType(TInvokableSubclass).GetMethod(vmName).Invoke(Self, Arg0);
end;