gpt4 book ai didi

java - 如何使用套接字 channel 读写数据和接受连接

转载 作者:行者123 更新时间:2023-12-03 18:11:55 26 4
gpt4 key购买 nike

我使用 java NIO 创建了一个简单的服务器客户端应用程序。我在那里使用了一个选择器来接受连接、读取数据和写入。但我想要一个应用程序,其中 1 个选择器将忙于接受连接,而第 2 个选择器将读取数据,第 3 个选择器将写入数据。

意味着我不想将所有负载都放入单个选择器中。

如何实现?有没有在线帮助

谢谢迪帕克。

//创建选择器 选择器selector = Selector.open();

    // Create two non-blocking server sockets on 80 and 81
ServerSocketChannel ssChannel1 = ServerSocketChannel.open();
ssChannel1.configureBlocking(false);
ssChannel1.socket().bind(new InetSocketAddress(80));

// Register both channels with selector
ssChannel1.register(selector, SelectionKey.OP_ACCEPT);

while (true) {
// Wait for an event
selector.select();

// Get list of selection keys with pending events
Iterator it = selector.selectedKeys().iterator();

// Process each key
while (it.hasNext()) {
// Get the selection key
SelectionKey selKey = (SelectionKey)it.next();

// Remove it from the list to indicate that it is being processed
it.remove();

// Check if it's a connection request
if (selKey.isAcceptable()) {
// Get channel with connection request
ServerSocketChannel ssChannel = (ServerSocketChannel)selKey.channel();

// Accepting a Connection on a ServerSocketChannel
SocketChannel sChannel = serverSocketChannel.accept();

// If serverSocketChannel is non-blocking, sChannel may be null
if (sChannel == null) {
// There were no pending connection requests; try again later.
// To be notified of connection requests,

} else {
// Use the socket channel to communicate with the client

}

}
}
}

最佳答案

通常,在非阻塞的tcp服务器上,先accept,再read,再write,

您需要按此顺序注册选择器才有意义。


示例代码

这是非阻塞 io 的完整示例:

TcpChannelTest.java:(TestNG 测试类)

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.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;

import org.testng.annotations.Test;

/**
* tcp channel test
*
* @author eric
* @date Sep 2, 2012 9:17:40 PM
*/
public class TcpChannelTest {
public String serverHost = "localhost";
public int serverPort = 12345;

private ServerSocketChannel server;
private int clientSerial = 0;
private int clientCount = 5;

// test tcp non-blocking channel,
@Test
public void testTcpNonBlockingChanne() throws IOException, InterruptedException {
// start server
startServerNonBlocking();

Thread.sleep(500); // wait server to be ready, before start client,

// start clients
for (int i = 0; i < clientCount; i++) {
startClientOnce();
}

// shutdown server,
Thread.sleep(500); // wait client to be handled,
shutdownServer();
}

// start non-blocking server,
private void startServerNonBlocking() throws IOException {
new Thread(new Runnable() {
@Override
public void run() {
try {
server = ServerSocketChannel.open();
server.socket().bind(new InetSocketAddress(serverHost, serverPort)); // bind,
server.configureBlocking(false); // non-blocking mode,

Selector selector = Selector.open();
server.register(selector, SelectionKey.OP_ACCEPT);

while (true) {
selector.select();
Set<SelectionKey> readyKeys = selector.selectedKeys();

// process each ready key...
Iterator<SelectionKey> iterator = readyKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = (SelectionKey) iterator.next();
iterator.remove();

if (key.isAcceptable()) {
SocketChannel client = server.accept();
System.out.printf("[%s]:\t%s\n", Thread.currentThread().getName(), "accept connection");
client.configureBlocking(false);

// prepare for read,
client.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
// read
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer inBuf = ByteBuffer.allocate(1024);
while (client.read(inBuf) > 0) {
System.out.printf("[%s]:\t%s\n", Thread.currentThread().getName(), new String(inBuf.array(), StandardCharsets.UTF_8));
}

// prepare for write,
client.register(selector, SelectionKey.OP_WRITE);
} else if (key.isWritable()) {
SocketChannel client = (SocketChannel) key.channel();
String response = "hi - from non-blocking server";
byte[] bs = response.getBytes(StandardCharsets.UTF_8);
ByteBuffer buffer = ByteBuffer.wrap(bs);
client.write(buffer);

// switch to read, and disable write,
client.register(selector, SelectionKey.OP_READ);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}, "t-server-threads").start();
}

// close server,
private void shutdownServer() {
try {
if (server != null) {
server.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* <p>
* tcp client - via channel,
* </p>
* <p>
* It send once request.
* </p>
*
* @throws IOException
*/
private void startClientOnce() throws IOException {
// start client in a new thread
new Thread(new Runnable() {
@Override
public void run() {
try {
SocketChannel client = SocketChannel.open(new InetSocketAddress(serverHost, serverPort));

// write
String request = "hello - from client [" + Thread.currentThread().getName() + "}";
byte[] bs = request.getBytes(StandardCharsets.UTF_8);
ByteBuffer buffer = ByteBuffer.wrap(bs);
while (buffer.hasRemaining()) {
client.write(buffer);
}

// read
ByteBuffer inBuf = ByteBuffer.allocate(1024);
while (client.read(inBuf) > 0) {
System.out.printf("[%s]:\t%s\n", Thread.currentThread().getName(), new String(inBuf.array(), StandardCharsets.UTF_8));
}

client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}, "t-channelClient-" + clientSerial++).start();
}
}

关于java - 如何使用套接字 channel 读写数据和接受连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/905781/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com