在Java中,使用Socket處理并發連接通常有兩種方法:多線程和NIO(非阻塞I/O)。下面分別介紹這兩種方法的實現。
在這種方法中,為每個客戶端連接創建一個新的線程。當客戶端連接到服務器時,服務器將創建一個新的線程來處理該連接。這種方法簡單易實現,但在大量并發連接的情況下可能會導致性能問題。
以下是一個簡單的多線程服務器示例:
import java.io.*;
import java.net.*;
public class MultiThreadedServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("Server started on port 8888");
while (true) {
Socket socket = serverSocket.accept();
System.out.println("New client connected");
ClientHandler clientHandler = new ClientHandler(socket);
new Thread(clientHandler).start();
}
}
}
class ClientHandler implements Runnable {
private Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
InputStream input = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
OutputStream output = socket.getOutputStream();
PrintWriter writer = new PrintWriter(output, true);
String message;
while ((message = reader.readLine()) != null) {
System.out.println("Received message from client: " + message);
writer.println("Server received: " + message);
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
NIO提供了更高效的I/O操作,可以在單個線程中處理多個并發連接。這種方法使用Selector來監聽多個通道(Channel),當某個通道上有事件發生時(例如數據可讀或可寫),Selector會通知相應的處理器進行處理。這種方法在大量并發連接的情況下性能更好。
以下是一個簡單的NIO服務器示例:
import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*;
public class NIOServer {
public static void main(String[] args) throws IOException {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(8888));
serverSocketChannel.configureBlocking(false);
Selector selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("Server started on port 8888");
while (true) {
selector.select();
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectedKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
if (key.isAcceptable()) {
handleAccept(key, selector);
} else if (key.isReadable()) {
handleRead(key);
}
iterator.remove();
}
}
}
private static void handleAccept(SelectionKey key, Selector selector) throws IOException {
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
System.out.println("New client connected");
}
private static void handleRead(SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = socketChannel.read(buffer);
if (bytesRead > 0) {
buffer.flip();
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
String message = new String(data).trim();
System.out.println("Received message from client: " + message);
ByteBuffer responseBuffer = ByteBuffer.wrap(("Server received: " + message).getBytes());
socketChannel.write(responseBuffer);
} else if (bytesRead < 0) {
socketChannel.close();
}
}
}
這兩種方法都可以處理并發連接,具體選擇哪種方法取決于你的需求和性能要求。對于大量并發連接的情況,NIO方法通常更合適。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。