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

java分布式开发TCP/IP NIO无阻塞 Socket((基于消息方式实现系统间的通信) )

阅读更多

在java中可以基于java.nio.channels中的Channel和Selector的相关类来实现TCP/IP+NIO方式的系统间通信。

 

用于系统间通信依靠SocketChannel和ServerSocketChannel,SocketChannel用于建立连接,监听事件及操作读写,ServerSocketChannel用于监听端口及监听连接事件,可通过Selector来获取是否有要处理的事件。

 

服务端java代码:

package com.java.distributed.message.tcpip;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;

public class NIOServer {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		int port =7889;
		//打开选择器
		Selector selector=Selector.open();
		//打开服务器套接字通道
		ServerSocketChannel ssc=ServerSocketChannel.open();
		//检索与此通道关联的服务器套接字
		ServerSocket serverSocket=ssc.socket();
		//将 ServerSocket 绑定到特定地址(IP 地址和端口号)
		serverSocket.bind(new InetSocketAddress(port));
		System.out.println("server listen on port:"+port);
		
		//调整通道的阻塞模式
		ssc.configureBlocking(false);
		//向给定的选择器注册此通道,返回一个选择键。SelectionKey.OP_ACCEPT--用于套接字接受操作的操作集位   
		ssc.register(selector, SelectionKey.OP_ACCEPT);
		
		while(true){
			//timeout:为正,则在等待某个通道准备就绪时最多阻塞 timeout 毫秒;如果为零,则无限期地阻塞;必须为非负数
			int nKeys=selector.select(1000);
			if(nKeys>0){
				
				for(SelectionKey key:selector.selectedKeys()){
					/*测试此键的通道是否已准备好接受新的套接字连接--
					 * 如果此键的通道不支持套接字接受操作,则此方法始终返回 false
					 * */
					if(key.isAcceptable()){
						ServerSocketChannel server=(ServerSocketChannel) key.channel();
						SocketChannel sc=server.accept();
						
						if(sc==null){
							continue;
						}
						sc.configureBlocking(false);
						sc.register(selector, SelectionKey.OP_READ);
					}else if(key.isReadable()){
						//分配一个新的字节缓冲区
						ByteBuffer buffer=ByteBuffer.allocate(1024);
						SocketChannel sc=(SocketChannel) key.channel();
						int readBytes=0;
						String message=null;
						try{
							int ret;
							try{
								while((ret=sc.read(buffer))>0){
									readBytes +=ret;
								}
								
							}catch(Exception e ){
								readBytes=0;
								//ignore
							}finally{
								//反转此缓冲区。首先对当前位置设置限制,然后将该位置设置为零
								buffer.flip();
							}
							
							if(readBytes>0){
								message=Charset.forName("UTF-8").decode(buffer).toString();
								buffer=null;
							}
						}finally{
							if(buffer!=null)
								buffer.clear();
						}
						
						if(readBytes>0){
							System.out.println("message from client:"+message);
							if("quit".equalsIgnoreCase(message.trim())){
								sc.close();
								selector.close();
								System.out.println("Server has been shutdown!");
								System.exit(0);
							}
							String outMessage="server response:"+message;
							sc.write(Charset.forName("UTF-8").encode(outMessage));
						}
						
					}
				}
				selector.selectedKeys().clear();
			}
		
		}
	}
}

 

 

客户端java代码:

package com.java.distributed.message.tcpip;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;


public class NIOClient {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		int port =7889;
		SocketChannel channel=SocketChannel.open();
		channel.configureBlocking(false);
		
		SocketAddress target=new InetSocketAddress("127.0.0.1",port);
		channel.connect(target);
		Selector selector=Selector.open();
		//用于套接字连接操作的操作集位
		channel.register(selector, SelectionKey.OP_CONNECT);
		BufferedReader systemIn=new BufferedReader(new InputStreamReader(System.in));
		
