zlingh

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

TCP/IP 
TCP/IP是个协议组,可分为三个层次:网络层、传输层和应用层。 
在网络层有IP协议、ICMP协议、ARP协议、RARP协议和BOOTP协议。 
在传输层中有TCP协议与UDP协议。 
在应用层有:TCP包括FTP、HTTP、TELNET、SMTP等协议 
                 UDP包括DNS、TFTP等协议 
短连接 
连接->传输数据->关闭连接 
HTTP是无状态的,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。 
也可以这样说:短连接是指SOCKET连接后发送后接收完数据后马上断开连接。 
  
长连接 
连接->传输数据->保持连接 -> 传输数据-> 。。。 ->关闭连接。 
长连接指建立SOCKET连接后不管是否使用都保持连接,但安全性较差。 
  
http的长连接 
HTTP也可以建立长连接的,使用Connection:keep-alive,HTTP 1.1默认进行持久连接。HTTP1.1和HTTP1.0相比较而言,最大的区别就是增加了持久连接支持(貌似最新的 http1.0 可以显示的指定 keep-alive),但还是无状态的,或者说是不可以信任的。 
  
什么时候用长连接,短连接? 
 长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况,。每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,次处理时直接发送数据包就OK了,不用建立TCP连接。例如:数据库的连接用长连接, 如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。 
  
而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。 
  
总之,长连接和短连接的选择要视情况而定。 
发送接收方式 
1、异步 
报文发送和接收是分开的,相互独立的,互不影响。这种方式又分两种情况: 
(1)异步双工:接收和发送在同一个程序中,由两个不同的子进程分别负责发送和接收 
(2)异步单工:接收和发送是用两个不同的程序来完成。 
2、同步 
报文发送和接收是同步进行,既报文发送后等待接收返回报文。 同步方式一般需要考虑超时问题,即报文发出去后不能无限等待,需要设定超时时间,超过该时间发送方不再等待读返回报文,直接通知超时返回。 
  
在长连接中一般是没有条件能够判断读写什么时候结束,所以必须要加长度报文头。读函数先是读取报文头的长度,再根据这个长度去读相应长度的报文。 

Socket是什么 

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
\

通信过程:
\

主机 A 的应用程序要能和主机 B 的应用程序通信,必须通过 Socket 建立连接,而建立 Socket 连接必须需要底层 TCP/IP 协议来建立 TCP 连接。建立 TCP 连接需要底层 IP 协议来寻址网络中的主机。我们知道网络层使用的 IP 协议可以帮助我们根据 IP 地址来找到目标主机,但是一台主机上可能运行着多个应用程序,如何才能与指定的应用程序通信就要通过 TCP 或 UPD 的地址也就是端口号来指定。这样就可以通过一个 Socket 实例唯一代表一个主机上的一个应用程序的通信链路了。

建立通信链路
当客户端要与服务端通信,客户端首先要创建一个 Socket 实例,操作系统将为这个 Socket 实例分配一个没有被使用的本地端口号,并创建一个包含本地和远程地址和端口号的套接字数据结构,这个数据结构将一直保存在系统中直到这个连接关闭。在创建 Socket 实例的构造函数正确返回之前,将要进行 TCP 的三次握手协议,TCP 握手协议完成后,Socket 实例对象将创建完成,否则将抛出 IOException 错误。
与之对应的服务端将创建一个 ServerSocket 实例,ServerSocket 创建比较简单只要指定的端口号没有被占用,一般实例创建都会成功,同时操作系统也会为 ServerSocket 实例创建一个底层数据结构,这个数据结构中包含指定监听的端口号和包含监听地址的通配符,通常情况下都是“*”即监听所有地址。之后当调用 accept() 方法时,将进入阻塞状态,等待客户端的请求。当一个新的请求到来时,将为这个连接创建一个新的套接字数据结构,该套接字数据的信息包含的地址和端口信息正是请求源地址和端口。这个新创建的数据结构将会关联到 ServerSocket 实例的一个未完成的连接数据结构列表中,注意这时服务端与之对应的 Socket 实例并没有完成创建,而要等到与客户端的三次握手完成后,这个服务端的 Socket 实例才会返回,并将这个 Socket 实例对应的数据结构从未完成列表中移到已完成列表中。所以 ServerSocket 所关联的列表中每个数据结构,都代表与一个客户端的建立的 TCP 连接。

 

 

 

