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

提示:要学习客户端和服务器如何交互, 就是去找它们通信协议中对应命令发送过程。 对于登录过程,对应登录命令就是去分析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(		//去看它的实现, 调用了_DoLogin
			BIND_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 148IMLibCoreConnect(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 );

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
teamtalk安卓源码是一款开源的即时通讯应用程序的源代码。它基于C++和Java开发,具有跨平台的特性,可以在安卓设备上使用。通过对teamtalk安卓源码的剖析,我们可以深入了解其工作原理和实现细节。 首先,在剖析过程中,我们会看到teamtalk安卓源码的整体架构。它主要由客户服务器两部分组成。客户负责用户界面和交互逻辑的展示,服务器负责数据存储和通信管理。双方通过TCP/IP协议进行通信。 其次,我们会发现teamtalk安卓源码具有丰富的功能。用户可以注册账号、登录、添加好友、发送文字和语音消息、创建群组等。它支持即时消息的收发、离线消息的存储和推送,还提供了消息撤回和删除的功能。此外,它还支持实时语音和视频通话,可以进行多人会议。 在剖析过程中,我们还会了解其核心技术点。比如,teamtalk安卓源码使用了SQLite数据库进行数据存储,使用了音视频编解码技术来保证语音和视频通话的质量。另外,它采用了高效的网络通信协议和算法,保证了数据的安全性和实时性。 此外,我们也会注意到teamtalk安卓源码的可扩展性和开放性。它提供了丰富的接口和插件机制,允许开发者进行二次开发和定制。开发者可以根据自己的需求,添加新的功能和扩展。 总的来说,通过对teamtalk安卓源码的剖析,我们可以了解到它是一款功能强大、可扩展的即时通讯应用程序。它不仅具有各种基本的通信功能,还提供了高质量的语音和视频通话能力。对于开发者来说,通过深入研究其源码,可以获取到宝贵的经验和技术知识。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值