`
chenjizone
  • 浏览: 4200 次
文章分类
社区版块
存档分类
最新评论

Java 非阻塞 socket 通信

    博客分类:
  • java
阅读更多

前几天我们公司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阻塞通信和非阻塞通信的在网络中的应用 源码包每一行都有注释,在代码里面每一个类都有详细的注释来解释这个类的功能这个方法的功能,调用哪一个类的哪一个功能等等。 压缩包包含实验...

    用Java实现非阻塞通信

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

    Nio非阻塞socket通信demo

    在这个“Nio非阻塞socket通信demo”中,我们可以深入理解NIO在Socket通信中的应用。 1. **Java NIO基础** - **通道(Channels)**:NIO的核心概念之一,通道是数据读写的目标或来源,如文件通道、套接字通道等。...

    非阻塞socket通信.doc

    非阻塞socket通信是Java编程中一种高效处理网络通信的方式,尤其在处理多客户端并发连接时更为适用。传统的Java Socket编程通常使用`ServerSocket`和`Socket`类,它们在处理连接请求和数据传输时会采取阻塞模式,即...

    使用AIO实现非阻塞socket通信

    总之,通过这个使用AIO实现的非阻塞socket通信项目,我们可以学习到如何利用Java AIO进行高效的网络编程,理解和实践异步I/O模型,这对于构建高性能、高并发的网络应用至关重要。通过实际操作,你可以更好地理解非...

    使用NIO实现非阻塞socket通信

    在Java编程中,NIO(New ...总之,本项目通过Java NIO实现了非阻塞socket通信,有效地解决了高并发场景下的连接管理问题,提高了系统效率。对于学习和理解NIO以及如何构建基于NIO的网络应用,这是一个很好的实践案例。

    java非阻塞通信研究

    Java非阻塞通信是现代Java开发中的一个重要概念,特别是在高并发和高性能的系统设计中。非阻塞通信允许程序在等待数据就绪时不会被挂起,而是继续执行其他任务,提高了系统的整体效率。这种技术主要应用于网络I/O...

    阻塞通信和非阻塞通信的区别

    例如,在使用非阻塞Socket时,如果服务器没有响应,客户端可以继续执行其他操作,而不需要等待服务器响应。 在Java中,通过使用ServerSocketChannel、SocketChannel和Selector可以实现非阻塞通信。...

    java使用socket和c++通信

    在Java中,非阻塞Socket通信主要涉及`java.nio`包下的Selector、Channel和Buffer等核心组件。 实现Java和C++之间的通信,首先需要在Java端创建ServerSocket监听特定端口,等待客户端连接。当C++客户端使用Socket...

    java.net包socket通信

    Java.NET包的Socket通信不仅限于基础的TCP连接,还可以通过SocketChannel和Selector等NIO(非阻塞I/O)类进行高效率的并发通信。NIO允许一个线程同时处理多个连接,提高了服务器的性能和可扩展性。 总之,Java.NET...

    java非阻塞式的通信

    ### Java非阻塞式通信详解 #### 一、线程阻塞的概念与影响 线程阻塞是指在程序运行过程中,线程遇到某些条件而暂时停止执行的状态,这种状态下线程将不会消耗CPU资源,直到阻塞条件解除。在传统的Java网络编程中,...

    C#和java 之间基于Socket的通信

    - 使用非阻塞I/O或异步I/O可以提高Socket通信的性能。Java的NIO(Non-blocking I/O)和C#的异步编程模型(如`async/await`关键字)都是不错的选择。 10. **测试与调试**: - 为确保通信正常,需要编写测试用例,...

    java Socket通信实现

    - Java NIO(New I/O)库提供了非阻塞的Socket通信方式,提高了高并发场景下的性能。 - `java.nio.channels.SocketChannel`和`java.nio.channels.ServerSocketChannel`是NIO中的Socket实现。 9. **SSL/TLS安全套...

    java web使用Socket通信案例源码

    Java Web使用Socket通信是一种常见的网络编程技术,常用于构建实时、低延迟的通信系统,例如在线聊天、游戏、远程控制等。在这个简单的案例中,我们将探讨如何在Java Web环境中运用Socket进行服务器与客户端的交互。...

    JavaSocket学习---NIO实现非阻塞的通信

    在实际应用中,NIO非阻塞Socket通信适用于高并发场景,如聊天服务器、在线游戏服务器等。通过复用线程和非阻塞的I/O操作,服务器能够处理大量并发连接,且资源消耗相对较低。然而,NIO的编程模型比传统的阻塞I/O复杂...

    Socket通信Java代码

    Socket通信在Java编程中是网络通信的基础,它允许两台计算机通过TCP/IP协议进行数据交换。Socket编程涉及网络层、传输层以及应用层等多个层次,主要用于实现客户端与服务器之间的连接。下面将详细介绍Java中的Socket...

    Java Socket学习---单线程阻塞

    为了提高效率,可以采用多线程或者非阻塞I/O(如NIO,Java的新I/O库)来改进。但是,对于初学者来说,理解单线程阻塞模型是学习网络编程的基础,有助于深入理解Socket通信的工作原理。 此外,源码分析可以帮助我们...

    基于java NIO的socket通信demo

    总的来说,这个示例展示了如何使用Java NIO进行Socket通信,通过非阻塞的方式提高系统的并发处理能力。同时,它还演示了如何处理字符集问题,保证了跨平台数据交换的准确性。对于理解和实践Java NIO在网络编程中的...

    socket通信,客户端向服务器传文件

    总结来说,Java中的Socket通信为客户端和服务器提供了双向通信的接口,可以用于文件传输。客户端通过建立Socket连接,读取文件内容并写入Socket的输出流,而服务器端则接收这些数据并保存到本地。这个过程涉及到了...

    java阻塞式socket服务

    Java NIO(非阻塞I/O)提供了这种能力,但本场景中我们讨论的是传统的阻塞式Socket。 三、ServerSocket的使用 1. 创建ServerSocket:通过`new ServerSocket(int port)`创建一个监听特定端口的服务器,其中port参数...

Global site tag (gtag.js) - Google Analytics