gpt4 book ai didi

java - 在同一端口上监听 TCP 和 UDP 请求

转载 作者:可可西里 更新时间:2023-11-01 02:31:45 26 4
gpt4 key购买 nike

我正在编写一组客户端/服务器程序

根据客户端请求的操作,我使用make TCP或者UDP request。

客户端的实现很简单,因为我可以轻松地打开与任何协议(protocol)的连接并将请求发送到服务器端。

另一方面,在服务器端,我想在同一个端口上同时监听 UDP 和 TCP 连接。此外,我喜欢服务器为每个连接请求打开新线程。

我采用了以下解释的方法:link text

我通过为每个 TCP/UDP 请求创建新线程来扩展此代码示例。

如果我只使用 TCP,这会正常工作,但当我尝试进行 UDP 绑定(bind)时它会失败。

请给我任何建议,我该如何纠正这个问题。

发送

这是服务器代码:

public class Server {
public static void main(String args[]) {
try {
int port = 4444;
if (args.length > 0)
port = Integer.parseInt(args[0]);

SocketAddress localport = new InetSocketAddress(port);

// Create and bind a tcp channel to listen for connections on.
ServerSocketChannel tcpserver = ServerSocketChannel.open();
tcpserver.socket().bind(localport);

// Also create and bind a DatagramChannel to listen on.
DatagramChannel udpserver = DatagramChannel.open();
udpserver.socket().bind(localport);

// Specify non-blocking mode for both channels, since our
// Selector object will be doing the blocking for us.
tcpserver.configureBlocking(false);
udpserver.configureBlocking(false);

// The Selector object is what allows us to block while waiting
// for activity on either of the two channels.
Selector selector = Selector.open();

tcpserver.register(selector, SelectionKey.OP_ACCEPT);
udpserver.register(selector, SelectionKey.OP_READ);

System.out.println("Server Sterted on port: " + port + "!");

//Load Map
Utils.LoadMap("mapa");
System.out.println("Server map ... LOADED!");

// Now loop forever, processing client connections
while(true) {
try {
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();

// Iterate through the Set of keys.
for (Iterator<SelectionKey> i = keys.iterator(); i.hasNext();) {
SelectionKey key = i.next();
i.remove();

Channel c = key.channel();

if (key.isAcceptable() && c == tcpserver) {
new TCPThread(tcpserver.accept().socket()).start();
} else if (key.isReadable() && c == udpserver) {
new UDPThread(udpserver.socket()).start();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
System.err.println(e);
System.exit(1);
}
}

UDPThread代码:

public class UDPThread extends Thread {
private DatagramSocket socket = null;

public UDPThread(DatagramSocket socket) {
super("UDPThread");
this.socket = socket;
}

@Override
public void run() {
byte[] buffer = new byte[2048];
try {
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);

String inputLine = new String(buffer);
String outputLine = Utils.processCommand(inputLine.trim());

DatagramPacket reply = new DatagramPacket(outputLine.getBytes(), outputLine.getBytes().length,
packet.getAddress(), packet.getPort());
socket.send(reply);

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

我收到:

Exception in thread "UDPThread" java.nio.channels.IllegalBlockingModeException
at sun.nio.ch.DatagramSocketAdaptor.receive(Unknown Source)
at server.UDPThread.run(UDPThread.java:25)

10倍

最佳答案

它应该可以工作。这段代码的问题之一似乎是 ByteBuffer 大小设置为 0,这意味着数据报被丢弃(如评论中所述)。如果您需要通过 UDP 接收任何信息并且您在可靠的网络上,您可以将大小设置得相当大并接收由多个数据包组成的大数据报。否则,在不可靠的网络上,将其设置为 MTU 大小。确保在接收到任何内容后翻转()字节缓冲区。

此外,为每个请求创建新线程不是一个好主意,为您在 HashMap 或其他东西中收到的每个不同 IP 创建一个“ session ”线程,然后执行 guarded block。在 session 对象上。传入新信息后收到消息时,唤醒沉睡在该对象上的线程。您拥有的选择器代码旨在避免以这种方式创建线程。

编辑:基于上面的代码,你创建了一个数据报 channel ,然后使用套接字直接接收数据报?那是没有意义的。只有在绑定(bind) channel 后才能使用 channel 方法。另外,不要在单独的线程中执行此操作。您的代码不是线程安全的,会自行崩溃。如前所述,将接收到的信息传递给单独的“ session ”线程。选择器旨在告诉您可以在不阻塞的情况下从哪些 channel 读取数据(尽管无论如何都禁用了阻塞,因此它会告诉您哪些 channel 有数据要从中读取)。

关于java - 在同一端口上监听 TCP 和 UDP 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2819274/

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