目录

  • 使用多线程实现异步通信的基本步骤如下:
  • 使用NIO实现异步通信的基本步骤如下:
  • 下面是使用Java语言通过SocketServer异步通信的例子,其中一边可以查询信息并发送指令


【Java中SocketServer异步通信】_服务器

Java中的SocketServer类是一个基于传输层协议的服务器端类,它提供了一种机制,允许服务器端与多个客户端进行通信。

在Java中,实现异步通信可以使用多线程或者NIO(Non-blocking I/O)技术。

使用多线程实现异步通信的基本步骤如下:

  1. 创建ServerSocket对象,指定服务器端口号。
  2. 调用ServerSocket的accept()方法,等待客户端的连接。当有客户端连接时,accept()方法会返回一个Socket对象。
  3. 创建一个新的线程,处理与客户端的通信。可以使用Runnable接口或者继承Thread类来实现。
  4. 在新的线程中,使用Socket对象的InputStream和OutputStream来与客户端进行通信。

下面是一个简单的使用多线程实现异步通信的例子:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketServerExample {

    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8080);
            System.out.println("Server started");

            while (true) {
                Socket socket = serverSocket.accept();
                System.out.println("Client connected");

                // 创建一个新的线程,处理与客户端的通信
                Thread thread = new ClientHandler(socket);
                thread.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static class ClientHandler extends Thread {
        private Socket socket;

        public ClientHandler(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            try {
                InputStream inputStream = socket.getInputStream();
                OutputStream outputStream = socket.getOutputStream();

                // 处理与客户端的通信
                // ...

                socket.close(); // 关闭连接
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

上面的例子中,ServerSocket对象在8080端口上监听客户端的连接。当有客户端连接时,会创建一个新的线程(ClientHandler),该线程负责处理与客户端的通信。在ClientHandler线程中,通过Socket对象的InputStream和OutputStream来与客户端进行通信。

另一种实现异步通信的方式是使用Java的NIO技术。NIO提供了非阻塞的I/O操作,允许程序在等待I/O操作完成时继续做其他事情。

使用NIO实现异步通信的基本步骤如下:

  1. 创建ServerSocketChannel对象,并绑定到服务器端口。
  2. 将ServerSocketChannel设置为非阻塞模式。
  3. 创建Selector对象。
  4. 将ServerSocketChannel注册到Selector,监听OP_ACCEPT事件。
  5. 在循环中,调用Selector的select()方法,等待事件发生。
  6. 当有事件发生时,使用Selector的selectedKeys()方法获取事件的集合。
  7. 遍历事件的集合,根据事件的类型进行处理。

下面是一个简单的使用NIO实现异步通信的例子:

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class SocketServerExample {

    public static void main(String[] args) {
        try {
            ServerSocketChannel serverChannel = ServerSocketChannel.open();
            serverChannel.bind(new InetSocketAddress(8080));
            serverChannel.configureBlocking(false);

            Selector selector = Selector.open();
            serverChannel.register(selector, SelectionKey.OP_ACCEPT);
            System.out.println("Server started");

            while (true) {
                selector.select();
                Set<SelectionKey> keys = selector.selectedKeys();
                Iterator<SelectionKey> it = keys.iterator();

                while (it.hasNext()) {
                    SelectionKey key = it.next();
                    it.remove();

                    if (key.isAcceptable()) {
                        ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
                        SocketChannel socketChannel = serverSocketChannel.accept();
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector, SelectionKey.OP_READ);
                        System.out.println("Client connected");
                    } else if (key.isReadable()) {
                        SocketChannel socketChannel = (SocketChannel) key.channel();
                        ByteBuffer buffer = ByteBuffer.allocate(1024);
                        int bytesRead = socketChannel.read(buffer);

                        if (bytesRead == -1) {
                            socketChannel.close();
                            System.out.println("Client disconnected");
                        } else {
                            String message = new String(buffer.array(), 0, bytesRead);
                            System.out.println("Received message: " + message);
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

上面的例子中,我们首先创建一个ServerSocketChannel对象并绑定到8080端口,然后将它设置为非阻塞模式。接着,创建一个Selector对象,并将ServerSocketChannel注册到Selector中,监听OP_ACCEPT事件。

在循环中,调用Selector的select()方法等待事件的发生。当有事件发生时,我们使用Selector的selectedKeys()方法获取事件的集合。然后,遍历事件的集合,根据事件的类型进行处理。如果事件是OP_ACCEPT,表示有客户端连接,我们就接受客户端的连接,并将客户端的SocketChannel注册到Selector中,监听OP_READ事件。如果事件是OP_READ,表示有数据可读,我们就读取数据并处理。

下面是使用Java语言通过SocketServer异步通信的例子,其中一边可以查询信息并发送指令

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

public class SocketServerExample {

    public static void main(String[] args) {
        int port = 8080;

        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("Server started on port " + port);

            while (true) {
                Socket clientSocket = serverSocket.accept();
                System.out.println("Client connected: " + clientSocket.getInetAddress().getHostAddress());

                ClientHandler clientHandler = new ClientHandler(clientSocket);
                clientHandler.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static class ClientHandler extends Thread {
        private Socket clientSocket;
        private BufferedReader in;
        private PrintWriter out;

        public ClientHandler(Socket socket) {
            this.clientSocket = socket;
        }

        public void run() {
            try {
                in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                out = new PrintWriter(clientSocket.getOutputStream(), true);

                String inputLine;
                while ((inputLine = in.readLine()) != null) {
                    System.out.println("Received message from client: " + inputLine);

                    if (inputLine.equalsIgnoreCase("getinfo")) {
                        // 查询信息并发送结果给客户端
                        String info = "This is the server's information";
                        out.println(info);
                    } else if (inputLine.equalsIgnoreCase("sendcommand")) {
                        // 执行指令并发送结果给客户端
                        String commandResult = executeCommand("dir"); // 示例指令为查看当前目录
                        out.println(commandResult);
                    }
                }

                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        private String executeCommand(String command) throws IOException {
            StringBuilder sb = new StringBuilder();

            Process process = Runtime.getRuntime().exec(command);
            BufferedReader commandOutputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));

            String line;
            while ((line = commandOutputReader.readLine()) != null) {
                sb.append(line).append("\n");
            }

            return sb.toString();
        }
    }
}

该例子创建了一个SocketServer,监听在8080端口。当有客户端连接时,会创建一个新的线程处理该客户端的请求。在处理请求过程中,如果客户端发送"getinfo"指令,则会返回服务器的信息;如果客户端发送"sendcommand"指令,则会执行一个指令并返回执行结果。