Java NIO无法绑定指定IP和端口解决方案

在使用SNMP4J时,我想指定创建的客户端使用的本地IP和端口,因为在Socket时这是可以的,但是发现无法实现

因为SNMP4J底层的通信是使用NIO实现的,而NIO编程时貌似就不能显示的指定

例如在SNMP4J的DefaultTcpTransportMapping类里面,当作为客户端需要发送消息时,程序首先判断是否创建了这个客户端,如果没有在创建时看到这样的代码:

SocketChannel sc = null;
try {
	sc = SocketChannel.open();
	sc.configureBlocking(false);
	sc.connect(new InetSocketAddress(((TcpAddress) address).getInetAddress(),((TcpAddress) address).getPort()));
	s = sc.socket();
	entry = new SocketEntry((TcpAddress) address, s);
	entry.addMessage(message);
	sockets.put(address, entry);
	synchronized (pending) {
		pending.add(entry);
	}
	selector.wakeup();
	logger.debug("Trying to connect to " + address);
} catch (IOException iox) {
	logger.error(iox);
	throw iox;
}

即使在SocketChannel中,他的Socket变量定义也是不能修改的:

/**
 * Retrieves a socket associated with this channel.
 *
 * <p> The returned object will not declare any public methods that are not
 * declared in the {@link java.net.Socket} class. </p>
 *
 * @return A socket associated with this channel
 */
public abstract Socket socket();

所以我直接判定Java NIO中,客户端是无法指定自己的IP和端口的!

那么有人在想为什么需要指定自己的IP和端口?具体需求我就不再说了,在计算机上虽然只有一块网卡,但是我们可以使用兼容的IP:

由于我的服务端程序以客户端IP来判断信息来源,现在我需要在我的电脑上做测试程序,需要同时邦定两个IP地址进行消息发送。

此时我就可以在高级设置里面设置兼容IP就可以,但是现在程序却无法选择。

在Socket里面可以这样写:

package com.xidian.nms.socket;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
public class SocketServer {
	public static void main(String[] args) throws Exception {
		// 创建非邦定式连接对象
		ServerSocket ss = new ServerSocket();
		// 需要邦定的本地IP和地址
		SocketAddress address = new InetSocketAddress("192.168.0.109", 2330);
		// 将连接对象邦定到地址
		ss.bind(address);
		System.out.println("服务已经启动");
		while (true) {
			// 接收请求
			Socket socketClient = ss.accept();
			// 客户端IP
			String ip = socketClient.getInetAddress().getHostAddress();
			// 客户端端口
			int port = socketClient.getPort();
			System.out.println("服务端收到请求:" + ip + "/" + port);
		}
	}
}

服务端很简单,你可以一行代码搞定,也可以显示的指定IP、端口,然后进行显示的服务连接操作:

package com.xidian.nms.socket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
public class SocketClient {
	public static void main(String[] args) throws Exception{
		Socket socket = new Socket();
		// 需要邦定的本地IP
		InetAddress iaddThis = InetAddress.getByName("192.168.1.109");
		// 需要邦定的本地地址
		SocketAddress saddThis = new InetSocketAddress(iaddThis,2331);
		socket.bind(saddThis);
		// 连接的远程服务地址
		InetAddress iaddRe = InetAddress.getByName("192.168.0.109");
		SocketAddress saddRe = new InetSocketAddress(iaddRe,2330);
		// 显示连接
		socket.connect(saddRe);
//		Socket socket = new Socket("192.168.0.109", 2330);
	}
}

注释掉的内容是一行搞定连接的方式。

经过测试,如果想要修改所邦定的IP和显示再次进行连接操作,需要把设置NIO同步的代码放到后面:

try {
	sc = SocketChannel.open();
	s = sc.socket();
	s.bind(new InetSocketAddress("192.168.0.109", 999));
	s.connect(new InetSocketAddress(((TcpAddress) address).getInetAddress(),((TcpAddress) address).getPort()));
	sc.configureBlocking(false);
	entry = new SocketEntry((TcpAddress) address, s);
	entry.addMessage(message);
	sockets.put(address, entry);
	synchronized (pending) {
		pending.add(entry);
	}
	selector.wakeup();
	logger.debug("Trying to connect to " + address);
} catch (IOException iox) {
	logger.error(iox);
	throw iox;
}

否则会报错:

