`
coach
  • 浏览: 386965 次
  • 性别: Icon_minigender_2
  • 来自: 印度
社区版块
存档分类
最新评论

基于心跳的socket长连接

    博客分类:
  • http
阅读更多
案例:
心跳:
socket模拟网页的报文连接某个网站,创建tcp的socket后,当我socket.connect后,如果在5到7秒钟不socket.send,那么这个链接就失效了。 请问如何长时间的保持这个链接
这是在服务器端的设置的,客户端没法设置,可以发送心跳包。
socket.connect后,每3-4秒用socket.send发送一字节数据(内容随便),然后观查这个连接是否保持。

lientSocket=serverSocket.accept();
OutputStream os = clientSocket.getOutputStream();          
ObjectOutputStream oos=new ObjectOutputStream(os);
oos.writeObject(al);
oos.flush();
oos.close()//socket会关闭

实现:
长连接的维持,是要客户端程序,定时向服务端程序,发送一个维持连接包的。
如果,长时间未发送维持连接包,服务端程序将断开连接。

客户端:
通过持有Client对象,可以随时(使用sendObject方法)发送Object给服务端。
如果keepAliveDelay毫秒(程序中是2秒)内未发送任何数据,则,自动发送一个KeepAlive对象给服务端,
用于维持连接。
由于,我们向服务端,可以发送很多不同的对象,服务端也可以返回不同的对象。
所以,对于返回对象的处理,要编写具体的ObjectAction实现类进行处理。
通过Client.addActionMap方法进行添加。这样,程序会回调处理。

服务端:
由于客户端会定时(keepAliveDelay毫秒)发送维持连接的信息过来,所以,服务端要有一个检测机制。
即当服务端receiveTimeDelay毫秒(程序中是3秒)内未接收任何数据,则,自动断开与客户端的连接。
ActionMapping的原理与客户端相似(相同)。
通过添加相应的ObjectAction实现类,可以实现不同对象的响应、应答过程。


package houlei.csdn.keepalive;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 维持连接的消息对象。
 */
public class KeepAlive implements Serializable{

	private static final long serialVersionUID = -2813120366138988480L;

	/* 覆盖该方法,仅用于测试使用。
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"\t维持连接包";
	}

}


client:
package houlei.csdn.keepalive;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.ConcurrentHashMap;

/**
 *	C/S架构的客户端对象,持有该对象,可以随时向服务端发送消息。
 */
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) {
			System.out.println("处理:\t"+obj.toString());
		}
	}
	public static void main(String[] args) throws UnknownHostException, IOException {
		String serverIp = "127.0.0.1";
		int port = 65432;
		Client client = new Client(serverIp,port);
		client.start();
	}
	
	private String serverIp;
	private int port;
	private Socket socket;
	private boolean running=false;
	private long lastSendTime;
	private ConcurrentHashMap<Class, ObjectAction> actionMapping = new ConcurrentHashMap<Class,ObjectAction>();
	
	public Client(String serverIp, int port) {
		this.serverIp=serverIp;this.port=port;
	}
	
	public void start() throws UnknownHostException, IOException {
		if(running)return;
		socket = new Socket(serverIp,port);
		System.out.println("本地端口:"+socket.getLocalPort());
		lastSendTime=System.currentTimeMillis();
		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<Object> cls,ObjectAction action){
		actionMapping.put(cls, action);
	}

	public void sendObject(Object obj) throws IOException {
		ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
		oos.writeObject(obj);
		System.out.println("发送:\t"+obj);
		oos.flush();
	}
	
	class KeepAliveWatchDog implements Runnable{
		long checkDelay = 10;
		long keepAliveDelay = 2000;
		public void run() {
			while(running){
				if(System.currentTimeMillis()-lastSendTime>keepAliveDelay){
					try {
						Client.this.sendObject(new KeepAlive());
					} catch (IOException e) {
						e.printStackTrace();
						Client.this.stop();
					}
					lastSendTime = System.currentTimeMillis();
				}else{
					try {
						Thread.sleep(checkDelay);
					} catch (InterruptedException e) {
						e.printStackTrace();
						Client.this.stop();
					}
				}
			}
		}
	}
	
	class ReceiveWatchDog implements Runnable{
		public void run() {
			while(running){
				try {
					InputStream in = socket.getInputStream();
					if(in.available()>0){
						ObjectInputStream ois = new ObjectInputStream(in);
						Object obj = ois.readObject();
						System.out.println("接收:\t"+obj);
						ObjectAction oa = actionMapping.get(obj.getClass());
						oa = oa==null?new DefaultObjectAction():oa;
						oa.doAction(obj, Client.this);
					}else{
						Thread.sleep(10);
					}
				} catch (Exception e) {
					e.printStackTrace();
					Client.this.stop();
				} 
			}
		}
	}
	
}


server:
package houlei.csdn.keepalive;


import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ConcurrentHashMap;

/**
 * C/S架构的服务端对象。
 */
public class Server {

	/**
	 * 要处理客户端发来的对象,并返回一个对象,可实现该接口。
	 */
	public interface ObjectAction{
		Object doAction(Object rev);
	}
	
	public static final class DefaultObjectAction implements ObjectAction{
		public Object doAction(Object rev) {
			System.out.println("处理并返回:"+rev);
			return rev;
		}
	}
	
	public static void main(String[] args) {
		int port = 65432;
		Server server = new Server(port);
		server.start();
	}
	
	private int port;
	private volatile boolean running=false;
	private long receiveTimeDelay=3000;
	private ConcurrentHashMap<Class, ObjectAction> actionMapping = new ConcurrentHashMap<Class,ObjectAction>();
	private Thread connWatchDog;
	
	public Server(int port) {
		this.port = port;
	}

	public void start(){
		if(running)return;
		running=true;
		connWatchDog = new Thread(new ConnWatchDog());
		connWatchDog.start();
	}
	
	@SuppressWarnings("deprecation")
	public void stop(){
		if(running)running=false;
		if(connWatchDog!=null)connWatchDog.stop();
	}
	
	public void addActionMap(Class<Object> cls,ObjectAction action){
		actionMapping.put(cls, action);
	}
	
	class ConnWatchDog implements Runnable{
		public void run(){
			try {
				ServerSocket ss = new ServerSocket(port,5);
				while(running){
					Socket s = ss.accept();
					new Thread(new SocketAction(s)).start();
				}
			} catch (IOException e) {
				e.printStackTrace();
				Server.this.stop();
			}
			
		}
	}
	
	class SocketAction implements Runnable{
		Socket s;
		boolean run=true;
		long lastReceiveTime = System.currentTimeMillis();
		public SocketAction(Socket s) {
			this.s = s;
		}
		public void run() {
			while(running && run){
				if(System.currentTimeMillis()-lastReceiveTime>receiveTimeDelay){
					overThis();
				}else{
					try {
						InputStream in = s.getInputStream();
						if(in.available()>0){
							ObjectInputStream ois = new ObjectInputStream(in);
							Object obj = ois.readObject();
							lastReceiveTime = System.currentTimeMillis();
							System.out.println("接收:\t"+obj);
							ObjectAction oa = actionMapping.get(obj.getClass());
							oa = oa==null?new DefaultObjectAction():oa;
							Object out = oa.doAction(obj);
							if(out!=null){
								ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
								oos.writeObject(out);
								oos.flush();
							}
						}else{
							Thread.sleep(10);
						}
					} catch (Exception e) {
						e.printStackTrace();
						overThis();
					} 
				}
			}
		}
		
		private void overThis() {
			if(run)run=false;
			if(s!=null){
				try {
					s.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			System.out.println("关闭:"+s.getRemoteSocketAddress());
		}
		
	}
	
}
分享到:
评论

相关推荐

    Socket长连接+心跳包+发送读取

    以下是Socket长连接、心跳包和数据发送读取的关键知识点: 1. **TCP连接**:Socket基于传输层的TCP协议,提供可靠的双向通信。TCP保证了数据的顺序和完整性,通过三次握手建立连接,四次挥手断开连接。 2. **...

    进程间负载,基于socket长连接

    基于socket的长连接是指两个进程之间建立一次连接后,长时间保持连接状态,而非每次交互都创建新的连接。这样可以减少连接建立和释放的开销,提高整体性能。 在IPLB中使用基于socket的长连接,通常涉及以下关键知识...

    c# Socket长连接 短链接 自己封装 通讯

    总结来说,这个主题涵盖了C#中基于Socket的网络编程,特别是长连接和短连接的实现,以及如何设计和使用自定义的通信协议。这样的知识对于构建高性能、可靠且可扩展的网络应用至关重要。开发者需要理解TCP/IP协议、...

    TCP长连接Socket心跳收发消息

    本篇文章将深入探讨TCP长连接Socket以及心跳收发消息的原理和实现方法。 首先,TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。它通过三次握手建立连接,并在连接建立后可以进行双向数据传输。TCP连接...

    java socket 长连接实例

    "Java Socket 长连接实例"是关于如何实现一个持久连接的服务器和客户端程序的示例,这种连接能够保持开放,直到一方明确地关闭它。这在需要频繁通信或者需要长时间保持连接状态的应用场景中非常有用,比如聊天应用、...

    Android-MinaSocket一款基于Mina的Socket长连接库

    **Android-MinaSocket:基于Mina的高效Socket长连接库** 在移动应用开发中,尤其是Android平台,实时性与稳定性是许多应用场景的核心需求,比如在线游戏、即时通讯、物联网设备等。在这种背景下,使用Socket进行长...

    socket 长连接实例

    - **关闭连接**:通信完成后,使用`close()`函数关闭Socket连接。 3. **长连接的维护**: - 在长连接中,服务器和客户端不会在每次数据交换后立即关闭连接,而是会维持一段时间的空闲状态,等待下一次数据传输。 ...

    基于SuperSocket的消息推送详细说明文档1

    - 服务端初始化,监听Socket连接。 - 客户端发起连接请求。 - 服务端接受连接,创建会话。 - 客户端发送数据,确认连接。 - 服务端发送心跳包,保持连接。 - 客户端接收心跳包,维持长连接。 - 客户端关闭...

    swift-iOS基于NSStream实现的Socket长连接小封装

    - 开启/关闭连接:启动和停止Socket连接。 - 发送数据:提供一个接口用于向服务器发送数据。 - 监听数据:实现内部的数据接收和处理逻辑。 - 错误处理:捕获并处理可能出现的网络错误。 在实现过程中,为了保持连接...

    netty基于http socket websocke及心跳包机制t的demo

    4. 如何处理Socket连接,发送和接收自定义协议的数据。 5. 示例代码展示如何在Java中编写和运行Netty应用。 这个demo将是一个很好的学习资源,帮助开发者理解Netty框架在实际应用中的工作原理,以及如何结合HTTP、...

    socket客户端长连接实现以及xml文件解析

    在IT领域,Socket编程是网络通信的基础,而XML(Extensible Markup Language)则是...在xfunds-socket-price这个项目中,可能涉及到通过Socket连接获取价格数据,这些数据以XML格式传输,然后在客户端进行解析和处理。

    socket心跳功能

    1. 创建Socket连接:使用`Socket`类创建到服务器的连接,通常还会伴随着`ServerSocket`类在服务端接收连接。 2. 设计心跳包:心跳包可以是自定义的字符串或特定结构的数据,如JSON格式的简单对象,包含心跳类型、...

    基于C#Socket网络连接协议操作类

    这是一个C#写的Socket网络通信连接的操作类,支持心跳和重连机制,只需知道服务器的IP和端口就能连接上服务器并实时接收数据,接收到的数据为Byte[]类型的数组,二进制协议数据.

    TCP/IPsocket长连接

    8. **安全性**:为了保护用户数据的安全,可能需要在传输层使用SSL/TLS加密,实现安全的Socket连接,防止数据被窃取。 9. **权限管理**:在安卓系统中,进行网络通信需要在Manifest文件中声明`...

    一个Socket连接管理器(心跳机制)

    以上就是关于"一个Socket连接管理器(心跳机制)"的相关知识点,涵盖了Socket的基本概念、TCP连接原理、心跳包的设计与实现、异常处理、线程管理以及性能优化等多个方面。理解并掌握这些知识点,对于构建稳定、高效的...

    基于Socket的网络通信设计

    本主题将深入探讨如何利用Socket编程实现基于TCP/IP协议的网络通信,涵盖从建立连接、监听请求到发送和接收数据的全过程。 1. **网络协议基础** - TCP/IP协议族:Transmission Control Protocol/Internet Protocol...

    socket客户端,可连接多个服务器

    TCP Socket连接的建立遵循三次握手的过程,客户端首先发起连接请求(SYN),服务器响应确认并发送自己的SYN(SYN+ACK),客户端再回应服务器的确认(ACK)。当这三步交互完成,连接便建立成功。而断线后的重连机制,...

    基于HPSocket实现 socket 通讯 - 修正版 ( C# demo 、 C++ dll )

    通过HPSocket,开发者可以设置心跳检测,当检测到连接中断时,客户端能自动尝试重新连接到服务器,确保服务的连续性。 4. **消息收发**: 在HPSocket中,发送和接收消息是通过调用特定的API完成的。发送消息通常...

    毕设&课设&项目&实训-基于SuperSocket实现客户端与客户端的消息推送以及服务端与客户端互发心跳数据包维持长连接.zip

    毕设&课设&项目&实训-基于SuperSocket实现客户端与客户端的消息推送以及服务端与客户端互发心跳数据包维持长连接、离线消息存储并转发 【项目资源】: 包含前端、后端、移动开发、操作系统、人工智能、物联网、信息...

    Android-一个基于okio的简化Socket操作的android框架实现Socket断线自动连接

    9. **测试与调试**:对于Socket连接的稳定性,开发者需要进行充分的测试,包括网络良好的情况以及模拟断网、服务器宕机等异常情况,确保断线重连功能的可靠性和健壮性。 通过OkioSocketDemo项目,开发者可以学习到...

Global site tag (gtag.js) - Google Analytics