赞
踩
- 服务器端循环获取所有的客户端socket,放到一个
socket的list
中,等到需要通信的时候,调用相对应的管道就可以了- 客户端和服务器端一样,纪要发送消息,也要接受消息
// tcp客户端 public class Client { public static void main(String[] args) throws IOException { // 1. 创建一个Socket对象 // 参数一:服务端的ip地址 // 参数二:服务端的端口号 Socket socket = new Socket("127.0.0.1", 8888); // 创建一个独立的线程负责读取服务端发送过来的数据 ClientReaderThread clientReaderThread = new ClientReaderThread(socket); clientReaderThread.start(); // 2. 通过Socket对象获取一个输出流 OutputStream outputStream = socket.getOutputStream(); // 3. 把低级的字节输出流包装成高级的数据输出流 // 这一步不是必须得,但是高级的数据输出流可以更方便的操作数据 DataOutputStream dataOutputStream = new DataOutputStream(outputStream); Scanner scanner = new Scanner(System.in); while (true) { System.out.println("请输入要发送的数据:"); String s = scanner.nextLine(); // 4. 使用数据输出流向服务端发送数据 dataOutputStream.writeUTF(s); dataOutputStream.flush(); if (s.equals("exit")) { System.out.println("客户端退出"); // 5. 关闭资源 // dataOutputStream关闭的时候会自动关闭outputStream dataOutputStream.close(); socket.close(); Server.removeSocket(socket); break; } } } }
读取线程是子线程
public class ClientReaderThread extends Thread { private Socket socket; public ClientReaderThread(Socket socket) { this.socket = socket; } @Override public void run() { try ( // 1. 通过Socket对象获取一个输入流 InputStream inputStream = socket.getInputStream(); // 2. 将原始的字节输入流包装成高级的数据输入流 // 这一步不是必须的,但是高级的数据输入流可以更方便的操作数据 DataInputStream dataInputStream = new DataInputStream(inputStream); ) { while (true) { // 3. 读取客户端发送过来的数据 String data = dataInputStream.readUTF(); System.out.println("客户端发送过来的数据:" + data); System.out.println("客户端的ip地址:" + socket.getInetAddress().getHostAddress() + ",客户端的端口号:" + socket.getPort()); if (data.equals("exit")) { System.out.println("客户端退出"); // 4. 关闭资源 socket.close(); break; } } } catch (Exception e) { e.printStackTrace(); } } }
// tcp服务端 public class Server { // 用来存储所有的socket对象 private static ArrayList<Socket> onLineSockets = new ArrayList<Socket>(); public static void main(String[] args) throws IOException { // 1. 创建服务端对象 // 参数:服务端的端口号 ServerSocket server = new ServerSocket(8888); while(true){ // 2. 服务端一直处于监听状态,等待客户端的连接 // accept()方法是一个阻塞方法,会一直等待客户端的连接 Socket socket = server.accept(); // 将socket对象存储到集合中 onLineSockets.add(socket); // 3. 将socket独享交给独立的线程去负责 ServerReaderThread serverReaderThread = new ServerReaderThread(socket); serverReaderThread.start(); } } public static void removeSocket(Socket socket){ onLineSockets.remove(socket); } public static ArrayList<Socket> getOnLineSockets(){ return onLineSockets; } }
public class ServerReaderThread extends Thread { private Socket socket; public ServerReaderThread(Socket socket) { this.socket = socket; } @Override public void run() { try ( // 1. 通过Socket对象获取一个输入流 InputStream inputStream = socket.getInputStream(); // 2. 将原始的字节输入流包装成高级的数据输入流 // 这一步不是必须的,但是高级的数据输入流可以更方便的操作数据 DataInputStream dataInputStream = new DataInputStream(inputStream); ) { while (true) { // 3. 读取客户端发送过来的数据 String data = dataInputStream.readUTF(); // System.out.println("客户端发送过来的数据:" + data); // System.out.println("客户端的ip地址:" + socket.getInetAddress().getHostAddress() // + ",客户端的端口号:" + socket.getPort()); // 4. 将客户端发送过来的数据转发给所有的客户端 sendMsgToAllClient(data); if (data.equals("exit")) { System.out.println("客户端退出"); // 4. 关闭资源 socket.close(); break; } } } catch (Exception e) { e.printStackTrace(); } } // 异常抛出给上一级 private void sendMsgToAllClient(String data) throws Exception{ // 1. 获取所有的socket对象 for (Socket socket : Server.getOnLineSockets()) { // 2. 通过socket对象获取一个输出流 // 3. 将原始的字节输出流包装成高级的数据输出流 // 这一步不是必须的,但是高级的数据输出流可以更方便的操作数据 DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); // 4. 使用数据输出流向客户端发送数据 dataOutputStream.writeUTF(data); dataOutputStream.flush(); } } }
- 只能实现群发,无法端到端
- 也会发给自己
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。