`

JAVANIO在Socket 通讯中的应用(转)

 
阅读更多

 

 

JAVANIO在Socket 通讯中的应用

 

1 引言

  用Java平台编写Socket(套接字)系统,因为输入输出都必须同步。这样,对于多客户端/ 服务器模式,不得不

使用多线程. 即为每个连接的客户都分配一个线程来处理输入输出,其线程与客户机之比几乎为1∶1,所以易受

到大量线程开销的影响,结果既导致了性能问题又缺乏可伸缩性。为解决这个问题,java平台的制订者引入了非

阻塞I/ O机制。

 

2 以前的Socket 编程

  以前的Socket 编程从服务器端套接字开始,下面我们看一个典型的C/ S系统中服务器端的设计:

创建新的ServerSocket :

ServerSocket s=newServerSocket() ;

接着,接受传入调用。调用accept()完成接入:

Socket conn=s. accept() ; / / 程序在此阻塞,直到服务器接受了一个客户机请求一旦建立连接服务器开始与

客户端进行数据流交换。

while (true) {

  Socket socket ;

  socket = s. accept() ; / / 取得客户请求,如果没有线程在此处阻塞

printStreamos = newPrintStream(newBufferedOutputStream(socket. getOutputStream())) ;

  BufferedReader is = newBufferedReader(newInputStreamReader(clientSocket. getInputStream())) ;

  / / 创建输入输出流,直到缓冲区满才成批的读取或发送数据

  . . . . . . .

  }

在此模式中,线程将在读或写时阻塞,一直到读或写操作彻底完成。如果在读的时候,数据尚未完全到达套

接字,则线程将在读操作上阻塞,一直到数据可用。我们一般是大量的使用线程来处理阻塞问题,但这个解决办

法会产生负效应:线程开销同时影响性能和可伸缩性,为此java的制订者推出了异步通讯机制来解决这些问题。

3 NIO结构

  NIO(NewI/ O) 设计的原理是反应器设计模式(Reactor pattern) 。分布式系统中的服务器应用程序必须处理

收稿日期:2003204218

第18卷第3期

2003年9月

成 都 信 息 工 程 学 院 学 报

JOURNALOFCHENGDUUNIVERSITYOFINFORMATIONTECHNOLOGY

Vol. 18No. 3

Sep. 2003

© 1994-2010 China Academic Journal Electronic Publishing House. All rights reserved.    http://www.cnki.net

多个向它们发送服务请求的客户机。然而,在调用特定的服务之前,服务器应用程序必须将每个传入请求多路分

用并分派到各自相应的服务提供者。反应器模式正好适用于这一功能,它允许事件驱动应用程序将服务请求多

路分用并进行分派,然后,这些服务请求被并发地从一个或多个客户机传送到应用程序。NIO就是根据此机理设

计而成。

NIO结构如图1所示:

图1 非阻塞Socket 结构

  NIO实现了异步输入输出,这是指在进行输入输出处理时,它不必等到输入输出处理完毕才返回,就实现了

非阻塞。在服务器端,ServerSocketChannel 通过静态函数open()返回一个ServerSocketChannel 实例。然后调用

ServerSocketChannel. socket(). bind()绑定到服务器某端口,并调用register(Selector sel , SelectionKey.OP- ACCEPT)注

册OP- ACCEPT(接受连接)事件到一个选择器中(ServerSocketChannel 只可以注册OP- ACCEPT事件) 。当有客户

请求连接时,选择器就会通知该通道有客户连接请求,就可以进行相应的输入输出控制了;在客户端,客户端通道

实例注册自己感兴趣的事件后(可以是OP- CONNECT,OP- READ,OP- WRITE的组合) ,调用SocketChannel. connect

(InetSocketAddress )连接服务器然后进行相应处理。这里的连接是异步的,即不会等到服务器有相应立即返回而

继续执行后面的代码。

4 NIO的实现

4.1 创建NIO的连接

为了实现基础的非阻塞套接字读和写操作,首先我们要引入NIO包,接着建立连接。限于篇幅,我们仅列出

关键部分代码,客户端建立与服务器的连接:

Stringhost = 192.168.0.1;

InetSocketAddress socketAddress = newInetSocketAddress(host , 80) ;

SocketChannel channel = SocketChannel.open() ;/ / SocketChannel 执行实际读写操作

channel. connect(socketAddress) ;

channel. configureBlockingMethod(false) ;/ / 使通道成为非阻塞的

在非阻塞模式中,线程将读取已经可用的数据(不论多少) ,然后返回执行其它任务。如果将真(true)传递给

configureBlockingMethod() ,则通道的行为将与在Socket 上进行阻塞读或写时的行为完全相同。所不同的是这些阻

塞读和写可以被其它线程中断。

NIO中实现非阻塞I/ O数据的读取主要靠Selector 类的工作。

4.2 Selector的工作

在反应器模式情形中,Selector 类对多个SelectableChannels 的事件进行多路复用。每个Channel 向Selector 注

册事件。当事件从客户机处到来时,Selector 将它们多路分用并将这些事件分派到相应的Channel。

创建Selector 最简单的办法是使用open() 方法:

Selector selector = Selector.open() ;

9 5 2 第3期           王洁:JAVANIO在Socket 通讯中的应用

© 1994-2010 China Academic Journal Electronic Publishing House. All rights reserved.    http://www.cnki.net

4.3 接受客户端的连接

要为每个客户机请求提供服务的Channel 创建一个连接。下面的代码创建称为Server 的ServerSocketChannel

并将它绑定到本地端口:

ServerSocketChannel serverChannel = ServerSocketChannel.open() ;

serverChannel. configureBlocking(false) ;

InetAddress ia = InetAddress. getLocalHost() ;

InetSocketAddress isa = newInetSocketAddress(ia, port ) ;

serverChannel. socket(). bind(isa) ;

每个要为客户机请求提供服务的Channel 都必须接着将自己向Selector 注册。Channel 应根据它将处理的事

件进行注册。接受传入连接的Channel 应这样注册:

SelectionKeyacceptKey = channel. register( selector,SelectionKey.OP- ACCEPT) ;

Channel 向Selector 的注册用SelectionKey对象表示。当Channel 被关闭,Selector 被关闭,调用Key的cancel()

时Key失效。

Selector 在select() 调用时阻塞。接着,它开始等待,直到建立了一个新的连接,或者另一个线程将它唤醒,或

者另一个线程将原来的阻塞线程中断。

4.4 服务器的工作

Server 是那个将自己向Selector 注册以接受所有传入连接的ServerSocketChannel :SelectionKeyacceptKey =

serverChannel. register(sel , SelectionKey.OP- ACCEPT) ;

 while (acceptKey. selector(). select() > 0){

Server 被注册后,根据每个关键字(key)的类型以迭代方式对一组关键字进行处理。一个关键字被处理完成

后,就都被从就绪关键字(readykeys)列表中除去:

Set readyKeys = sel. selectedKeys() ;

 Iterator it = readyKeys.iterator() ;

while (it. hasNext())

{

 SelectionKeykey = (SelectionKey)it. next() ;

 it. remove() ;

. . . .

}

如果关键字是可接受(acceptable)的,则接受连接,注册通道,以接受更多的事件(例如:读或写操作) 。如果关

键字是可读的(readable)或可写的(writable) ,则服务器会指示它已经就绪于读写本端数据:

SocketChannel socket ;

if (key.isAcceptable()) {

 ServerSocketChannel schannel = (ServerSocketChannel) key. channel() ;

 socket = (SocketChannel) schannel. accept() ;

 socket. configureBlocking(false) ;

 SelectionKeyakey = socket. register(sel ,SelectionKey.OP- READ| SelectionKey.OP- WRITE) ;

}

if (key.isReadable()) {

 Stringtempstr = readline(key) ;

 if (tempstr.length() > 0) {

0 6 2 成 都 信 息 工 程 学 院 学 报            第18卷

© 1994-2010 China Academic Journal Electronic Publishing House. All rights reserved.    http://www.cnki.net

  writeMessage(socket ,tempstr) ;

 }

}

if (key.isWritable()) {

 Stringtempstr = readline(key) ;

 socket = (SocketChannel)key. channel() ;

 if (result.length() > 0) {

  writeline(socket ,tempstr) ;

}

}

5 结束语

  NIO可以很好的解决以前Socket 编程中出现的问题,主要表现在有两方面:线程不再在读或写时阻塞,以及

Selector 能够处理多个连接,从而大幅降低了服务器应用程序开销。

 

分享到:
评论

相关推荐

    JAVANIO在Socket通讯中的应用

    ### JAVANIO在Socket通讯中的应用 #### 引言 在Java开发中,网络通信是常见需求之一,其中Socket编程是最基础也是最重要的技术之一。然而,在传统的Java Socket编程中,由于采用的是阻塞I/O模型,即所有的读写操作...

    java socket开发即时通讯服务器

    Java Socket 开发即时通讯服务器是构建实时通信系统的关键技术之一,尤其在企业级应用、在线游戏、聊天室等场景中广泛应用。本篇将深入探讨Java Socket在即时通讯服务器开发中的核心概念、步骤以及关键技术。 首先...

    卫通星GPS定位器GT06协议socket通讯JAVA Spring Boot对接.zip

    通过阅读和理解这些代码,你可以掌握如何在实际项目中应用Spring Boot进行Socket通讯,以及处理特定协议的技巧。 总之,将卫通星GPS定位器GT06与Java Spring Boot应用对接,涉及到了网络编程、协议解析、异步处理等...

    java Socket即时通讯

    在这个教程中,我们将深入理解Java Socket的基本概念,并通过一个实际的示例来阐述如何在Tomcat服务器上部署和运行一个简单的Socket即时通讯应用。 首先,Socket在Java中的主要类包括`java.net.Socket`(客户端)和...

    java_sx.rar_java socket _java 通讯_socket

    8. **安全性**:在实际应用中,可能会涉及到SSL/TLS安全套接字,用于加密数据传输,保护信息安全。 9. **心跳机制**:在长连接中,为了检测连接是否依然活跃,常需要实现心跳机制,定期发送确认信息。 10. **网络...

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

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

    java_chat_program.rar_socket java用户_socket即时通讯

    在这个"java_chat_program.rar"压缩包中,我们有一个基于Java Socket实现的简单即时通讯程序,用户既可以注册登录,也可以以游客身份使用,这为我们提供了一个理解Socket通信机制和实时聊天应用开发的实例。...

    基于java的BIO、NIO、AIO通讯模型代码实现

    这些通信模型在不同的场景下有着各自的优势,理解和掌握它们对于优化Java应用程序的性能至关重要。 **1. 基于Java的BIO(Blocking I/O)** BIO是Java早期的I/O模型,它是最简单也是最直接的。在BIO模型中,每个...

    Socket编程QQ实现 JAVA

    Socket编程在Java中是网络通信的基础,主要用于实现客户端与服务器之间的连接。QQ作为一个即时通讯软件,其背后的原理也离不开Socket通信。在这个项目中,我们将学习如何利用Java的Socket API来模拟实现一个简单的QQ...

    socket_java_yibu.rar_java socket _socket异步

    本压缩包中的"socket异步通讯实例"是一个具体的应用示例,旨在解释Java Socket如何实现异步通信。 首先,我们要了解什么是Socket。Socket在计算机网络中扮演着桥梁的角色,它连接了两台机器上的应用程序,允许它们...

    聊天室基础项目资料_socket聊天室_聊天室_java项目_socket_

    在这个项目中,开发者将学习如何利用Java的Socket类来创建客户端和服务器端的连接,实现实时的数据传输,构建一个简单的聊天环境。 【描述】"TCP/IP通信,使用Socket编程,java即时聊天室" 揭示了项目的重点在于...

    Java Socket传输图片源代码

    - 这种简单的图片传输机制适用于小型应用,如文件共享服务、即时通讯应用中的图片发送等。 - 对于大规模的、高性能的图片传输,可能需要更复杂的缓存策略、多线程处理和错误恢复机制。 通过学习和实践"Java ...

    Java网络编程socket

    本篇文章将深入探讨Java Socket编程的基本概念、核心类、以及实际应用中的关键点。 一、Socket基本概念 Socket,通常被称为套接字,是进程间通信的一种方式,它允许不同计算机上的进程通过网络进行通信。在网络编程...

    异步和多线程socket通讯

    本文将深入探讨"异步和多线程socket通讯"这一主题,基于提供的描述和标签,我们将讨论如何利用多线程和异步机制来提升socket通信的效率和响应性。 首先,Socket是一种在应用程序与网络服务之间建立连接的接口,它...

    socket通讯框架.rar

    Socket通讯框架是网络编程中的重要组成部分...以上就是Socket通讯框架的基本介绍,其核心在于通过TCP/IP协议实现进程间的可靠通信,而实际应用中往往结合多线程、并发处理、安全通信等技术,构建出高效稳定的网络服务。

    基于Java Socket网络编程的基础性应用研究.zip

    本研究主要探讨了Java Socket在基础性应用中的原理、方法及实践,旨在帮助开发者深入理解如何利用Java Socket进行网络数据传输。 一、Java Socket概述 Java Socket是Java提供的网络通信桥梁,它允许两台计算机通过...

    java网络编程socket

    Java网络编程中的Socket是连接应用程序和网络协议的重要接口,它允许两个网络应用程序通过TCP/IP通信。在Java中,Socket类代表了客户端与服务器之间的连接,ServerSocket类则用于服务器端,监听并接受客户端的连接...

    Socket 通讯客户端和服务器端

    在实际应用中,为了处理并发连接,服务器通常会使用多线程或异步I/O模型,如Java的NIO(非阻塞I/O)或Python的asyncio库。 在Socket编程中,还需要注意以下关键知识点: - **TCP与UDP**:Socket可以基于TCP(传输...

    Java springboot 整合mina 框架,nio通讯基础教程,mina框架基础教程.zip

    在这个压缩包中,包含了“Java_NIO基础视频教程”和“MINA视频教程”,你可以通过观看这些教程,了解和学习NIO和Mina的基本用法。同时,“Netty快速入门视频(52im.net).txt”虽然不是直接与Mina相关的,但Netty也是...

Global site tag (gtag.js) - Google Analytics