DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: wjy13061029975
今日帖子: 3
在线用户: 2
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 jfhyn (贺兰之边) ★☆☆☆☆ -
普通会员
2019/5/9 21:57:01
标题:
请教大家,Delphi-Cross-Socket的UserData,UserObject的用法 浏览:1907
加入我的收藏
楼主: Delphi-Cross-Socket的TestCrossSocket中,我发送数据增加UserData数据,但是在服务端却接收不到.
//客户端
procedure TfmMain.Button2Click(Sender: TObject);
const
  DATA_SIZE = 10 * 1024 * 1024;
var
  LStream: TBytesStream;
  LConns: TArray<ICrossConnection>;
  I: Integer;
  B: Byte;
begin
  LConns := FSocket.LockConnections.Values.ToArray;
  if (LConns <> nil) then
  begin
    LStream := TBytesStream.Create(nil);
    for I := 1 to DATA_SIZE do
    begin
      B := RandomRange(0, 255 + 1);
      LStream.Write(B, SizeOf(Byte));
    end;
    LStream.Position := 0;
  //增加的UserData数据----------
    LConns[0].UserData := PChar('abcdefg');
    LConns[0].SendStream(LStream,
      procedure(AConnection: ICrossConnection; ASuccess: Boolean)
      begin
        TThread.Queue(nil,
          procedure
          begin
          if ASuccess then
          ShowMessage( 'SendStream SUCCESS!!' + FSendCount.ToString)
          else
          ShowMessage('SendStream FAILED!!');
          end);
        FreeAndNil(LStream);
      end);
  end;
  FSocket.UnlockConnections;
end;
服务端
procedure TfmMain.OnReceived(Sender: TObject; AConnection: ICrossConnection;
  ABuf: Pointer; ALen: Integer);
begin
  //此处接收不到数据,一直是nil----------
 if AConnection.UserData <> nil then
   log(PChar(AConnection.UserData));
  AtomicIncrement(FRcvdCount);
  AtomicIncrement(FRcvdBytes, ALen);
end;

不知道为什么,恳请大神指导一下.
----------------------------------------------
-
作者:
男 xuchuantao (暗黑天使) ★☆☆☆☆ -
普通会员
2019/5/9 23:25:51
1楼: 应该你没有分配内存,过程结束后系统回收了字符串的内存造成的,我这是没有问题的.
唯一不同的是我这是结构体而且是手动分配内存的.
----------------------------------------------
按此在新窗口浏览图片
作者:
男 abcjingtong (jingtong) ★☆☆☆☆ -
普通会员
2019/5/10 15:15:51
2楼: 可以把UserData写到LStream里一起发送了,这样做需要客户端处理下粘包
----------------------------------------------
18114532@qq.com
作者:
男 abcjingtong (jingtong) ★☆☆☆☆ -
普通会员
2019/5/10 17:09:41
3楼: 个人觉得CrossSocket对有经验的开发人员更合适,而DIOCP适合注重应用层面的人士,我个人把DIOCP中的MsgPack类用到CrossSocket中然后写了粘包处理,算是二者的结合吧。如果有需要我可以发给你。
----------------------------------------------
18114532@qq.com
作者:
男 jfhyn (贺兰之边) ★☆☆☆☆ -
普通会员
2019/5/10 23:17:51
4楼: 现在明白了UserData等的用法,是为了附加信息,处理发送或者返回数据的完整性.
谢谢大家!
@abcjingtong 3楼兄弟,能否把Demo发给我学习一下,谢谢!
----------------------------------------------
-
作者:
男 akuan54 (SKL) ★☆☆☆☆ -
普通会员
2020/1/31 11:58:57
5楼: @abcjingtong 兄弟,能否把Demo 提供出来,学习学习,感谢!谢谢!
----------------------------------------------
-
作者:
男 jfhyn (贺兰之边) ★☆☆☆☆ -
普通会员
2020/1/31 13:22:59
6楼: @akuan54 UserObject UserData就是为了方便处理数据的,接收或者发送时创建一个UserObject就行,我有时会把DataSet传给UserData.
----------------------------------------------
-
作者:
男 akuan54 (SKL) ★☆☆☆☆ -
普通会员
2020/1/31 14:58:33
7楼: @jfhyn 谢谢您的说明。会再研究看看的。

