网络连接中的长连接和短链接是什么意思?
短连接
连接->传输数据->关闭连接
比如HTTP是无状态的的短链接,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。
具体就是:浏览器client发起并建立TCP连接 -> client发送HttpRequest报文 -> server接收到报文->server handle并发送HttpResponse报文给前端,发送完毕之后立即调用socketclose方法
->client接收response报文->client最终会收到server端断开TCP连接的信号->client 端断开TCP连接,具体就是调用close方法。
也可以这样说:短连接是指SOCKET连接后,发送接收完数据后马上断开连接。
因为连接后接收了数据就断开了,所以每次数据接受处理不会有联系。 这也是HTTP协议无状态的原因之一。
长连接
连接->传输数据->保持连接 -> 传输数据-> ->直到一方关闭连接,多是客户端关闭连接。
长连接指建立SOCKET连接后不管是否使用都保持连接,但安全性较差。
HTTP在短链接和长连接上的选择:
HTTP是无状态的 ,也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。
如果客户端浏览器访问的某个HTML或其他类型的 Web页中包含有其他的Web资源,如JavaScript文件、图像文件、CSS文件等;当浏览器每遇到这样一个Web资源,就会建立一个HTTP会话
HTTP11和HTTP10相比较而言,最大的区别就是增加了持久连接支持(貌似最新的HTTP11 可以显示的指定 keep-alive),但还是无状态的,或者说是不可以信任的。
如果浏览器或者服务器在其头信息加入了这行代码 Connection:keep-alive
TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了带宽。
实现长连接要客户端和服务端都支持长连接。
什么时候用长连接,短连接?
长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况。
每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,次处理时直接发送数据包就OK了,不用建立TCP连接。
例如:数据库的连接用长连接, 如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。
像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。
总之,长连接和短连接的选择要视情况而定。
我刚刚做了个winSock与采集器的通讯和继电器板卡的通讯,皆成功注意点:IP地址,端口,协议这三样要准确,发送有二种方式:字符串,二进制串,接收也要对应的有的通讯卡,返回中包含发送的内容是正常的,也有的板卡无返回的
HTTP是无状态的
也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。如果客户端浏览器访问的某个HTML或其他类型的 Web页中包含有其他的Web资源,如JavaScript文件、图像文件、CSS文件等;当浏览器每遇到这样一个Web资源,就会建立一个HTTP会话
HTTP11和HTTP10相比较而言,最大的区别就是增加了持久连接支持(貌似最新的 http10 可以显示的指定 keep-alive),但还是无状态的,或者说是不可以信任的。
如果浏览器或者服务器在其头信息加入了这行代码
Connection:keep-alive
TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了带宽。
实现长连接要客户端和服务端都支持长连接。
所谓长连接指建立SOCKET连接后不管是否使用都保持连接,但安全性较差,
所谓短连接指建立SOCKET连接后发送后接收完数据后马上断开连接,一般银行都使用短连接
短连接:比如
http
的,只是连接、请求、关闭,过程时间较短
,
服务器若是一段时间内没有收到请求即可关
闭连接。
长连接:有些服务需要长时间连接到服务器,比如
CMPP
,一般需要自己做在线维持。
最近在看
“
服务器推送技术
”
,在
B/S
结构中,通过某种
magic
使得客户端不需要通过轮询即可以得到服务
端的最新信息(比如股票价格)
,这样可
以节省大量的带宽。
传统的轮询技术对服务器的压力很大,
并且造成带宽的极大浪费。如果改用
ajax
轮询,可以降低带宽的负荷
(因为服务器返回的不是完整页面)
,
但是对服务器
的压力并不会有明显的减少。
而推技术(
push
)可以改善这种情况。但因为
HTTP
连接
的特性(短暂,必须由客户端发起)
,使得推技术的实现比较困难,常见的做法是通过延长
http
连接的寿
命
,
来实现
push
。
接下来自然该讨论如何延长
http
连接的寿命
,
最简单的自然是死循环法
:
servlet
代
码
片
段
public
void
doGet(Request
req,
Response
res)
{
PrintWriter
out
=
resgetWriter();
……
正
常
输
出
页
面
……
通过轮询来实现长连接
轮询:隔一段时间访问服务器,服务器不管有没有新消息都立刻返回。
http长连接实现代码:
客户端:
package houleicsdnkeepalive;
import javaioIOException;
import javaioInputStream;
import javaioObjectInputStream;
import javaioObjectOutputStream;
import javanetSocket;
import javanetUnknownHostException;
import javautilconcurrentConcurrentHashMap;
/
C/S架构的客户端对象,持有该对象,可以随时向服务端发送消息。
创建时间:2011-7-18 上午12:17:25
@author HouLei
@since 10
/
public class Client {
/
处理服务端发回的对象,可实现该接口。
/
public static interface ObjectAction{
void doAction(Object obj,Client client);
}
public static final class DefaultObjectAction implements ObjectAction{
public void doAction(Object obj,Client client) {
Systemoutprintln("处理:\t"+objtoString());//诊断程序是否正常
}
}
public static void main(String[] args) throws UnknownHostException, IOException {
String serverIp = "127001";
int port = 65432;
Client client = new Client(serverIp,port);
clientstart();
}
private String serverIp;
private int port;
private Socket socket;
private boolean running=false;
private long lastSendTime;
private ConcurrentHashMap actionMapping = new ConcurrentHashMap();
public Client(String serverIp, int port) {
thisserverIp=serverIp;thisport=port;
}
public void start() throws UnknownHostException, IOException {
if(running)return;
socket = new Socket(serverIp,port);
Systemoutprintln("本地端口:"+socketgetLocalPort());
lastSendTime=SystemcurrentTimeMillis();
running=true;
new Thread(new KeepAliveWatchDog())start();
new Thread(new ReceiveWatchDog())start();
}
public void stop(){
if(running)running=false;
}
/
添加接收对象的处理对象。
@param cls 待处理的对象,其所属的类。
@param action 处理过程对象。
/
public void addActionMap(Class cls,ObjectAction action){
actionMappingput(cls, action);
}
public void sendObject(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(socketgetOutputStream());
ooswriteObject(obj);
Systemoutprintln("发送:\t"+obj);
oosflush();
}
class KeepAliveWatchDog implements Runnable{
long checkDelay = 10;
long keepAliveDelay = 2000;
public void run() {
while(running){
if(SystemcurrentTimeMillis()-lastSendTime>keepAliveDelay){
try {
ClientthissendObject(new KeepAlive());
} catch (IOException e) {
eprintStackTrace();
Clientthisstop();
}
lastSendTime = SystemcurrentTimeMillis();
}else{
try {
Threadsleep(checkDelay);
} catch (InterruptedException e) {
eprintStackTrace();
Clientthisstop();
}
}
}
}
}
class ReceiveWatchDog implements Runnable{
public void run() {
while(running){
try {
InputStream in = socketgetInputStream();
if(inavailable()>0){
ObjectInputStream ois = new ObjectInputStream(in);
Object obj = oisreadObject();
Systemoutprintln("接收:\t"+obj);//接受数据
ObjectAction oa = actionMappingget(objgetClass());
oa = oa==nullnew DefaultObjectAction():oa;
oadoAction(obj, Clientthis);
}else{
Threadsleep(10);
}
} catch (Exception e) {
eprintStackTrace();
Clientthisstop();
}
}
}
}
}
服务端:
package houleicsdnkeepalive;
import javaioIOException;
import javaioInputStream;
import javaioObjectInputStream;
import javaioObjectOutputStream;
import javanetServerSocket;
import javanetSocket;
import javautilconcurrentConcurrentHashMap;
/
C/S架构的服务端对象。
创建时间:2011-7-18 上午12:17:37
@author HouLei
@since 10
/
public class Server {
/
要处理客户端发来的对象,并返回一个对象,可实现该接口。
/
public interface ObjectAction{
Object doAction(Object rev);
}
public static final class DefaultObjectAction implements ObjectAction{
public Object doAction(Object rev) {
Systemoutprintln("处理并返回:"+rev);//确认长连接状况
return rev;
}
}
public static void main(String[] args) {
int port = 65432;
Server server = new Server(port);
serverstart();
}
private int port;
private volatile boolean running=false;
private long receiveTimeDelay=3000;
private ConcurrentHashMap actionMapping = new ConcurrentHashMap();
private Thread connWatchDog;
public Server(int port) {
thisport = port;
}
public void start(){
if(running)return;
running=true;
connWatchDog = new Thread(new ConnWatchDog());
connWatchDogstart();
}
@SuppressWarnings("deprecation")
public void stop(){
if(running)running=false;
if(connWatchDog!=null)connWatchDogstop();
}
public void addActionMap(Class cls,ObjectAction action){
actionMappingput(cls, action);
}
class ConnWatchDog implements Runnable{
public void run(){
try {
ServerSocket ss = new ServerSocket(port,5);
while(running){
Socket s = ssaccept();
new Thread(new SocketAction(s))start();
}
} catch (IOException e) {
eprintStackTrace();
Serverthisstop();
}
}
}
class SocketAction implements Runnable{
Socket s;
boolean run=true;
long lastReceiveTime = SystemcurrentTimeMillis();
public SocketAction(Socket s) {
thiss = s;
}
public void run() {
while(running && run){
if(SystemcurrentTimeMillis()-lastReceiveTime>receiveTimeDelay){
overThis();
}else{
try {
InputStream in = sgetInputStream();
if(inavailable()>0){
ObjectInputStream ois = new ObjectInputStream(in);
Object obj = oisreadObject();
lastReceiveTime = SystemcurrentTimeMillis();
Systemoutprintln("接收:\t"+obj);
ObjectAction oa = actionMappingget(objgetClass());
oa = oa==nullnew DefaultObjectAction():oa;
Object out = oadoAction(obj);
if(out!=null){
ObjectOutputStream oos = new ObjectOutputStream(sgetOutputStream());
ooswriteObject(out);
oosflush();
}
}else{
Threadsleep(10);
}
} catch (Exception e) {
eprintStackTrace();
overThis();
}
}
}
}
private void overThis() {
if(run)run=false;
if(s!=null){
try {
sclose();
} catch (IOException e) {
eprintStackTrace();
}
}
Systemoutprintln("关闭:"+sgetRemoteSocketAddress());//关闭长连接
}
}
}
长连接的维持,是要客户端程序,定时向服务端程序,发送一个维持连接包的。
如果,长时间未发送维持连接包,服务端程序将断开连接。
所谓长连接,指在一个TCP连接上可以连续发送多个数据包,在TCP连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接,一般需要自己做在线维持。
短连接是指通信双方有数据交互时,就建立一个TCP连接,数据发送完成后,则断开此TCP连接,一般银行都使用短连接。
比如http的,只是连接、请求、关闭,过程时间较短,服务器若是一段时间内没有收到请求即可关闭连接。
其实长连接是相对于通常的短连接而说的,也就是长时间保持客户端与服务端的连接状态。
长连接与短连接的操作过程:
通常的短连接操作步骤是:
连接→数据传输→关闭连接;
而长连接通常就是:
连接→数据传输→保持连接(心跳)→数据传输→保持连接(心跳)→……→关闭连接;
这就要求长连接在没有数据通信时,定时发送数据包(心跳),以维持连接状态,短连接在没有数据传输时直接关闭就行了
0条评论