用Nio实现java的客户端和服务端
时间: 2023-11-09 14:08:46 浏览: 166
使用 NIO(Non-blocking I/O)实现 Java 的客户端和服务端可以提高网络通信的效率。下面是一个简单的示例,演示了如何使用 NIO 实现一个简单的客户端和服务端。
首先是服务端代码:
```java
import java.io.IOException;
import java.net.InetSocketAddress;
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 NioServer {
private static int BUF_SIZE = 1024;
private static int PORT = 8080;
private static int TIMEOUT = 3000;
public static void main(String[] args) {
selector();
}
public static void handleAccept(SelectionKey key) throws IOException {
ServerSocketChannel ssChannel = (ServerSocketChannel) key.channel();
SocketChannel sc = ssChannel.accept();
sc.configureBlocking(false);
sc.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocateDirect(BUF_SIZE));
}
public static void handleRead(SelectionKey key) throws IOException {
SocketChannel sc = (SocketChannel) key.channel();
ByteBuffer buf = (ByteBuffer) key.attachment();
int bytesRead = sc.read(buf);
while (bytesRead > 0) {
buf.flip();
while (buf.hasRemaining()) {
System.out.print((char) buf.get());
}
System.out.println();
buf.clear();
bytesRead = sc.read(buf);
}
if (bytesRead == -1) {
sc.close();
}
}
public static void handleWrite(SelectionKey key) throws IOException {
ByteBuffer buf = (ByteBuffer) key.attachment();
buf.flip();
SocketChannel sc = (SocketChannel) key.channel();
while (buf.hasRemaining()) {
sc.write(buf);
}
buf.compact();
}
public static void selector() {
Selector selector = null;
ServerSocketChannel ssc = null;
try {
selector = Selector.open();
ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(PORT));
ssc.configureBlocking(false);
ssc.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
if (selector.select(TIMEOUT) == 0) {
System.out.println("==");
continue;
}
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
if (key.isAcceptable()) {
handleAccept(key);
}
if (key.isReadable()) {
handleRead(key);
}
if (key.isWritable() && key.isValid()) {
handleWrite(key);
}
if (key.isConnectable()) {
System.out.println("isConnectable = true");
}
iterator.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (selector != null) {
selector.close();
}
if (ssc != null) {
ssc.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
```
然后是客户端代码:
```java
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
public class NioClient {
private static int BUF_SIZE = 1024;
private static int PORT = 8080;
private static int TIMEOUT = 3000;
public static void main(String[] args) throws IOException {
SocketChannel clientChannel = SocketChannel.open();
clientChannel.configureBlocking(false);
Selector selector = Selector.open();
clientChannel.register(selector, SelectionKey.OP_CONNECT);
clientChannel.connect(new InetSocketAddress(PORT));
while (true) {
if (selector.select(TIMEOUT) == 0) {
System.out.println("==");
continue;
}
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
if (key.isConnectable()) {
SocketChannel channel = (SocketChannel) key.channel();
if (channel.isConnectionPending()) {
channel.finishConnect();
}
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ);
Scanner scanner = new Scanner(System.in);
String message = scanner.nextLine();
channel.write(ByteBuffer.wrap(message.getBytes()));
} else if (key.isReadable()) {
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(BUF_SIZE);
int bytesRead = channel.read(buffer);
while (bytesRead > 0) {
buffer.flip();
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
System.out.println();
buffer.clear();
bytesRead = channel.read(buffer);
}
}
iterator.remove();
}
}
}
}
```
这里的服务端监听端口为 8080,客户端连接的端口也为 8080。客户端首先向服务端发送一条消息,然后等待服务端的响应。当服务端接收到客户端的消息后,就会输出到控制台,并将消息原封不动地返回给客户端。客户端接收到服务端的响应后,也会将其输出到控制台。
注意,这个示例只是一个简单的演示,实际开发中需要考虑更多的因素,例如线程安全、异常处理等等。
阅读全文