对于 @abcjingtong 有关 [MsgPack类用到CrossSocket中然后写了粘包处理] 这部份有兴趣,希望 @abcjingtong 有时间的话可以发出来提供大家学习。感谢。
----------------------------------------------
-
作者:
男 abcjingtong (jingtong) ★☆☆☆☆ -
普通会员
2020/1/31 19:10:45
8楼: 对不起,因为自己的忙一直没有回复大家的需求,我现在始写一下,今晚21点前应该可以完成
----------------------------------------------
18114532@qq.com
作者:
男 abcjingtong (jingtong) ★☆☆☆☆ -
普通会员
2020/1/31 20:16:39
9楼: 由于Socket的分片传输机制,Socket接收端每次接收的数据其实也是一个个片断(具体片断大小怎么分请见相关的协议),所以需要对接收到的数据判断是否完整,以便将完整的数据交到业务逻辑里处理。
Socket通讯双方都有一个连接对象Connection,CrossSocket也不例外,所有的Socket事件几乎都有这个参数,比如
procedure THCRSocket.LogicConnected(AConnection: ICrossConnection);
procedure THCRSocket.LogicDisconnected(AConnection: ICrossConnection);
procedure THCRSocket.LogicReceived(AConnection: ICrossConnection; ABuf: Pointer; ALen: Integer);
为了处理粘包,我们需要有一个对象,能记录下来当前接收的数据,并在接收数据前绑定到Connection上面,
这样之后Connection就一直能有这个对象供我们操作了,比如我创建了一个叫TBufferLink的对象,
在连接一旦建立就绑定到UserObject上
procedure THCRSocket.LogicConnected(AConnection: ICrossConnection);
begin
  inherited LogicConnected(AConnection);
  AConnection.UserObject := TBufferLink.Create;
end;
当然,如果连接断开了,就把这个对象释放掉
procedure THCRSocket.LogicDisconnected(AConnection: ICrossConnection);
begin
  inherited LogicDisconnected(AConnection);
  if Assigned(AConnection.UserObject) then
    TBufferLink(AConnection.UserObject).Free;
end;
在每次收到数据时,把收到的数据拼装到这个TBufferLink里,并由它给出数据是否接收完整了,
注意接收到数据和接收完整是两个概念,
procedure THCRSocket.LogicReceived(AConnection: ICrossConnection; ABuf: Pointer; ALen: Integer);
var
  vRecvBuffer: TBufferLink;
  vDecodeObj: TObject;
begin
  inherited LogicReceived(AConnection, ABuf, ALen);
  vRecvBuffer := AConnection.UserObject as TBufferLink;
  vRecvBuffer.AddBuffer(ABuf, ALen);  // 数据拼装

  vDecodeObj := DecodeRecvBuffer(vRecvBuffer);  // 返回数据是否接收完整
  if Integer(vDecodeObj) = -1 then  // 错误的包格式, 关闭连接
  begin
    Active := False;
    Exit;
  end
  else
  if vDecodeObj <> nil then  // 接收完整了
  begin
    try
      if Assigned(FOnReceivedData) then  // 交给业务逻辑处理
        FOnReceivedData(AConnection, TBytesStream(vDecodeObj));
    finally
      TBytesStream(vDecodeObj).Free;
    end;
  end;
end;
具体DecodeRecvBuffer里的实现不算很复杂,但理解起来有点吃力,有需要了再讲吧,附上我自己封装的2个单元,如果还有缺少告诉我
HCSocket.pas里有THCRServer和THCRClient,可分别作为服务端和客户端的对象使用,如
  FMsgServer := THCRServer.Create;
  FMsgServer.Port := 12820;
  FMsgServer.OnConnected := DoServerConnected;
  FMsgServer.OnDisconnected := DoServerDisconnected;
  FMsgServer.OnReceiveData := DoServerReceiveData;
  FMsgServer.OnError := DoServerError;
----------------------------------------------
18114532@qq.com
作者:
男 abcjingtong (jingtong) ★☆☆☆☆ -
普通会员
2020/1/31 20:19:28
10楼: HCSocket.pas,自己改后缀
此帖子包含附件:abcjingtong_2020131201928.txt 大小:11.8K
----------------------------------------------
18114532@qq.com
作者:
男 abcjingtong (jingtong) ★☆☆☆☆ -
普通会员
2020/1/31 20:23:08
11楼: utils_buffer.pas,来自DIOCP非我原创,自己改后缀,
盒子这传文件不是一般的不稳定。
此帖子包含附件:abcjingtong_202013120238.txt 大小:71.4K
----------------------------------------------
18114532@qq.com
作者:
男 akuan54 (SKL) ★☆☆☆☆ -
普通会员
2020/1/31 21:33:29
12楼: @abcjingtong 感激您的分享,定当好好学习一番。再次感谢。
----------------------------------------------
-
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行837.8906毫秒 RSS