`
chenjili88
  • 浏览: 3620 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Java 非阻塞 socket 通信

 
阅读更多

前几天我们公司C语言组的人需要一个基于socket的报文接收器来方便他们测试项目,我花了小半天给他们做了个多线程的socket服务端,我写好后在本机上测试后交给了他们,但是他们那边能连上服务器端,但是发送消息时没响应,后来我看到他们用的都是tcp/ip测试工具(一个c/s结构的socket调试工具)来测了,发送时我的后台也没有收到请求报文,但是他们的连接断了之后 我这边就收到了,又谷歌了一下,还真发现了问题,因为我的服务端 用的是serversocket类 这种是阻塞式的socket 当连接之后服务端就一直在读取流或者写出流 到缓存中,这种情况有两种方法解决,一是在客户端发送报文时末尾加个换行符,这种方法后来我试了下 好像是可以 但是客户端还是收不到实时的响应。第二种方法就是运用nio包下的非阻塞式的socket了(这种方法是最优的)。

非阻塞式socket 运用到了以下几个重要概念:

Selector:是 一个SelectableChannel对象的多路复用器,所有非阻塞式的channel都要注册到这个Selector上。

ServerSocketChannel:对应的是ServerSocket

SocketChannel:对应的是Socket

SelectionKey:这个就是来描述channel与selector之间注册关系的一个映射对象。

ByteBuffer:说这个首先要说一下channel与流的区别了,以前我们用的socket,读取写入数据用的都是流的形式,而nio包下的采用的都是块的形式,channel可以把一块数据映射到内存上,这样的话处理速度上内存速度肯定是优于流的,其实有点像操作系统的虚拟内存和分页存储。而ByteBuffer就是channel的一个容器,用来读和写数据用的,channel也只能通过ByteBuffer来处理数据。

如图所示是用NIO实现非阻塞服务端的示意图:

具体实现可以看以下的实例服务端:

public class NServer {
	private Selector selector=null;
	private Charset charset=Charset.forName("GBK");
	/**
	 * ByteBuffer有几个重要概念:position、limit
	 * ByteBuffer.allocate(1024) 开辟一个1024字节的空间
	 * 当读取n个字节position就加n(从0开始),limit 默认是开辟的空间最大的值
	 * ByteBuffer.flip();重置position为0,limit为已用空间的最后一个值的索引(通常之后将是写数据的操作)
	 * ByteBuffer.clear();重置position为0,limit为开辟空间的最大的值(通常之后是重新读取数据的操作)
	 */
	private ByteBuffer buffer=ByteBuffer.allocate(1024);
	private static final int PORT=3001;
	
	public void init() throws IOException{
		//新建selector
		selector=Selector.open();
		//新建serversocket
		ServerSocketChannel server=ServerSocketChannel.open();
		//绑定本地端口
		server.socket().bind(new InetSocketAddress("127.0.0.1", PORT));
		//设置非阻塞模式
		server.configureBlocking(false);
		/**
		 * 注册至soket服务器至selector
		 * SelectionKey有4个状态:
		 * OP_READ	可读模式
		 * OP_WRITE	可写模式
		 * OP_CONNECT	可连接模式
		 * OP_ACCEPT	接受连接模式
		 * 4个状态可以累加
		 */
		server.register(selector, SelectionKey.OP_ACCEPT);
		
		while(selector.select()>0){
			//遍历selector上的已注册的key并且处理key对应的channel
			Iterator<SelectionKey> it=selector.selectedKeys().iterator();
			while(it.hasNext()) {
				SelectionKey sk=it.next();
				if(sk.isAcceptable()){
					//接受请求处理
					SocketChannel socketChannel=server.accept();
					socketChannel.configureBlocking(false);
					socketChannel.register(selector, SelectionKey.OP_READ);
					sk.interestOps(SelectionKey.OP_ACCEPT);
				}
				if(sk.isReadable()){
					//读取客户端数据处理
					SocketChannel sc=(SocketChannel) sk.channel();
					String content="";
					try {
						while(sc.read(buffer)>0){
							//重置limit 为写数据做准备
							buffer.flip();
							content+=charset.decode(buffer);
							System.out.println("==================读取的数据是:"+content);
							sk.interestOps(SelectionKey.OP_READ|SelectionKey.OP_WRITE);
						}
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						sk.cancel();
						if(sk.channel()!=null)
							sk.channel().close();
					}
					if(content.length()>0){
						sk.attach(content);
					}
					//为读取数据做准备
					buffer.clear();
				}
				if(sk.isValid()&&sk.isWritable()){
					//写入客户端数据处理
					SocketChannel sc=(SocketChannel) sk.channel();
					String content=(String) sk.attachment();
					sc.write(charset.encode(content));
					sk.interestOps(SelectionKey.OP_READ);
				}
				//去除已经处理过的key
				it.remove();
			}
		}
	}
	public static void main(String[] args){
		try {
			new NServer().init();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

客户端可以用TCP/IP 测试工具 测试。

分享到:
评论

相关推荐

    java网络编程socket非阻塞通信

    通过java网络编程深入理解socket阻塞通信和非阻塞通信的在网络中的应用 源码包每一行都有注释,在代码里面每一个类都有详细的注释来解释这个类的功能这个方法的功能,调用哪一个类的哪一个功能等等。 压缩包包含实验...

    Nio非阻塞socket通信demo

    本人写的Nio非阻塞socket通信demo,内有注释。

    使用AIO实现非阻塞socket通信

    用Java编写的简易聊天工具,使用AIO实现非阻塞socket通信,对理解非阻塞socket通信有很多帮助。

    用Java实现非阻塞通信

    ● SocketChannel:Socket的替代类,支持阻塞通信与非阻塞通信。 ● Selector:为ServerSocketChannel监控接收连接就绪事件,为SocketChannel监控连接就绪、读就绪和写就绪事件。 ● SelectionKey:代表...

    使用NIO实现非阻塞socket通信

    Java编写的简易聊天工具,使用NIO实现非阻塞socket通信,使用Java原生sdk实现,可以运行。

    java使用socket和c++通信

    java和c++通信,支持多用户并发,采用java非阻塞式socket通信。

    java socket 大文件传输,快速传输(包的分片,组装)源码

    java socket 大文件传输,快速传输, 数据包的分片,组装,涉及UDP,TCP传输技术,NIO非阻塞等等,适合对socket编程进一步学习的同学

    协议socket通讯JAVA Spring Boot对接.rar

    1. Socket 机制 Socket,又称为套接字,用于描述 IP 地址和...只要有 IO,就会有阻塞或非阻塞的问题,无论这个 IO 是网络的,还是硬盘的。原因在于程序是运行在系统之上的,任何形式的IO 操作发起都需要系统内核的支持。

    轻量级网络通信框架nSocket.zip

    nSocket是基于java NIO.1和NIO.2开发的轻量级网络通信框架,该框架为用户提供异步非阻塞的网络编程接口。目前更新到0.1版本,实现了基本的连通性和简要的通信,在0.2版本中将增加filter chain的功能。nSocket与mina...

    java高手真经 光盘源码

    javanio.zip 23.NIO非阻塞通信(Socket/UDP实例、简单聊天系统) javarmi.zip 24.RMI编程(HelloWorld例、计算器实例) javacorba.zip 25.Corba编程(HelloWorld例、计算器实例) 第6部分(4个程序包) java...

    Java高手真经(编程基础卷)光盘全部源码 免积分

    javanio.zip 23.NIO非阻塞通信(Socket/UDP实例、简单聊天系统) javarmi.zip 24.RMI编程(HelloWorld例、计算器实例) javacorba.zip 25.Corba编程(HelloWorld例、计算器实例) 第6部分(4个程序包) java...

    socketjava源码-demo-sockets-io-nio-nio2:“Java套接字I/O:阻塞,非阻塞和异步”文章和源代码

    O:阻塞,非阻塞和异步 介绍 在描述I / O时,术语“非阻塞”和“异步”通常可以互换使用,但是它们之间存在显着差异。 本文描述了Java中非阻塞和异步套接字I / O操作之间的理论和实践差异。 套接字是通过TCP和UDP...

    Java高手真经(编程基础卷)光盘全部源码

    javanio.zip 23.NIO非阻塞通信(Socket/UDP实例、简单聊天系统) javarmi.zip 24.RMI编程(HelloWorld例、计算器实例) javacorba.zip 25.Corba编程(HelloWorld例、计算器实例) 第6部分(4个程序包) java...

    基于javatcpsocket通信的拆包和装包源码-NettyTree:网状树

    socket通信的拆包和装包源码 NettyTree 搭建一个基于Netty的通信框架 NIO:非阻塞式IO BIO:阻塞式IO 1) TCP粘包、拆包 2)编解码技术 1)Java序列化 2)业界主流的编解码框架 Thrift Protobuf 3) Websocket 5)...

    JAVA IO同步,异步

    介绍了基于系统底层通信技术socket,JAVA IO同步,异步,阻塞,非阻塞;

    基于javatcpsocket通信的拆包和装包源码-niochatroom:基于Javanio的聊天室

    socket通信的拆包和装包源码 功能 1)编写一个 NIO 群聊系统,实现服务器端和客户端之间的数据简单通讯(非阻塞) 2)实现多人群聊 3)服务器端:可以监测用户上线,离线,并实现消息转发功能 4)客户端:通过channel ...

    JAVA上百实例源码以及开源项目

     Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。  设定字符串为“张三,你好,我是李四”  产生张三的密钥对(keyPairZhang)  张三生成公钥(publicKeyZhang...

    JAVA上百实例源码以及开源项目源代码

     Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。  设定字符串为“张三,你好,我是李四”  产生张三的密钥对(keyPairZhang)  张三生成公钥(publicKeyZhang...

Global site tag (gtag.js) - Google Analytics