美文网首页
2020-02-09-Socket全双工通信

2020-02-09-Socket全双工通信

作者: 耿望 | 来源:发表于2020-02-09 17:42 被阅读0次

参考了网上的代码,实现两台客户端通过服务器实现全双工通信。
客户端输入 connect to:+id 来选择连接到那一台机器。
同时可以通过update id: 来更改本身id。

服务端

package server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;

public class Server {
    
    private static final int DEFAULT_PORT = 54321;
    
    private ServerSocket serverSocket = null;
    private HashMap<Integer, Processer> socketMap = null;
    
    public Server() {
        try {
            serverSocket = new ServerSocket(DEFAULT_PORT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        socketMap = new HashMap<Integer, Processer>();
    }
    
    public void start() {
        try {
            while(true) {
                Socket socket = serverSocket.accept();
                int id = socket.getPort();
                String host = socket.getInetAddress().getHostAddress();
                System.out.println("connected "+ host + " " + id);
                Processer processer = new Processer(socket, id);
                processer.start();
                socketMap.put(id, processer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        
    }
    
    public static void main(String[] args) {
        new Server().start();
    }

    private void sendMessage(int id, String msg) {
        Processer processer = socketMap.get(id);
        if (processer == null) {
            return;
        }
        processer.writeMessage(msg);
    }
    
    private void setId(int oldId, int newId) {
        if (socketMap.containsKey(oldId)) {
            Processer processer = socketMap.get(oldId);
            processer.updateId(newId);
            socketMap.remove(oldId);
            socketMap.put(newId, processer);
        }
    }
    
    private class Processer extends Thread {
        
        private Socket socket = null;
        private Writer writer = null;
        private Reader reader = null;
        private int id = -1;
        
        public Processer(Socket socket, int id) {
            this.id = id;
            this.socket = socket;
            writer = new Writer();
            reader = new Reader();
        }
        
        @Override
        public void run() {
            reader.start();
            writer.start();
            try {
                reader.join();
                writer.join();
                System.out.println("Cient closed, exit.");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                if (socket != null) {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        
        private void writeMessage(String message) {
            writer.writeMessage(message);
        }
        
        private void updateId(int newId) {
            this.id = newId;
        }
    
        private class Reader extends Thread {

            private BufferedReader bufferedReader = null;
            
            public Reader() {
                try {
                    bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            
            @Override
            public void run() {
                String message = "";
                int targetId = -1;
                try {
                    while (!socket.isClosed()
                            && message != null
                            && !"exit".equals(message)) {
                        message = bufferedReader.readLine();
                        if (message == null || "".equals(message)) {
                            continue;
                        }
                        if (message.contains("connect to:")) {
                            String[] data = message.split(":");
                            targetId = Integer.parseInt(data[1]);
                        } else if (message.contains("update id:")) {
                            String[] data = message.split(":");
                            int newId = Integer.parseInt(data[1]);
                            setId(id, newId);
                        } else {
                            if (targetId > 0) {
                                sendMessage(targetId, message);
                            }
                        }
                    }
                } catch (IOException e) {
                    System.out.println("Cient closed, Reader exit.");
                } finally {
                    if (bufferedReader != null) {
                        try {
                            bufferedReader.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    
        private class Writer extends Thread {

            private PrintWriter printWriter = null;
            private volatile ArrayList<String> messageList = null;
            
            public Writer() {
                messageList = new ArrayList<String>();
                try {
                    printWriter = new PrintWriter(socket.getOutputStream());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            
            public void writeMessage(String message) {
                if (message == null || "".equals(message)) {
                    return;
                }
                synchronized (messageList) {
                    messageList.add(message);
                    messageList.notify();
                }
            }
            
            @Override
            public void run() {
                String message = "";
                while (!socket.isClosed() && message != null) {
                    synchronized (messageList) {
                        while (messageList.isEmpty()) {
                            try {
                                messageList.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                                break;
                            }
                        }
                        message = messageList.get(0);
                        messageList.remove(0);
                    }
                    if (message == null || "".equals(message)) {
                        System.out.println("Can not send empty message!");
                    } else {
                        printWriter.println(message);
                        printWriter.flush();
                        System.out.println("write " + message);
                    }
                }
                if (printWriter != null) {
                    printWriter.close();
                }
            }
        }
    }
}

客户端

package client;

import java.io.IOException;
import java.net.Socket;

public class Client {
    
    private static final int DEFAULT_PORT = 54321;
    private static final String DEFAULT_IP = "193.112.193.132";
    
    private Socket socket = null;
    private Reader reader = null;
    private Writer writer = null;
    
    public Client() {
        try {
            socket = new Socket(DEFAULT_IP, DEFAULT_PORT);
            System.out.println("connetct " + socket.getLocalPort());
            reader = new Reader(socket);
            writer = new Writer(socket);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public void start() {
        reader.start();
        writer.start();
        try {
            reader.join();
            writer.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        new Client().start();
    }
}

为了避免线程阻塞,读写分别在两个子线程实现。

Reader

package client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

public class Reader extends Thread {
    
    private Socket socket = null;
    private BufferedReader bufferedReader = null;
    
    public Reader(Socket socket) {
        this.socket = socket;
        try {
            bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    @Override
    public void run() {
        String readLine = "";
        try {
            while (!socket.isClosed()
                    && readLine != null
                    && !"exit".equals(readLine)) {
                readLine = bufferedReader.readLine();
                System.out.println(readLine);
            }
            System.out.println("Server closed, Reader exit.");
        } catch (IOException e) {
            System.out.println("Server closed, Reader exit.");
        } finally {
            try {
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Writer

package client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class Writer extends Thread {
    
    private Socket socket = null;
    private PrintWriter printWriter = null;
    private BufferedReader bufferedReader = null;
    
    public Writer(Socket socket) {
        super("ClientWriterThread");
        this.socket = socket;
        bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        try {
            printWriter = new PrintWriter(socket.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    @Override
    public void run() {
        String readLine = "";
        try {
            while (!socket.isClosed()
                    && readLine != null
                    && !"exit".equals(readLine)) {
                readLine = bufferedReader.readLine();
                if ("".equals(readLine)) {
                    System.out.println("Can not send empty message!");
                } else {
                    printWriter.println(readLine);
                    printWriter.flush();
                }
            }
            System.out.println("Client closed, Writer exit.");
        } catch (IOException e) {
            System.out.println("Server closed, Writer exit.");
        } finally {
            try {
                if (printWriter != null) {
                    printWriter.close();
                }
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

相关文章

  • 2020-02-09-Socket全双工通信

    参考了网上的代码,实现两台客户端通过服务器实现全双工通信。客户端输入 connect to:+id 来选择连接到...

  • OKHttp之WebSocket的使用

    WebSocket协议是一种建立在TCP连接基础上的全双工通信的协议。应用于即时通信等场景。 全双工通信:客户端和...

  • 全双工通信的 WebSocket

    全双工通信与半双工通信的区别 半双工:参考对讲机,A:能不能听到我说话,over B:可以可以,over 全双工:...

  • 【译】fdwifi

    fdwifi模块 无线全双工通信模块RFD(中继全双工)- MAC的实施 扩展WiFi模块 支持范围IEEE 80...

  • 全双工通信的 WebSocket

    GitHub Repo:Halfrost-FieldFollow: halfrost · GitHubSource...

  • WebSock--全双工通信

    介绍: WebSocket是HTML5开始提供的一种浏览器与服务器之间进行全双工通信的网路技术。在WebSocke...

  • 浏览器多个标签页之间的通信

    一:websocket通讯 全双工(full-duplex)通信自然可以实现多个标签页之间的通信 WebSocke...

  • Spring Boot 整合单机websocket(附githu

    websocket 概念 websocket 是一个通信协议,通过单个 TCP 连接提供全双工通信。websock...

  • Websocket协议

    WebSocket是一种在单个TCP传输控制协议连接上进行全双工全双工通信的协议。WebSocket使得客户端和服...

  • 使用Websocket

    WebSocket是一种在单个TCP传输控制协议连接上进行全双工全双工通信的协议。WebSocket使得客户端和服...

网友评论

      本文标题:2020-02-09-Socket全双工通信

      本文链接:https://www.haomeiwen.com/subject/nydnxhtx.html