		while(true){
			if(channel.isConnected()){
				String command=systemIn.readLine();
				channel.write(Charset.forName("UTF-8").encode(command));
				
				if(command==null||"quit".equalsIgnoreCase(command.trim())){
					systemIn.close();
					channel.close();
					selector.close();
					System.out.println("Client quit !");
					System.exit(0);
				}
			}
			int nKeys=selector.select(1000);
			if(nKeys>0){
				for(SelectionKey key:selector.selectedKeys()){
					if(key.isConnectable()){
						SocketChannel sc=(SocketChannel) key.channel();
						sc.configureBlocking(false);
						sc.register(selector, SelectionKey.OP_READ);
						sc.finishConnect();
					}else if(key.isReadable()){
						ByteBuffer buffer=ByteBuffer.allocate(1024);
						SocketChannel sc=(SocketChannel) key.channel();
						int readBytes=0;
						try{
							int ret=0;
							try{
								while((ret=sc.read(buffer))>0){
									readBytes+=ret;
								}
							}finally{
								buffer.flip();
							}
							if (readBytes > 0) {   
                                System.out.println(Charset.forName("UTF-8")   
                                        .decode(buffer).toString());   
                                buffer = null;   
                            }   

						}finally {   
                            if (buffer != null) {   
                                buffer.clear();   
                            }
						}
					}
				}
					selector.selectedKeys().clear();   
			}
		}
	}

}

 

分享到:
评论
1 楼 mars914 2011-11-07  
channel,Buffer,selector。Java 标准IO中基于流进行数据交互,java NIO中给出了许多Buffer,基于数据块进行操作,通过channel(通道)进行交互。Channel同时支持异步的读和写。且主要与buffer进行数据读写。

Selector也是Java NIO提供的类,能够监听网络IO中Channel的事件,检查Channel是否准备好可读/可写,以及连接(connect),accept。一个Selector可支持监听多个Channel的事件。这样NIO中可以一个线程可以支持多个请求发送。

同样,考虑客户端发送多个请求,NIO方式相比BIO可以做到不阻塞,因此客户端可以采用连接复用的方式,即每个SocketChannel在发送消息后,不用等待响应可继续发送其他消息。这样可以降低连接池带来的资源争抢问题,对系统性能有帮助。

对于服务器接受多个连接请求,通常采用的是有一个线程来监听连接事件,另一个线程来监听网络流的读写事件。

当有网络流的读写事件时,在放入一个线程池中处理。这种方式比TCP/IP+BIO的好处是在于可接受很多连接,而这些连接只有在有真正的与服务器进行(请求)交互才会创建线程进行处理。这网上被称为:一请求一连接。

当连接数不多,或者连接数很多而且连接上的请求比较频繁是,TCP/IP NIO方式不会带相比TCP/IP+BIO理论上不会有太大的优势。

综上,TCP/IP+NIO对于高访问量的系统来说,服务器端可以支撑更多的连接。

