zoukankan      html  css  js  c++  java
  • 研究QQ、Fetion、Msn的socket连接

    LumaQQ 发送信息流程:

    MessageManager.SendIM

    PackageManager.Sendpacket: port = QQPort.Main.Name

    ConnectionManager.EnsureConnection == 确认ConnectionPool 建立socket链接

    ConnectionPool. Send = IConnection.Send()

    TCPConnection.Send 

    SocketConnection.Send = socket.Send(sendBuf.ToByteArray(), 0, sendBuf.Length, SocketFlags.None);

    发送后就没有下文了。

    关闭发送:

    ConnectionPool.Release(id) 

    SocketConnection.Close 

    当ConnectionPool.newTCPConnection的时候发生。 

    当QQPOrt.Create的时候发生。 

    当EnsureConnection的时候发生。

    可以看见,发送信息后,socket被闲置了。 发送的端口是80. = LoginPort


    小结发送: 

    本质上,发送信息等都是一种socket短链接。 

    客户端发送之后,如果不需要服务器ack,则断开链接(代码中并没有。) 

    基本上所有的发送package都需要服务器ack。 如果需要ack,则package发送之后,压入重发堆栈,直到超时、收到ack。

    接收代码分析:

    LoginManager.Logn()QQClient.LoginPort = QQGlobal.QQ_PORT_TCP; 实际上也是80端口。

    然后也是来到了PackageManager.SendPackageAnyway.

    QQClient.ConnectionManager.ConnectionPool.Send(port, packet, false); 

    看来是接收还是发送,就是一个标志位: 

    if (QQClient.ConnectionManager.EnsureConnection(port, true)) 表示接收 true = start 但是默认都是true

    所以登录之后,当发送第一个package的时候,代码首先创建了SocketConnection. 这个时候就进入了等待状态。 Receive.

    同时发送的时候仍然使用了这个socket。 即发送和接收都是一个socket。即使他之前在等待接收信息。 

    小结一下LumaQQ的工作流程:

    登录的时候, packetmanager初始化trigger(packetincometrigger/resendtrigger/keepalivetrigger)

    然后调用了 QQClient.PacketManager.SendPacketAnyway(outPacket, QQPort.Main.Name);

    来到Packetmanager=> if (QQClient.ConnectionManager.EnsureConnection(port, true))

    => IConnection conn = QQPort.GetPort(portName).Create(QQClient, QQClient.LoginServerHost, QQClient.LoginPort, start);

    来到OOPort.Create: policy = new ConnectionPolicy(client, Name, ProtocolFamily.Basic, ProtocolFamily.Basic);

    而这个狗屁Policy.ID = QQPOrt.name

    然而这个狗屁QQPort.Name实际上只有一个值是有意义的 = Main。真他妈的设计者脑子里面装的是什么狗屎垃圾。所以最终发现这个垃圾policy.id永远是一样的。 导致了ConnectionPool获取的Connection也一定是唯一一个。

    这样就创建了一个等待接收的socket 。然后发送的时候是:

    QQClient.ConnectionManager.ConnectionPool.Send(port, packet, false); 

    socket接收到信息后,放入queue(@Packetmanager), 同时在ThreadExcutor添加了一个trigger。(恶心的代码是在trigger使用标志位isrunning判断当前trigger是否正在运行。而这个trigger竟然是packetmanager的一个field。)

    PacketIncomeTrigger被唤醒之后,调用了Call。

    他就调用了Packetmanager.RemoveIncomingPacket / FirePacketArrivedEvent。 

    然后就调用了ProcessorRouter=>IPacketListener => BasicFamilyProcessor.PacketArrived =>

    MessageManager.OnReceiveNormalIM => 调用了代理回调到了客户。 

    马勒戈壁的,突然发现一个狗屁Policy.ID去调用缓存了的connection. 真他妈的什么代码。简直就是浪费时间。

    一句话小结,整个LumaQQ就是一堆垃圾,可以去烧了。没有任何步骤可言、没有任何架构思想;接收和发送使用相同的socket,而且没有去考虑是否断线了。之类的。做了个好像短链接的东西,实际上还是原来正在BeginReceive的connection。我 FUCK

    ------------------------------------------------------------------

    Fetion 估计也是类似的FUCKing 设计。因为参与设计的人就是那些。 

    一切从登录开始:Login=> 

    this.connection = new SipConnection(); 

    LoginManager. GetSysConfig(user, connection);

    SIPCSingInStep1 =>  connection.Connect(addrStrArr[0], addrStrArr[1]); =?>this.socket = TcpHelper.CreateSocket(ip, port);

    string result = TcpHelper.SendAndReceive(connection.SipSocket, sendData); 

    SIPCSingInStep2  string result = TcpHelper.SendAndReceive(connection.SipSocket, sendData);

    MyFetion.Initialize = this.connection.StartListen(this.user.Uri);+>this.ListenAsync(this.socket);+state.BeginReceive

    基本上思路类似,开了socket之后等待,同时日后的发送仍然时候了这个socket。 

    ------------------------------------------------------------------

    最后是MSN。 

    messenger.Connect(); 

    nsMessageProcessor.Connect(); (@SocketMessageProcessor

    socket = GetPreparedSocket();  =》socket).BeginConnect=》BeginDataReceive

    NSMessageHandler=> MessageProcessor.SendMessage(new NSMessage("XFR", new string[] { "SB" }));

    最后就是SocketMessageProcessor.SendSocketData()

    结构比较流水,虽然臃肿,但是没有luma这么垃圾。 

    ------------------------------------------------------------------

    最后看看GTalk。看看牛人如何玩socket

    XmppClientConnection xmppCon = new XmppClientConnection(); 

    xmppCon.Open();

     OpenSocket(); 

    SocketConnect(base.Server, base.Port); 

    ClientSocket.Connect(); 

    _socket.BeginConnect(endPoint, new AsyncCallback(EndConnect), null); 

    this.Receive();

    我C!!!马勒戈壁的。看见没有!!GTALK的代码就是如此的简洁!这才是代码!这才是享受! 这才叫做开源!!!称得上开源的,拜托!请先像XMPP这样,简洁明了。并且没有错误。否则,不是开源,而是丢弃、放弃! 

    马勒戈壁的。。。看了一堆不爽的代码,到了gtalk才看到一点像样的东西。。。。 

  • 相关阅读:
    Bounded Context
    Unity3D研究院之IOS本地消息通知LocalNotification的使用(六十七)
    SVN服务器搭建和使用
    进度条
    XQuery获取节点的属性名与值
    AnimatorStateInfo
    Unity3D 中脚本执行的先后顺序
    Unity里面的自动寻路(二)
    Unity里面的自动寻路(一)
    java遍历文件夹两种方式
  • 原文地址:https://www.cnblogs.com/zc22/p/1754425.html
Copyright © 2011-2022 走看看