php长连接和短连接

长连接到底有什么用?我想你应该见过很多在线聊天工具吧,比如新浪的Woocall,另外还有很多网页在线聊天的工具。Omegle也是一个很不错的网站,前段时间挺火的,目前alexa全球排名8694(2009-8-18数据),另外使用校内的人应该会熟悉其中一个功能,如果有人回复你了,网站会马上出现提示,此时你并没有刷新页面;Gmail也有此功能,如果邮箱里收到了新的邮件,网站会马上提醒你,即使你的网页一直未刷新过。

这么多类似的功能都离不开长连接,短连接一般都是单项请求数据,服务器不能主动把数据“推”想客户端,但有了长连接就好多了,利用后端与前端的技术组合起来,可以实现服务器的“推送信息”功能,如果数据库里面有更新,后端程序可以立即把数据“推送出来”,而不要多次反复请求,多次建立连接,多次断开。

每次我们访问PHP脚本的时候,都是当所有的PHP脚本执行完成后,我们才得到返回结果。如果我们需要一个脚本持续的运行,那么我们就要通过php长连接的方式,来达到运行目的。

一般php环境为apache+php+linux,但是由于apache对php连接都有时间限制,一般超过这个连接时间apache服务器会自动断掉连接。

方法一

这种情况下比较简单方便的方式就是在php页面中设置set_time_limit(0)(当然也可以在php.ini配置文件中设置,但是这样对整个环境产生影响,毕竟我们并不想对所有连接都可以长时间连接,影响服务性能)

每个PHP脚本都限制了执行时间,所以我们需要通过 set_time_limit 来设置一个脚本的执行时间为无限长,然后使用 flush() 和 ob_flush() 来清除服务器缓冲区,随时输出脚本的返回值。

如下例子:

view

plain

<?php

header("Content-Type: text/plain");

set_time_limit(0);

while( true )

{

// 持续执行的脚本

flush();

ob_flush();

sleep(5);

}

?>

当我们执行后,每隔5秒钟,我们会执行一次,通过这一方法,我们可以完成很多功能,例如后台监控程序,定时执行功能,日志分析,数据整理等耗时的操作。

下面再看一个简单例子,官方文档中例子

view

plain

<?php

header('Content-type: text/plain');

echo date("H:m:s"), "/n";

set_time_limit(30);

for ($i = 0; $i < 1000; $i++)

{

echo date("H:m:s"),"/n";

for ($r = 0; $r < 100000; $r++){

$X.= tan(M_LNPI+log(ceil( date("s")*M_PI*M_LNPI+100)));

}

ob_flush();

flush();

}

echo "work! $x";

?>

方法二

在linux环境下,通过cron配置执行脚本,就是通过linux下php命令执行php文件,这种方式是在php单独环境下执行,不受apache环境限制,可以执行长时间运行的程序 (同样还有j2ee中,jsp长时间执行就会出现断开连接情况,当然通过servlet可以后台一直执行,但是毕竟需要配置web.xml还需要重启环境,不是很方便,这是就可以单独执行java程序,让后通过cron配置linux后台定时执行)

例如:

10 5 * * * /usr/bin/php /usr/local/run/back_run.php

每天5点10分执行back_run.php脚本程序,这时可以执行任意长时间,执行完后进程自动销毁,执行的时候,可以通过ps -ef|grep back_run.php找到执行中的进程。

该方式可以实现很多php批处理功能。

通常短连接是这样:连接->传输数据->关闭连接

那什么时候用短连接呢?

一般长连接用于少数client-end to server-end的频繁的通信,例如:数据库的连接用长连接, 如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。

而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源。(查看来源)

那什么是长连接?一般长连接相对短连接而言的,长连接在传输完数后不关闭连接,而不断的发送包保持连接等待处理下一个数据包。

such as: 连接->传输数据->保持连接 -> 传输数据-> 。。。 ->关闭连接。

Socket协议的形象描述

