上周研究了一下服务器主动推送这个东东是怎么搞的(网上吹得那么牛B,然后又省流量什么的,参考了一下IPHONE的QQ离线推送)看了一下原来只是一个长连接过程。特意写个文章跟大家分享一下!
我们平时的应用开发当中,一般用的是短连接:1.client 连接Server---->2.client端向Server端拿数据---->3.拿完数据马上断开连接。
服务器主动推送用的是长连接:1.client连接Server---->2.client跟Server一直处理对话的状态,直至对话状态被关闭(这个过程当中,client 跟Server可以随意对话,他们的关系处于平等状态)---->3.断开连接
就好比两个人之间的对话,如果对话之前已经搭好了对话的线路,那么这两个人都可以占了主动,Server也就可以向client主动说话了;如果对话之前没有搭好线路的情况下,就只能够是每次都是client这个人先跟Server搭好线路,然后才可以对话。所以这就造成了我们会觉得Server不能主动向client发数据这种感觉。
我们从tcp的连接过程来看:
TCP的连接先要经过3次握手,握手成功了之后,再进行数据的通信交流,三次握手过程大大致如下所示:
(1)客户端发送一个带SYN标志的TCP报文到服务器。这是三次握手过程中的报文1。
(2) 服务器端回应客户端的,这是三次握手中的第2个报文,这个报文同时带ACK标志和SYN标志。因此它表示对刚才客户端SYN报文的回应;同时又标志SYN给客户端,询问客户端是否准备好进行数据通讯,这是报文2。
(3) 客户必须再次回应服务段一个ACK报文,这是报文段3。
以上是三次握手的过程,是多么的麻烦!
如果采用长连接的方式的话,Server跟client之间的很多次对话,只需一次的Socket连接就可以了;对比短连接的话,Server跟client之间的多次对话,要进行多次的socket连接!从这个角度看,长连接的方式的确省了很多次tcp这一层的三次握手(也省了这个握手过程的数据流量)。
但是,如果client跟Server长时间处于连接状态的话,Server就一直无法释放这个连接的子进程了,如果client数目少的话还可以,如果client的数目太多,Server就一直跑许多个连接的子进程了,所以我们平时对于数据的实时性要求不高的情况下,一般不会用长连接,而采用可以减轻Server负担的短连接。
附上Socket连接伪代码:
TCP并发服务器:并发服务器的思想是每一个客户端的请求并不由服务器的主进程直接处理,而是服务器主进程创建一个子进程来处理。
创建TCP并发服务器的算法如下:
socket(……); //创建一个TCP套接字
bind(……); //邦定公认的端口号
listen(……);//倾听客户端连接
while(1) //开始循环接收客户端的接收
{
accept(……);//接收一个客户端的连接
if(fork(……)==0) //创建子进程
{
while(1)
{ //子进程处理某个客户端的连接
read(……);
process(……);
write(……);
}
close(……); //关闭子进程处理的客户端连接
exit(……) ;//终止该子进程
}
close(……); //父进程关闭连接套接字描述符,准备接收下一个客户端连接
}
后记:
之前跟同事还在怀疑,是不是通过这样一种方式去实现服务器主动推送的方法:client端在监听服务器的消息,相当于把client跟Server的角色转换了一样(通过某种很厉害的技术,把client伪装成一个像服务器的东东)。
测试:
在android的平台上边分别试了一下微信跟QQ,发现QQ是可以离线收信息,微信不可以。QQ的离线消息是通过在后台开启了另外一个服务(这个服务跟QQ的服务器建立了长连接,一直在跟腾迅的Server 连通了,所以及Server那边可以实时地发一些推送的消息过来client这端),所以即使关闭了QQ这个进程,那个服务还可以一直在监听Server传过来的消息。
iphone不能查看系统的所有进程,但的估计也是这样。另外附上iphone消息推送的原理图!!!!!!!!!!!!!!!不知道博客园怎么插入图片!!一次补回来
1、首先是应用程序注册消息推送。
2、 IOS跟APNS Server要deviceToken。应用程序接受deviceToken。
3、应用程序将deviceToken发送给PUSH服务端程序。
4、 服务端程序向APNS服务发送消息。
5、APNS服务将消息发送给iPhone应用程序。