提示:要学习客户端和服务器如何交互, 就是去找它们通信协议中对应命令发送过程。 对于登录过程,对应登录命令就是去分析CID_LOGIN_REQ_USERLOGIN

客户端登录模块

客户端工程一共包含十个项目
Moudles项目下的 Login文件夹中找到LoginDialog.cpp(有一个_DoLogin()函数) ;在TcpClient文件夹中找到 TcpClientModule.cpp(有一个doLogin()函数),
这两个是最关键的步骤,在_DoLogin(),可以看到

还记得客户端的配置吗?
http://127.0.0.1:8080/msg_server下边这个函数的调用就是发起http请求的意思
在LoginDlg.cpp 200行处
module::getHttpPoolModule()->pushHttpOperation(pOper);

当Login_server服务器处理了这条http请求(若成功,会将分配给你的msg_server服务器的ip,port, name等信息以json串的格式返回给你)

在LoginDlg.cpp 207行处
module::TTConfig* pCfg = module::getSysConfigModule()->getSystemConfig();
TTConfig对象就保存了服务器返回的msg_server信息(ip, port等)

在上边我们已经得到http请求的回应,此时我们已经有了
LoginDlalog.cpp中213行可以看到创建了一个LoginOperation(继承自ICallbackOpertaion)对象,通过startOperation()将这个对象当作一个任务放入了一个list待执行队列中, 并为它注册了一个回调函数(不只是登录模块是这样,其他的任务也是以继承ICallbackOpertaion类的方式, 将其子类实例化对象放入这个list链表中,只是这里是LoginOperation这种子类。)
如下:

