Java simulates long connection sending

1. Client

package com.msb.netty.testPageLongKeepAlive;


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;

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();  //保持长连接的线程,每隔2秒项服务器发一个一个保持连接的心跳消息
        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 = 1000;

        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();
                }
            }
        }
    }

}

2. Server

package com.msb.netty.testPageLongKeepAlive;


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;

public class Server {
    
    

    /**
     * 要处理客户端发来的对象,并返回一个对象,可实现该接口。
     */
    public interface ObjectAction {
    
    
        Object doAction(Object rev, Server server);
    }

    public static final class DefaultObjectAction implements ObjectAction {
    
    
        public Object doAction(Object rev, Server server) {
    
    
            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, Server.this);
                            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());
        }

    }

}

3. Maintain the heartbeat of the message

package com.msb.netty.testPageLongKeepAlive;


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维持连接包";
    }

}

Guess you like

Origin blog.csdn.net/weixin_47068446/article/details/130069639