程序是通了,但是没法转发,获取不到对方ip。nio中 udp使用的是DatagramChannel ,但是SelectorKey.channel()转化之后的DatagramChannel,调用getRemoteAddress()获取不到对方的ip信息。

看了下java doc

A selectable channel for datagram-oriented sockets.

A datagram channel is created by invoking one of the open methods of this class. It is not possible to create a channel for an arbitrary, pre-existing datagram socket. A newly-created datagram channel is open but not connected. A datagram channel need not be connected in order for the send and receive methods to be used. A datagram channel may be connected, by invoking its connect method, in order to avoid the overhead of the security checks are otherwise performed as part of every send and receive operation. A datagram channel must be connected in order to use the read and write methods, since those methods do not accept or return socket addresses.

Once connected, a datagram channel remains connected until it is disconnected or closed. Whether or not a datagram channel is connected may be determined by invoking its isConnected method.

更多信息点这里

这个意思差不多就是DatagramChannel 是面向数据报的,是无连接的,所以不需要知道对面ip。然后就为null了。

但是

在bio中,通过DatagramPacket 是可以获取到对方ip信息的。 所以 ip信息应该是在报文里了。所以我要怎么样才能从报文中拿到这个ip呢?

假如使用nio,默认必须要通过ByteBuf 去读取,这样子就获取不到完整的报文信息了。我服了!

以下是代码

public class Server {
private static LinkedList<SocketAddress> list=new LinkedList<SocketAddress>();
private static final ExecutorService executorService = Executors.newFixedThreadPool(4);
private static DatagramChannel server=null;
private static Selector selector=null;
static {
try{
server=DatagramChannel.open().bind(new InetSocketAddress(8889));
server.configureBlocking(false);
selector=Selector.open(); }catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] args)throws Exception { server.register(selector, SelectionKey.OP_READ);
while (true){
if (selector.select()>0){
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while (iterator.hasNext()){
SelectionKey selectionKey = iterator.next();
if (selectionKey.isReadable()){
saveIP(selectionKey);
String msg = readMsg(selectionKey);
broadcast(msg);
}
iterator.remove();
}}
}
}
public static void saveIP(SelectionKey selectionKey)throws Exception{
if (selectionKey.channel() instanceof DatagramChannel){
System.out.println(true);
}
DatagramChannel channel=(DatagramChannel)selectionKey.channel();
SocketAddress address = channel.getRemoteAddress();
if (!list.contains(address)){
list.add(address);
System.out.println("新增ip:"+address);
}
System.out.println("当前udp 保存的ip数量:"+list.size());
}
public static void broadcast(String msg) throws Exception{
ByteBuffer byteBuffer=ByteBuffer.wrap(msg.getBytes());
//DatagramPacket packet=new DatagramPacket(msg.getBytes(),0,msg.getBytes().length);
for (SocketAddress address:list
) {
executorService.submit(new Runnable() {
@Override
public void run() {
try{
server.send(byteBuffer,address);
}catch (Exception e){
System.out.println(Thread.currentThread().getName()+":"+address+"发送失败");
}
}
});
}
}
public static String readMsg(SelectionKey selectionKey)throws Exception{
DatagramChannel channel=(DatagramChannel)selectionKey.channel();
ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
channel.receive(byteBuffer);
byteBuffer.flip();
String msg=new String(byteBuffer.array(),"utf-8");
System.out.println("收到消息:"+msg);
return msg;
}
}

####已经找到解决办法了
DatagramChannel的 receive方法的返回值就是发送端的ip
> public abstract SocketAddress receive(ByteBuffer dst) throws IOException
Receives a datagram via this channel.
If a datagram is immediately available, or if this channel is in blocking mode and one eventually becomes available, then the datagram is copied into the given byte buffer and its source address is returned. If this channel is in non-blocking mode and a datagram is not immediately available then this method immediately returns null.
The datagram is transferred into the given byte buffer starting at its current position, as if by a regular read operation. If there are fewer bytes remaining in the buffer than are required to hold the datagram then the remainder of the datagram is silently discarded.
This method performs exactly the same security checks as the receive method of the DatagramSocket class. That is, if the socket is not connected to a specific remote address and a security manager has been installed then for each datagram received this method verifies that the source's address and port number are permitted by the security manager's checkAccept method. The overhead of this security check can be avoided by first connecting the socket via the connect method.
This method may be invoked at any time. If another thread has already initiated a read operation upon this channel, however, then an invocation of this method will block until the first operation is complete. If this channel's socket is not bound then this method will first cause the socket to be bound to an address that is assigned automatically, as if invoking the bind method with a parameter of null.
Parameters:
dst - The buffer into which the datagram is to be transferred
Returns:
The datagram's source address, or null if this channel is in non-blocking mode and no datagram was immediately available //这里说了,返回值是source address
Throws:
ClosedChannelException - If this channel is closed
AsynchronousCloseException - If another thread closes this channel while the read operation is in progress
ClosedByInterruptException - If another thread interrupts the current thread while the read operation is in progress, thereby closing the channel and setting the current thread's interrupt status
SecurityException - If a security manager has been installed and it does not permit datagrams to be accepted from the datagram's sender
IOException - If some other I/O error occurs

最新文章

  1. git pull push 不用输入用户名和密码的方法
  2. Django进阶篇(二)
  3. WIN-CE系统架构
  4. HTML页面实现返回顶部效果 go to top
  5. Linux下JDK安装笔记
  6. wireshark排查打印机问题
  7. [OpenJudge 3066]随机序列
  8. leetcode:Remove Linked List Elements
  9. NHibernate讲解
  10. COMPACT 行记录格式
  11. 将日志写入EventLog
  12. NPM环境搭建
  13. Project: Individual Project - Word frequency program-11061160顾泽鹏
  14. B树、B-树、B+树、B*树详解
  15. cocos2dx之WebView踩过的坑(android返回键处理问题)
  16. Windbg DUMP
  17. BZOJ:4820: [Sdoi2017]硬币游戏&amp;&amp;BZOJ:1444: [Jsoi2009]有趣的游戏(高斯消元求概率)
  18. [LeetCode] Student Attendance Record II 学生出勤记录之二
  19. Mayor&#39;s posters(线段树+离散化)
  20. ajax传递数组,后台更新

热门文章

  1. adb之wm学习笔记
  2. 使用.net core3.0 正式版创建Winform程序
  3. linux常用开发命令总结
  4. 【ADO.NET基础-Login】带验证码验证的登录界面(用于简单的基础学习)
  5. Android开发——Toolbar常用设置
  6. pikachu-数字型注入(post)#手工注入
  7. 04-numpy读取本地数据和索引
  8. Maven中jar包冲突的解决方式
  9. 防御 DDoS 的终极奥义——又拍云 SCDN
  10. 实际体验华为云AI : ModelArts