Exception in thread "main" java.nio.channels.IllegalBlockingModeException
at sun.nio.ch.SocketAdaptor.connect(SocketAdaptor.java:76)
at sun.nio.ch.SocketAdaptor.connect(SocketAdaptor.java:65)
at org.snmp4j.transport.DefaultTcpTransportMapping$ServerThread.sendMessage(DefaultTcpTransportMapping.java:503)
at org.snmp4j.transport.DefaultTcpTransportMapping.sendMessage(DefaultTcpTransportMapping.java:183)
at org.snmp4j.MessageDispatcherImpl.sendMessage(MessageDispatcherImpl.java:214)
at org.snmp4j.MessageDispatcherImpl.sendPdu(MessageDispatcherImpl.java:475)
at org.snmp4j.Snmp.sendMessage(Snmp.java:1110)
at org.snmp4j.Snmp.send(Snmp.java:914)
at org.snmp4j.Snmp.send(Snmp.java:894)
at org.snmp4j.Snmp.send(Snmp.java:859)
at com.xidian.nms.snmp.Snmp4jGet.sendPDU(Snmp4jGet.java:59)
at com.xidian.nms.snmp.Snmp4jGet.main(Snmp4jGet.java:38)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 深入了解java NIO之Selector(选择器)

    这一节我们将探索选择器(selectors).选择器提供选择执行已经就绪的任务的能力,这使得多元 I/O 成为可能.就像在第一章中描述的那样,就绪选择和多元执行使得单线程能够有效率地同时管理多个 I/O 通道(channels).C/C++代码的工具箱中,许多年前就已经有 select()和 poll()这两个POSIX(可移植性操作系统接口)系统调用可供使用了.许过操作系统也提供相似的功能,但对Java 程序员来说,就绪选择功能直到 JDK 1.4 才成为可行的方案. 下面我们来使用选择器:

  • java基于netty NIO的简单聊天室的实现

    一.为何要使用netty开发 由于之前已经用Java中的socket写过一版简单的聊天室,这里就不再对聊天室的具体架构进行细致的介绍了,主要关注于使用netty框架重构后带来的改变.对聊天室不了解的同学可以先看下我的博客(<JAVA简单聊天室的实现>) 本篇博客所使用的netty版本为4.1.36,完整工程已上传到Github(https://github.com/Alexlingl/Chatroom),其中lib文件夹下有相应的netty jar包和source包,自行导入即可. 1.为何要

  • 泛谈Java NIO

    前言 非阻塞IO,也被称之为新IO,它重新定义了一些概念. 1.缓冲buffer 2.通道 channel 3.通道选择器 BIO 阻塞IO,几乎所有的java程序员都会的字节流,字符流,输入流,输出流等分类就是针对BIO而言的.我们在使用BIO的时候都是建立基本的节点流然后用过滤流进行包装. 不同于BIO,NIO所有的IO操作都是通过通道读写buffer完成的.数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中. 通道 NIO的通道类似流,但是有所不同. 1.既可以从通道中读取数据,又可以

  • Java NIO实战之聊天室功能详解

    本文实例讲述了Java NIO实战之聊天室功能.分享给大家供大家参考,具体如下: 在工作之余花了两个星期看完了<Java NIO>,总体来说这本书把NIO写的很详细,没有过多的废话,讲的都是重点,只是翻译的中文版看的确实吃力,英文水平太低也没办法,总算也坚持看完了.<Java NIO>这本书的重点在于第四章讲解的"选择器",要理解透还是要反复琢磨推敲:愚钝的我花了大概3天的时间才将NIO的选择器机制理解透并能较熟练的运用,于是便写了这个聊天室程序. 下面直接上代

  • Java NIO Selector用法详解【含多人聊天室实例】

    本文实例讲述了Java NIO Selector用法.分享给大家供大家参考,具体如下: 一.Java NIO 的核心组件 Java NIO的核心组件包括:Channel(通道),Buffer(缓冲区),Selector(选择器),其中Channel和Buffer比较好理解 简单来说 NIO是面向通道和缓冲区的,意思就是:数据总是从通道中读到buffer缓冲区内,或者从buffer写入到通道中. 关于Channel 和 Buffer的详细讲解请看:Java NIO 教程 二.Java NIO Se

  • 基于Java写minio客户端实现上传下载文件

    前言: 确保已经安装了minio的服务端 代码: pom.xml <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>7.0.2</version> </dependency> application.yml server: port:90 minio: url: http://10.69.94.140

  • Java NIO.2 使用Path接口来监听文件、文件夹变化

    Java7对NIO进行了大的改进,新增了许多功能: •对文件系统的访问提供了全面的支持 •提供了基于异步Channel的IO 这些新增的IO功能简称为 NIO.2,依然在java.nio包下. 早期的Java只提供了File类来操作文件.文件夹本身,功能有限,性能也不高. NIO.2为解决这种缺陷,提供了Path接口,并提供了Paths.Files2个工具类,这2个工具类包含的方法都是静态方法,Files类提供了大量的静态方法来操作文件.文件夹. Path接口.Paths工具类使用示例: //获

  • 详解java NIO之Channel(通道)

    通道(Channel)是java.nio的第二个主要创新.它们既不是一个扩展也不是一项增强,而是全新.极好的Java I/O示例,提供与I/O服务的直接连接.Channel用于在字节缓冲区和位于通道另一侧的实体(通常是一个文件或套接字)之间有效地传输数据. channel介绍 通道是访问I/O服务的导管.I/O可以分为广义的两大类别:File I/O和Stream I/O.那么相应地有两种类型的通道也就不足为怪了,它们是文件(file)通道和套接字(socket)通道.我们看到在api里有一个F

  • Java NIO无法绑定指定IP和端口解决方案

    在使用SNMP4J时,我想指定创建的客户端使用的本地IP和端口,因为在Socket时这是可以的,但是发现无法实现 因为SNMP4J底层的通信是使用NIO实现的,而NIO编程时貌似就不能显示的指定 例如在SNMP4J的DefaultTcpTransportMapping类里面,当作为客户端需要发送消息时,程序首先判断是否创建了这个客户端,如果没有在创建时看到这样的代码: SocketChannel sc = null; try { sc = SocketChannel.open(); sc.con

  • PowerShell脚本开发之对指定IP进行端口扫描

    前些天看到一篇关于Metasploit与PowerShell的文章,里面提到了一句关于端口扫描的语句,写的很简练,思路很不错,可以抛开笨重的Nmap直接扫描指定的指定IP的端口: 复制代码 代码如下: 1..1024 | %{ echo ((new-object Net.Sockets.TcpClient).Connect("192.168.10.26",$_)) "$_ is open"} 2>$null 语句中直接通过..列举了1到1024之间的数字,通过

  • 运行django项目指定IP和端口的方法

    一.django项目启动命令 默认IP和端口 python manage.py runserver 指定端口 python manage.py runserver 192.168.1.50:8080 二.遇到的问题 Invalid HTTP_HOST header: '192.168.1.50'. You may need to add '192.168.1.50' to ALLOWED_HOSTS. 修改settings.py,将192.168.1.50添加到ALLOWED_HOSTS中 AL

  • Docker容器绑定外部IP和端口的方法

    Docker允许通过外部访问容器或者容器之间互联的方式来提供网络服务. 以下操作通过myfirstapp镜像模拟,如何制作myfirstapp镜像请点击此处. 1.外部访问容器 容器启动之后,容器中可以运行一些网络应用,通过-p或-P参数来指定端口映射. a.用-P(大写)标记时,docker会随机选择一个端口映射到容器内部开放的网络端口上. $ docker run -d -P myfirstapp python app.py $ docker ps CONTAINER ID IMAGE CO

  • nuxt配置通过指定IP和端口访问的实现

    非常简单,只要加一个配置! 第1步,复制这个代码(端口可改) "config": { "nuxt": { "host": "0.0.0.0", "port": "8090" } }, 第2步,找到根目录下的package.json,把代码粘贴进去. 这是全部的代码,我这里配置在了8~13行. { "name": "guanWangPhone", &

  • Java获取服务器IP及端口的方法实例分析

    本文实例讲述了Java获取服务器IP及端口的方法.分享给大家供大家参考,具体如下: 前几天写过一个获取远程服务器的IP和端口的程序,从网上查了一些资料顺便加一些自己的理解,希望对大家有所帮助: struts2 获取request HttpServletRequest requet=ServletActionContext.getRequest(); requet.getScheme()+"://"+requet.getServerName()+":"+requet.

  • python实现指定ip端口扫描方式

    在Linux中判断一台主机是否可达,可以使用ping命令,而判断端口是否打开,可以使用telnet命令,但是telnet命令没有超时时间的参数,使用起来不是很方便,那么可以利用Python来完成一个端口扫描的功能 socket实现端口扫描 #!/usr/bin/env python import socket def get_ip_status(ip,port): server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: se

  • C# 基于TCP 实现扫描指定ip端口的方式示例

    目录 一.单线程扫描 1.代码 2.界面 3.结果 4.抓包 二.多线程扫描 1.代码 2.界面 3.结果 4.抓包 三.总结 四.源码 1.github 2.gitee 一.单线程扫描 1.代码 using System; using System.Windows.Forms; using System.Net; using System.Net.Sockets; using System.Threading; namespace SingleThreadScanningPort { publ

  • springcloud client指定注册到eureka的ip与端口号方式

    client指定注册到eureka的ip与端口号 #设置使用IP eureka.instance.prefer-ip-address=true #设置外网IP号 eureka.instance.ip-address=49.10.22.106 #设置外网端口号 eureka.instance.non-secure-port=5565 eureka注册时使用ip而不是hostname问题 eureka的client注册到server时默认是使用hostname而不是ip,这就导致client在多台机

  • Java NIO原理图文分析及代码实现

    前言: 最近在分析hadoop的RPC(Remote Procedure Call Protocol ,远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.可以参考:http://baike.baidu.com/view/32726.htm )机制时,发现hadoop的RPC机制的实现主要用到了两个技术:动态代理(动态代理可以参考博客:http://weixiaolu.iteye.com/blog/1477774 )和java NIO.为了能够正确地分析

随机推荐