JAVA NIO 获取udp数据报的 发送方ip
程序是通了,但是没法转发,获取不到对方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
JAVA NIO 获取udp数据报的 发送方ip的更多相关文章
- Java网络编程(UDP协议:发送端)
package WebProgramingDemo; import java.io.IOException; import java.net.DatagramPacket; import java.n ...
- linux下的shell命令的编写,以及java怎样调用linux的shell命令(java怎样获取linux上的网卡的ip信息)
程序猿都非常懒,你懂的! 近期在开发中,须要用到server的ip和mac信息.可是server是架设在linux系统上的,对于多网口,在获取ip时就产生了非常大的问题.以下是在windows系统上, ...
- Java里面获取当前服务器(linux环境)的IP地址--与请求者的真实IP
package com.wfd360.Util; import javax.servlet.http.HttpServletRequest; import java.net.Inet4Address; ...
- 消息中间件系列三:使用RabbitMq原生Java客户端进行消息通信(消费者(接收方)自动确认模式、消费者(接收方)自行确认模式、生产者(发送方)确认模式)
准备工作: 1)安装RabbitMQ,参考文章:消息中间件系列二:RabbitMQ入门(基本概念.RabbitMQ的安装和运行) 2.)分别新建名为OriginalRabbitMQProducer和O ...
- Java网络编程UDP通信原理
前言 继续今天我们的Java网络编程--TCP和UDP通信 一.TCP和UDP概述 传输层通常以TCP和UDP协议来控制端点与端点的通信 TCP UDP 协议名称 传输控制协议 用户数据包协议 是 ...
- Java NIO UDP DEMO
今天有人问我Netty的UDP怎么使用,我自己尝试的去写一个Demo,在网上搜索了一下,关于Netty的UDP实现还是很少的,所以,今天写下这篇文章用来记录今天的一个简单Demo实现 不使用Netty ...
- 使用JAVA NIO实现的UDP client和server
//////////////////////////////////////////////////////////////////////////////////////////////////// ...
- JAVA NIO异步通信框架MINA选型和使用的几个细节(概述入门,UDP, 心跳)
Apache MINA 2 是一个开发高性能和高可伸缩性网络应用程序的网络应用框架.它提供了一个抽象的事件驱动的异步 API,可以使用 TCP/IP.UDP/IP.串口和虚拟机内部的管道等传输方式.A ...
- JAVA中获取当前运行的类名,方法名,行数
JAVA中获取当前运行的类名,方法名,行数 public static String getTraceInfo(){ StringBuffer sb = new StringBuffer(); Sta ...
随机推荐
- 品Spring:实现bean定义时采用的“先进生产力”
前景回顾 当我们把写好的业务代码交给Spring之后,Spring都会做些什么呢? 仔细想象一下,再稍微抽象一下,Spring所做的几乎全部都是: “bean的实例化,bean的依赖装配,bean的初 ...
- Windows上部署MySql
下载安装包 最新版本可以在 MySQL 下载中下载. 下载完后,我们将 zip 包解压到相应的目录,这里我将解压后的文件夹放在 D:\Program Files\Java\mysql-8.0.16-w ...
- 一个js破解教程
很好的一篇文章,先存着以后用到. 为了防止官网更新修复,存一下版本 https://pan.lanzou.com/b220073/ 密码:这是秘密 这篇文章以 JavaScript 为例讲解了破解的一 ...
- 使用Docker安装FastDFS(分布式文件系统)
1. 获取镜像 可以利用已有的FastDFS Docker镜像来运行FastDFS. 获取镜像可以通过下载 docker image pull delron/fastdfs 也可是直接使用提前下载的镜 ...
- 如何制作一个Nginx镜像
1,从这里你将学到编写Dockerfile的4个重要指令RUN,EXPOSE,ADD,ENTRYPOINT2,在Dockerfile中编写拷贝文件至容器的方法3, 安装一个nginx server,并 ...
- THINKPHP 中关联查询(多表查询)
THINKPHP 中关联查询(多表查询)可以使用 table() 方法或和join方法,请看示例: 1.Table方法:定义要操作的数据表名称,可以动态改变当前操作的数据表名称,需要写数据表的全名,包 ...
- 怎样实现给DEDE5.7的栏目增加栏目图片
前两天用DEDE做二次开发的时候,遇到一个问题,领导让给每个栏目增加一个栏目图片的功能,网上找了些东西,结合自己实际做的时候的方法,下面详细描述下具体的实现方式(只测试了V5.7版本,对低版本是否适用 ...
- MongoDB 学习笔记之 DBRef
DBRef: MongoDB建模有两种方式,一种是内嵌(Embed),另一种是连接(Link).内嵌比较好理解,就是字段内容是个数组,数组内再包含文档,而我们今天介绍的是另一种,称为链接DBRef.由 ...
- ssm配置文件
mybatis配置文件SqlMapConfig.xml <?xml version="1.0" encoding="UTF-8"?> <!DO ...
- 04-09 XgBoost算法
目录 XgBoost算法 一.XgBoost算法学习目标 二.XgBoost算法详解 2.1 XgBoost算法参数 2.2 XgBoost算法目标函数 2.3 XgBoost算法正则化项 2.4 X ...