LoginOperation* pOperation = new LoginOperation(        //去看它的实现, 调用了_DoLoginBIND_CALLBACK_1(LoginDialog::OnOperationCallback), loginparam);imcore::IMLibCoreStartOperation(pOperation);

在上边我们只是将登录任务放进了待执行队列,那么在哪里调用呢?

LoginOperation.cpp中48行可以看到doLogin在这里被调用(doLogin里面可以找到发送CID_LOGIN_REQ_USERLOGIN命令的语句)。

先获取msg_server的ip,port信息,在TTConfig结构体内可以查看
module::TTConfig* pCfg = module::getSysConfigModule()->getSystemConfig();
IM::Login::IMLoginRes* pImLoginResp = (IM::Login::IMLoginRes*)module::getTcpClientModule()->doLogin(server, pCfg->msgServPort,m_loginParam.csUserName,m_loginParam.password);

doLogin是在processOpertion中调用的,processOpertion是一个重写的函数, 不同的Operation类(这里是LoginOperation)对应着不同功能的processOpertion,可以把它理解为去执行任务(这里指登录任务)

这里要明白,发送消息的前提是建立了连接,doLogin函数中的第一行就是建立连接过程,这个连接和最开始的http连接获取msg_server不一样, http请求是客户端去连接的Login_server,为了获取msg_server信息, 而这次是客户端与msg_server建立连接。

TcpClientModule_Impl.cpp 148行
IMLibCoreConnect(util::cStringToString(linkaddr), port);

简单的理解当你点击登录按钮,会触发_DoLoing()需要做两件事, 先发送http消息请求,Login_server服务器返回给你msg_server服务器信息(ip,port,name),后在doLogin()中去连接msg_server进行一系列的信息验证过程。

服务器接收模块

主要分析, 在哪接收客户端的请求,以及如何为这条连接做负载均衡(将这条连接放到负载最小的msg_server上)。

客户端的请求包含了两部分第一部分是http请求(用Login_server来接收处理, 目的是给客户端找一个msg_server), 第二部分是具体的命令发送如:CID_LOGIN_REQ_USERLOGIN(用第一步找到的msg_server来接收处理)

抓住主线:
一:在Login_server中接受客户端的http连接

 http://127.0.0.1:8080/msg_server

Login_server服务器将负载最小的msg_server服务器信息(ip,port等)以json格式返回给客户端。
二:然后客户端再去连接这个msg_server, 说白了,Login_server只是一个中转站,msg_server才是与客户端一直交流的主要服务器。

首先在longin_server.cpp找, 在118行,我们可以看到longin_server.cpp通过netlib_listen监听了3个端口, 其中的HttpPort(也就是8080端口,就是负责处理登录连接的第一步,处理http请求消息, 登录连接的第二步是与msg_server交互)

netlib_listen就是封装了listen过程,将这个监听套接字(fd)注册到了epoll_wait()中,并且设置了回调函数(http_callback第49行),对比我们以往的C语言编程思维,因为Teamtalk是C++写的,它将所有的套接字(fd)都封装成了一个CBaseSocket对象,并且将这个对象通过map映射在hash表中保存,fd作为key,CBaseSocket对象作为value 当客户端点击登录的时候, 就会触发消息,所以我们需要去找epoll_wait() 在哪,在EventDispatch.cpp中的354行可以找到,当fd有消息的时候,通过我们刚刚说的那个hash映射表,因为key是fd, 我们就可以找到对应的CBaseSocket对象进行一系列处理(Read, Write等)。

登录第一步处理http连接(在login_server上)

当客户端点击登录后(_DoLogin), 服务器的HttpPort(也就是8080端口)对应的监听fd 被触发,这里一定要明白,客户端点了登录按钮后,涉及了两个步骤,先是发送http请求来向Login_server服务器获取负载最小的msg_server服务器的信息(ip,port), 所以首先讨论的是Login_server处理http请求。 通过监听fd找到对应的CBaseSocket对象,进一步调用pSocket->OnRead(); 在OnRead中可以看到_AcceptNewSocket,它的功能就是将这个客户端点击登录的连接接收,分配一个CBaseSocket对象与之(客户端点击登录的连接)绑定,放到全局hash映射表中,并注册到epoll_wait的队列中,在这个函数(_AcceptNewSocket)的最后一行可以看到m_callback(m_callback_data, NETLIB_MSG_CONNECT, (net_handle_t)fd, NULL), 这个m_callback就是一开始为监听fd注册的http_callback函数(在longin_server.cpp中的49行)
这里一定不要搞混了,这个http_callback和上边提到的pSocket->OnRead()完全不是一个东西, 可以把pSocket->OnRead()理解为宏观的所有套接字的统一接口,而http_callback才是对应的套接字(这里指这个监听fd)的具体回调函数。 接着进入http_callback 中可以知道,我们为这条新的登录连接(http连接)注册了回调函数httpconn_callback。 (这里也一定要明白,到这里我们只是接受了http的连接, 还并没有处理http消息,一定要有清晰的逻辑,所有的处理前提都是先建立tcp连接)
至此我们已经成功的接受了这条连接,并且设置了这条连接的回调函数,并将新连接的fd(http请求的连接)加入到了epoll_wait的队列中,重点:此时我们还没有处理客户端发送过来的 http://127.0.0.1:8080/msg_server, 当收到这条信息时, epoll_wait触发fd(客户端点击登录的连接),通过全局hash找到这条连接的CBaseSocket对象,调用pSocket->OnRead(), 在OnRead中可以看到,这次并不是进入的_AcceptNewSocket, 而是直接走的下边的回调函数m_callback, 此时这条连接(客户端点击登录的连接)的回调函数是httpconn_callback(在HttpConn.cpp中36行),通过fd找到对应的连接,注意这里不是CBaseSocket连接,仔细的朋友可以发现每个fd都绑定了两个对象,一个是CBaseSocket对象, 另一个是Conn对象 , 进一步调用pConn->OnRead(); ,这个OnRead和前边说的pSocket->OnRead()不是同一个, 在这个OnRead中我们可以找到 _HandleMsgServRequest(url, content); 这个函数中寻找负载最小的msg_server并将信息(ip,port)以json格式返回给客户端
至此 登录过程的第一步已经完成,我们已经成功将负载最小的msg_server信息返回给客户端了

登录第二步处理客户端登录请求(在msg_server上)

本文主要学习整体流程, 在msg_server上涉及了数据库服务器对客户端的登录信息进行验证,暂不深究。 msg_server上和Login_server一样,当有客户来连接的时候(tcp连接过程),会给这个客户fd绑定一个CBaseSocket对象,和一个Conn对象(Login_server上是CLoginConn对象,msg_server是MsgConn对象)。

当客户端发送CID_LOGIN_REQ_USERLOGIN命令,epoll_wait触发,pSocket->OnRead();

pSocket->OnRead();
m_callback(); //Login_server和msg_server都是一样的接口imconn_callback函数
//在imconn_callback中
pConn->OnRead(); //
//进入OnRead,可以看到
HandlePdu(pPdu);
//Login_server和msg_server不是同一个pConn,并且它们都重写了HandlePdu(pPdu)函数,所以有不同的实现
//在MsgConn.cpp中282行,即可看到对于CID_LOGIN_REQ_USERLOGIN命令的处理。
case CID_LOGIN_REQ_USERLOGIN:_HandleLoginRequest(pPdu );

以上就是客户端点击登录按钮, 一直到服务器处理好对应连接的全过程。

Teamtalk登录流程详解,客户端和服务器交互流程分析相关推荐

  1. 银联IC卡读卡流程详解--读卡器与卡交互指令

    最近因研究了下银联借记/贷记应用卡片规范,发现网上可参考资源较少,于是萌生了写下这篇文字的想法,希望可以帮助到有需要的兄弟姐妹,有描述不清晰或者有错误的地方欢迎指正. 下面进入正题,测试使用的卡是招商 ...

  2. lol澳洲服务器如何注册账号,云顶之弈手游澳服怎么进 LOL手游澳服账号注册流程详解[多图]...

    云顶之弈手游澳服作为国内玩家比较多的服务器,不仅可以偶遇到国内好友还可以遇到国际友人哦,那么具体服务器进入方法就让安族66来告诉大家吧~ LOL手游澳服账号注册流程详解 [云顶之弈手游已经开放注册 如 ...

  3. 《MySQL安装流程详解》及《MySQL安装一直失败,重新安装显示已安装》

    <MySQL安装流程详解>及<MySQL安装一直失败,重新安装显示已安装> 本文由博主经过查阅网上资料整理总结后编写,如存在错误或不恰当之处请留言以便更正,内容仅供大家参考学习 ...

  4. MySQL系列---架构与SQL执行流程详解

    文章目录 1. 背景 2. 架构体系 2.1 架构图 2.2 模块详解 2.3 架构分层 3. 查询SQL语句执行流程 3.1 连接 3.1.1 MySQL支持的通信协议 3.1.2 通信方式 3.2 ...

  5. 【联机对战】微信小程序联机游戏开发流程详解

    现有一个微信小程序叫中国象棋项目,棋盘类的单机游戏看着有缺少了什么,现在给补上了,加个联机对战的功能,增加了可玩性,对新手来说,实现联机游戏还是有难度的,那要怎么实现的呢,接下来给大家讲一下. 考虑到 ...

  6. 多维系统下单点登录深入详解

    多维系统下单点登录深入详解 1. 从淘宝天猫的单点登录说起 1.1 SSO单点登录 1.2 淘宝天猫登录场景解析 2. 单点登录之整体解决方案 2.1 设计方案-Cookie 2.2 设计方案-分布式 ...

  7. 负载均衡原理与实践详解 第五篇 负载均衡时数据包流程详解

    负载均衡原理与实践详解 第五篇 负载均衡时数据包流程详解 系列文章: 负载均衡详解第一篇:负载均衡的需求 负载均衡详解第二篇:服务器负载均衡的基本概念-网络基础 负载均衡详解第三篇:服务器负载均衡的基 ...

  8. 助创cms众筹 php,【教程】助创cms众筹系统完整测试流程详解

    原标题:[教程]助创cms众筹系统完整测试流程详解 这两年提到互联网金融,不得不提的一个词语:众筹.的确相比飘忽不定的股市和频发跑路P2P,众筹具备低风险,收益高,周期短等各方面的优势.为了帮助更多朋 ...

  9. 域名注册、域名实名认证、域名解析流程详解

    1.域名注册流程详解 首先登陆阿里云网站 www.aliyun.com 点击产品,选择域名注册(左下角蓝色字体) 然后来到此页面 在输入框中填入你想要注册的域名产看是否已经被注册 如:shiyansh ...

最新文章

  1. CentOS(5.8/6.4)linux生产环境若干优化实战
  2. Spring Security的内置过滤器是如何维护的?
  3. JS一起学03:js组成、下拉+text、字符串拼接、分号问题、数据类型、变量类型、作用域和闭包、命名、运算符、流程判断、调试、iNow、onchang
  4. 【客户下单】后台系统匹配分区关键字实现自动分单
  5. laravel+php+支付功能,laravel+微信支付源码
  6. 可以在循环体内声明局部变量吗?
  7. java swing 串口_ComTest 接收串口数据,并显示在文本框内,通过JavaSwing实现 Develop 265万源代码下载- www.pudn.com...
  8. C++11多线程----线程管理
  9. 上网时间监控软件_电脑监控系统软件有哪些作用?主要功能有哪些?
  10. oracle备份与恢复 exp,Oracle数据库备份与恢复之一:exp/imp(导出与导入装库与卸库)...
  11. 使用OData协议查询Windows日志
  12. ERP实施过程中的沟通管理研究
  13. php 编译 sass,如何在Symfony 3中使用纯PHP编译SASS(scss)
  14. Unity 内置渲染管线、SRP、URP、HDRP区别
  15. websockets_将WebSockets与Node.js结合使用
  16. js-函数式编程-柯里化和语义化
  17. Java多线程复习整理(二)
  18. 不会写SQL?ChatGPT 来帮你
  19. 【PyTorch】切记:GeForce RTX 3090 显卡仅支持 CUDA 11 以上的版本!
  20. C语言中“=,^=,|=”分别表示什么意

热门文章

  1. 诺曼底登陆后,联想手机如何反攻?
  2. java rhino 运行 js_Rhino -- 基于java的javascript实现
  3. 学校的计算机考试系统,南昊校园在线考试系统电脑阅卷系统
  4. 什么是JDBC,什么是JdbcTemplate
  5. AdapterView及子类
  6. Unity --- 物理引擎 ---- 刚体RigidBody 与 碰撞器 collider
  7. 【MySQL】MySQL复制原理与主备一致性同步工作原理解析(原理篇)(MySQL专栏启动)
  8. 大家小心了,骗子QQ 14258588665 买ig骗我2600
  9. 稳稳的数字化转型!华为云SAP解决方案
  10. mysql支持ASCII_MySQL ASCII()函数返回字符的ASCII码值