Java I/O全文摘要(五)数据源,网络流

来源:互联网 发布:python jsonrpc 编辑:程序博客网 时间:2024/04/28 20:20

1. 网络流

Java语言从一开始就考虑了网络的设计。

它是第一个对网络流支持和文件流支持同样多(甚至更多)的语言。

但是具体的所使用的流往往隐藏在无文档的sun包中。

因此,网络流依赖于InputStream 和 OutputStream的主要方法。

当然,高层构建上,你可以对流加上 缓冲,加密,压缩和其他一切你应用程序所需求的东西。


2 URLs

java.net.URL类代表了统一资源定位 (Uniform Resource Locator)

例如:http://www.cafeaulait.org/books/javaio2/

每个URL无歧义的代表了网络上唯一的资源。

URL有六个构造函数,他们都可能抛出MalformedURLException。(MalformedURLException是IOException的子类

public URL(String url) throws MalformedURLException
public URL(String protocol, String host, String file) throws MalformedURLException
public URL(String protocol, String host, int port, String file) throws MalformedURLException
public URL(String protocol, String host, int port, String file,  URLStreamHandler handler)  throws MalformedURLException
public URL(URL context, String url) throws MalformedURLException
public URL(URL context, String url, URLStreamHandler handler)  throws MalformedURLException


如果参数没有指定有效的URL,将抛出MalformedURLException异常。

仅仅带有一个URL的构造体按照如下方式使用:

URL u = null;try {  u = new URL("http://www.poly.edu/schedule/fall2006/bgrad.html#cs");}catch (MalformedURLException ex) {  // this shouldn't happen for a syntactically correct http URL}

有时,你希望单独指定协议,域名和API,按照下面的方式:

URL u = new URL("http", "www.poly.edu", "/schedule/ fall2006/bgrad.html#cs");

通常不需要指定端口,例如http默认端口为80,但有时候端口号会改变,这时候,你需要使用带有端口号的构造体:

URL u = new URL("http", "www.poly.edu", 80, "/schedule/ fall2006/bgrad.html#cs ");


此外,很多HTML包含了一个相关的URL,这也是最后两个构造体的用法。

一旦URL建立,你就可以从中检索数据了。


3.  从URL中获得数据

可以使用openStream()从字节流中获得原始数据,或者getContent( )返回代表数据的Java对象。

openStream()将构建一个与服务端连接的socket。

大多数网络,包括局域网,速度也比文件要慢,也更不可信赖。

英特网就更慢了,所以你需要读取少量数据,缓存到临时的位置并包装它,这再后面的章节中,BufferedInputStream就是这么干的。


4. URL 连接

URL连接于URL紧紧相连,正如它名字一样。

实际上,你可以通过URL的openConnection( )来获得URLConnection。

很多时候,URL是URLConnection的唯一包装类,

URLConnection提供了更多的客户端服务端的会话,

它不仅可以从客户端读取从服务端发送过来的信息,也可以将信息从客户端发往服务端。

java.net.URLConnection是一个抽象类,它可以处理不同类型的服务,例如FTP服务和WEB服务。

具体的子类隐藏在sun包中了,用于处理不同的服务。


5. 从URL Connections中读取数据

URL连接分为五部

(1)URL对象的建立

(2)使用URL对象的openConnection( )来创建URLConnection对象

(3)建立客户端与服务端的连接参数和请求属性

(4)使用连接方法connect( )来连接服务端,如果是网络使用socket,本地连接则用文件流

(5)通过getInputStream( )获得输入流,或者通过getContent( )获得内容句柄,也可通过getOutputStream( )向服务端发数据。


这个协议是基于HTTP 协议的,但是不是采用三次握手的方式,而是“单一请求,单一应答,关闭”的模式。

FTP可能不适用。

你无法直接构造URLConnection对象,你应该通过URL的 openConnection( )方法来获得它。

getInputStream( )将返回从URL读取数据的输入流。

当然,如果连接无法打开(如远端服务器不可达),connect( )将会抛出一个IOException

下面是使用URLConnection的一段代码样例.

    URL u = new URL(args[0]);    URLConnection connection = u.openConnection( );    in = connection.getInputStream( );    for (int c = in.read(); c != -1; c = in.read( )) {      System.out.write(c);    }


6. 向URL Connections中写入数据

与读很相似,但是你必须确定你要这么做。

使用通用的HTTP POST and PUT。

下面是步骤:

(1) 创建URL对象

(2)使用URL的openConnection( )方法来获得URLConnection对象

(3) 向方法setDoOutput( )中传入true表面你希望使用这个URLConnection对象来向服务器传递数据

(4) 如果你也希望读取数据setDoInput(true)

(5) 创建你想要传递的数据,最好是字节数组byte array

(6) 调用getOutputStream( )来获得输出流,往里面写入第5步创建的数组

(7) 关闭输出流

(8) 继续使用getInputStream( )获得输入流做一些事情


7. Sockets

在数据从一个主机发往别处时,通常需要切割成数据报文。

数据报文的大小从几十个字节到60000不等。

很多很大的东西都被切割成很小的部分,

这样的好处是,一旦有内容丢失了,也只需要重传丢失那部分的内容,

此外,如果到达不是顺序的,也需要在接收端重新排列起来。


幸运的是,这些包对于Java程序而言是不可见的。

Java已经将其抽象成了socket,它提供可信赖的两端之间的连接。

它独立于内容的编码,重传丢失,乱序重排等细节。

socket执行4个基本操作:

1>连接远端机器

2>发送数据

3>接收数据

4>关闭连接


一个socket可能连接超过一个远端主机。

基本类:java.net.Socket

它提供了两个主机间原始的,未翻译的通讯。

没有对于协议的抽象,那是URL和URLConnection关心的。

程序对于客户端与服务器的通信有完全的责任。


为了打开一个连接,构造一个Socket,然后制定要连接的host.

如果要连接一个新的主机,你需要创建一个新的Socket.

public Socket(String host, int port throws UnknownHostException, IOExceptionpublic Socket(InetAddress address, int port) throws IOExceptionpublic Socket(String host, int port, InetAddress localAddress, int localPort) throws IOExceptionpublic Socket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException

host参数可以是"www.oreilly.com" or "duke.poly.edu"

port端口号:大多数服务运行在知名的端口,如HTTP的80


8Sockets数据

数据在Socket上的发送和接收是通过流的。

public InputStream  getInputStream( ) throws IOExceptionpublic OutputStream getOutputStream( ) throws IOException

它也有关闭方法。

public void close( ) throws IOException

9 服务端Socket

每个连接都有两头:客户端,连接的发起者;服务端,连接的接受者。

为了使得能够建立连接,服务端必须写有能够让其他主机进行连接的程序。

他们监听来自远端请求建立连接.


多个客户端能够同时连接到一个服务端。

服务端可通过端口来确定客户端请求的服务。

由于需要同时处理多个连接请求,服务端需要多线程支持,输入的请求入队列,直到服务端能够接受它们。

对于默认的情况下,队列长度5~50,一旦满了,再次入列的请求将被拒绝,直到有可用。


类:java.net.ServerSocket

它代表一个服务端Socket

public ServerSocket(int port) throws IOExceptionpublic ServerSocket(int port, int backlog) throws IOExceptionpublic ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException

通常,下面这样就可以了:

ServerSocket ss = new ServerSocket(80);
如果端口已被绑定,抛出java.net.BindException


注意:在Unix 类系统上,端口必须在1~1023之间,否则accept()抛出BindException

0是特殊的情况,用于获取可用端口。

你可以使用getLocalPort方法来获取端口号

public int getLocalPort( )


客户端可服务端有用于指定端口号的连接是很有意义的,这样可以通过指定的端口号开辟新的连接用于独立通信。

例如FTP服务使用两个Socket,一个用于传递命令,一个用于传递数据。(先通过传递命令的将数据通道的基本参数传给服务端)


一旦你已经有了ServerSocket,那么调用accept( )方法来等待进入的连接。

这个方法被阻塞直到尝试建立连接的出现,然后返回一个Socket对象。这个对象用于与客户端通信。

public Socket accept( ) throws IOException


当然他也有close(),用于关闭

public void close( ) throws IOException


小Demo
ServerSocket ss = new ServerSocket(2345);while (true) {  Socket s = ss.accept( );  OutputStream out = s.getOutputStream( );  // send data to the client...  s.close( );}


注意关闭的是Socket,而不是ServerSocket。




0 0
原创粉丝点击