socket的英文原义是“孔”或“插座”。在这里作为4BDS UNIX的进程通信机制,取后一种意思。socket非常类似于电话插座。以一个国家级电话网为例。电话的通话双方相当于相互通信的2个进程,区号是它的网络地址;区内一个单位的交换机相当于一台主机,主机分配给每个用户的局内号码相当于socket号。任何用户在通话之前,首先要占有一部电话机,相当于申请一个socket;同时要知道对方的号码,相当于对方有一个固定的socket。然后向对方拨号呼叫,相当于发出连接请求(假如对方不在同一区内,还要拨对方区号,相当于给出网络地址)。对方假如在场并空闲(相当于通信的另一主机开机且可以接受连接请求),拿起电话话筒,双方就可以正式通话,相当于连接成功。双方通话的过程,是一方向电话机发出信号和对方从电话机接收信号的过程,相当于向socket发送数据和从socket接收数据。通话结束后,一方挂起电话机相当于关闭socket,撤消连接。

TCP/IP通信解读长短链接

一。通信方式

主要有以下三大类:

(一)SERVER/CLIENT方式

1.一个Client方连接一个Server方,或称点对点(peer to peer):

2.多个Client方连接一个Server方,这也是通常的并发服务器方式。

3.一个Client方连接多个Server方,这种方式很少见,主要

用于一个客户向多个服务器发送请求情况。

(二)连接方式

1.长连接

Client方与Server方先建立通讯连接,连接建立后不断开,

然后再进行报文发送和接收。这种方式下由于通讯连接一直

存在,可以用下面命令查看连接是否建立:

netstat –f inet|grep 端口号(如5678)。

此种方式常用于点对点通讯。

2.短连接

Client方与Server每进行一次报文收发交易时才进行通讯连

接,交易完毕后立即断开连接。此种方式常用于一点对多点

通讯,比如多个Client连接一个Server.

(三)发送接收方式

1.异步

报文发送和接收是分开的,相互独立的,互不影响。这种方

式又分两种情况:

(1)异步双工:接收和发送在同一个程序中,有两个不同的

子进程分别负责发送和接收

(2)异步单工:接收和发送是用两个不同的程序来完成。

2.同步

报文发送和接收是同步进行,既报文发送后等待接收返回报文。

同步方式一般需要考虑超时问题,即报文发上去后不能无限等

待,需要设定超时时间,超过该时间发送方不再等待读返回报

文,直接通知超时返回。

实际通信方式是这三类通信方式的组合。比如一般书上提供的

TCP/IP范例程序大都是同步短连接的SERVER/CLIENT程序。有的

组合是基本不用的,比较常用的有价值的组合是以下几种:

同步短连接Server/Client

同步长连接Server/Client

异步短连接Server/Client

异步长连接双工Server/Client

异步长连接单工Server/Client

其中异步长连接双工是最为复杂的一种通信方式,有时候经

常会出现在不同银行或不同城市之间的两套系统之间的通信。

比如金卡工程。由于这几种通信方式比较固定,所以可以预

先编制这几种通信方式的模板程序。

二.报文格式

通信报文格式多样性更多,相应地就必须设计对应的读写报文的接

收和发送报文函数。

(一)阻塞与非阻塞方式

1.非阻塞方式

读函数不停地进行读动作,如果没有报文接收到,等待一段时间后

超时返回,这种情况一般需要指定超时时间。

2.阻塞方式

如果没有报文接收到,则读函数一直处于等待状态,直到有报文到达。

(二)循环读写方式

1.一次直接读写报文

在一次接收或发送报文动作中一次性不加分别地全部读取或全部

发送报文字节。

2.不指定长度循环读写

这一般发生在短连接进程中,受网络路由等限制,一次较长的报

文可能在网络传输过程中被分解成了好几个包。一次读取可能不

能全部读完一次报文,这就需要循环读报文,直到读完为止。

3.带长度报文头循环读写

这种情况一般是在长连接进程中,由于在长连接中没有条件能够

判断循环读写什么时候结束,所以必须要加长度报文头。读函数

先是读取报文头的长度,再根据这个长度去读报文.实际情况中,

报头的码制格式还经常不一样,如果是非ASCII码的报文头,还必须

转换成ASCII,常见的报文头码制有:

(1)n个字节的ASCII码

(2)n个字节的BCD码

(3)n个字节的网络整型码


 

posted on 2014-09-25 15:35  zlingh  阅读(889)  评论(0编辑  收藏  举报