相关推荐

    分布式Java中的TCP/IP+NIO

    在分布式Java应用中,TCP/IP协议和NIO(非阻塞I/O)是构建高性能、高可用性系统的关键技术。TCP/IP是一种传输层协议,确保数据在网络中的可靠传输,而NIO是Java提供的一个I/O模型,允许程序进行非阻塞的数据读写,...

    Java+TCP/IP+Socket编程++原书第2版

    在Java中,通过Socket类和ServerSocket类,我们可以实现基于TCP/IP的网络通信。 Java的Socket编程涉及到以下几个关键知识点: 1. **Socket类**:Socket是Java中用于实现TCP通信的类,它代表了客户端到服务器的一个...

    java基于TCP/IP的聊天室

    Java基于TCP/IP的聊天室是一种实现用户间实时通信的应用程序,它依赖于网络协议TCP/IP进行数据传输。在这个系统中,通常包含两个主要组件:服务器端和客户端。 **TCP/IP协议**是Transmission Control Protocol/...

    Java网络编程TCP/IP 实例源码

    Java网络编程是构建分布式系统和互联网应用的基础,TCP/IP协议栈则是网络通信的核心。本实例源码集专注于Java实现的TCP/IP网络编程,适合初学者和有经验的开发者加深理解。下面将详细介绍其中涉及的关键知识点。 一...

    Java TCPIP Socket 编程中文版

    Java TCP/IP Socket编程是网络通信领域中的核心技术,它允许Java应用程序通过网络进行双向通信。在本教程中,我们将深入探讨这个主题,理解TCP/IP协议的基础,以及如何在Java中使用Socket进行实现。 TCP(传输控制...

    Java实现基于TCP协议的Socket通信

    Socket是TCP/IP协议族的应用程序接口,Java中的`java.net.Socket`和`java.net.ServerSocket`类是进行TCP通信的主要工具。 一、服务器端实现 服务器端需要创建一个`ServerSocket`实例,指定监听的端口号,然后调用`...

    Java_TCPIP_Socket中文版

    TCP(传输控制协议)是互联网协议栈中的一种面向连接的、可靠的传输层协议,而Socket则是Java提供的一种实现TCP/IP通信的接口。在这个“Java_TCP/IP_Socket中文版”资源中,我们很可能会学习到以下关键知识点: 1. ...

    Java TCP_IP Socket编程.rar

    总的来说,Java TCP/IP Socket编程涉及网络编程的基本原理和Java API的使用,是开发分布式系统、网络服务等应用的基础。通过深入学习和实践,开发者能够熟练掌握网络通信的核心技术,从而构建高效、可靠的网络应用。

    Java实现C/S架构的聊天系统

    这个系统利用了NIO(非阻塞I/O)机制、Socket通信以及多线程IO操作,实现了诸如好友管理、聊天交互以及文件传输等核心功能。这不仅为学习者提供了实际操作的机会,也是提升Java编程技能的良好实践。 首先,我们要...

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

    在IT行业中,网络通信是软件开发中的重要组成部分,特别是在分布式系统和互联网应用中。本话题主要探讨了两种常用编程语言——Java和C#之间如何利用Socket进行通信。Socket是网络编程的基本接口,允许应用程序通过...

    Java_TCPIP_Socket编程(中+英两本)

    Java TCP/IP Socket编程是网络通信领域中的核心技术,尤其在Java应用程序设计中扮演着至关重要的角色。Socket编程允许Java应用程序与其他网络上的程序进行双向通信,从而实现数据交换。本资源包含了两本书籍,一本是...

    《NIO与Socket编程技术指南》_高洪岩

    Socket通信基于TCP/IP协议,确保数据的可靠传输,通过输入流和输出流进行数据交换。在实际应用中,Socket常用于实现分布式服务、聊天应用、文件传输等场景。 本书可能涵盖了以下主题: 1. NIO基础:介绍NIO的基本...

    Java分布式程序设计 高清晰版

    Java语言由于其跨平台的特性,以及强大的网络通信库,如Java套接字(Sockets)、远程方法调用(RMI)、Java消息服务(JMS)等,成为了分布式系统开发的理想选择。 在Java中,分布式程序设计主要包括以下几个关键...

    Java_Socket开发高并发小型服务器

    在Java中,Socket提供了基于TCP/IP的网络通信能力。TCP是一种面向连接的、可靠的传输协议,保证了数据的有序性和无丢失性。通过创建ServerSocket来监听特定端口,等待客户机的连接,然后使用Socket建立实际的连接,...

    java网络即时通信系统

    综上所述,Java网络即时通信系统是基于Java技术构建的,利用Java的强类型、面向对象特性,结合NIO、Socket、WebSocket等网络通信技术,实现高效、实时的信息交换。同时,通过分布式架构、消息队列和安全机制,确保...

    java使用socket和c++通信

    在Java中,Socket类位于`java.net`包下,提供TCP/IP协议的网络通信功能。而在C++中,通常使用BSD Socket API进行网络编程,该API是操作系统提供的原生接口,适用于多种平台。 在Java中,非阻塞式Socket通信基于NIO...

    网络编程(socket、NIO、mina)---demo

    首先,Socket编程是网络编程的基础,它是TCP/IP协议族的一部分,提供了进程间通信的能力。Socket分为两种类型:基于TCP的面向连接的Socket和基于UDP的无连接的Socket。TCP Socket提供可靠的、基于字节流的数据传输,...

    分布式Java应用 完整版 PDF

    这一部分详细阐述了Java在网络编程中的应用,包括Socket编程、多线程通信、NIO(非阻塞I/O)以及Netty框架的使用。读者将学习如何创建高效的网络服务,理解TCP/IP协议栈的工作原理,以及如何处理并发连接和数据传输...

    socket实现tcp双机通讯

    在IT行业中,网络通信是至关重要的一个领域,特别是在分布式系统和互联网应用中。TCP(Transmission Control Protocol)是一种面向连接的、可靠的传输协议,为应用程序提供了一种在互联网上可靠发送和接收数据的方式...

    java-socket网络编程(tcp)

    在Java中,Socket是实现TCP通信的基础类,它提供了客户端与服务器端之间的双向通信通道。下面将详细介绍Java Socket与TCP网络编程的相关知识点。 1. **TCP协议基础** TCP是一种面向连接的、可靠的、基于字节流的...

Global site tag (gtag.js) - Google Analytics