天天看点

java学习笔记(四)networkStream

----------------------------------------------URL----------------------------------------------------------------------

java.net.URL代表对一个uniform resource locator(统一资源定位系统),类似http://metalab.unc.edu/javafaq/.,能够标识网络当中的一个资源的地址,这个类的构造函数有四个:

public URL(String u) 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(URL context, String u) throws MalformedURLException

这里出现了一个新的异常,也就是MalformedURLException,那么这个异常代表给出的字符串不是一个可用的URL,也就是说java内部可能没有实现对于这个协议的一个解析。

就是当前协议不能被解析

对于前两个构造函数,第一个是直接给出一个包含协议,主机,文件地址的完整地址字符串

URL u = null;
try {
u = new URL("http://www.poly.edu/schedule/fall97/bgrad.html#cs");
}
catch (MalformedURLException e) { }
           

对于第二个构造函数,只不过是给出协议,主机,和要找的文件所在的路径,让构造函数自己构造出URL

URL u = null;
try {
u = new URL("http", "www.poly.edu", "/schedule/fall97/bgrad.html#cs");
}
catch (MalformedURLException e) { }
           

有时候端口是不需要显示给出的,比如HTTP协议的默认端口是80,也可以通过第三个构造函数指定端口,第一个构造函数的完整的URL字符串当中很可能也是存在指定的端口的。

第四个构造函数可以根据给出的url,和要查找的文件,判断相对路径,然后解析出第二个文件的url,利用的是第一个路径和第二个文件的相对路径获取到第二个文件完整的url

URL u1, u2;
try {
u1 = new URL("http://metalab.unc.edu/javafaq/course/week12/07.html");
u2 = new URL(u1, "08.html");
}
catch (MalformedURLException e) { }
           

下面是根据闯进的url对象,获取到对应资源的输入流,可以利用这个输入流下载当前url定位到的这个文件

public final InputStream openStream() throws IOException

具体的例子如下:

try {
URL u = new URL("http://www.amnesty.org/");
InputStream in = u.openStream();
int b;
while ((b = in.read()) != -1) {
System.out.write(b);
}
}
catch (MalformedURLException e) {System.err.println(e);}
catch (IOException e) {System.err.println(e);}
           

因为网络链接,就算是局域网,在很多情况下都是缓慢的,不可靠的,所以我们在利用从网络获取的数据进行处理的时候,最好将数据先读取出来缓存到一个数组中,再进行处理,防止因为网络的问题,影响程序的效率,甚至导致程序崩溃。

------------------------------------------URL connections ------------------------------------------------------------

URLConnection和URL有着紧密的联系,我们可以通过URL的一个函数openConnection获取一个URLConnection的引用,实际上URL只是对URLConnection的一个封装,我们可以通过URLConnection可以更多对client和server之间的交流进行控制。

尤其突出的特点是,URLConnetion不仅能够获得一个输入流通过URL在客户端从服务器读取数据,还可以获取一个OutputStream向服务器发送数据,URLConnection是一个抽象类,用来处理与不同类型的服务器进行交流的类,它的子类实现了对webServer和FTPServer的具体操作

Socket是对传输协议的一个封装,而URL是对socket的一个封装。所以说应用起来更加方便,但是因为会有一个完整的报头,所以会比较消耗流量,因为得到了封装,所以在应用起来会受到一些限制,但是基本的应用都是能够做到的。URL更加过分,是对URLConnetion的一个封装

一、利用URLConnection读取数据

1.首先利用完整url地址创建URL对象

2.利用创建的url对象的openConnection函数创建URLConnection对象,在地址中的主机地址和端口等信息都会被配置号

3.利用connect()方法和服务器建立起链接,大概的实现就是利用socket建立一个网络连接或者说通过文件流访问本地的文件

4.可以利用getInputStream()或者getContent()获取输入流

之上的模式一般应用于HTTP/1.0协议,因为它不能够适应交叉的请求,回复,请求,回复.......,只能使用像HTTP/1.0这种单个请求的协议,对于FTP和HTTP/1.1不能够很好的适用。如果当前给出的URL的链接是不能够创建的,那么会抛出IOException异常。

import java.net.*;
import java.io.*;
import com.macfaq.io.*;
public class WebCat {
public static void main(String[] args) {
if (args.length == 0) {
System.err.println("Usage: java WebCat url1 url2 ...");
return;
}
for (int i = 0; i < args.length; i++) {
if (i > 0 && i < args.length) {
System.out.println();
System.out.println("----------------------");
System.out.println();
}
System.out.println(args[i] + ":");
try {
URL u = new URL(args[i]);
URLConnection uc = u.openConnection();
uc.connect();
InputStream in = uc.getInputStream();
StreamCopier.copy(in, System.out);
in.close();
}
catch (IOException e) {System.err.println(e);}
} // end for
           

上面是一个读入的例子,需要接收IOException异常

二、利用URL Connection输出数据

其实和读入的步骤差不多,只是要打开允许输出的开关而已

import java.net.*;
import java.io.*;
import com.macfaq.io.*;
public class MailClient {
public static void main(String[] args) {
if (args.length == 0) {
System.err.println("Usage: java MailClient [email protected]");
return;
}
try {
URL u = new URL("mailto:" + args[0]);
URLConnection uc = u.openConnection();
uc.setDoOutput(true);
uc.connect();
OutputStream out = uc.getOutputStream();
StreamCopier.copy(System.in, out);
out.close();
}
catch (IOException e) {System.err.println(e);}
           

------------------------------------------------Socket--------------------------------------------------------

对于java的程序员来说,分组发送等操作都被封装到了socket,我们需要进行的操作只是

1.连接到远程的计算机

2.传输数据

3.接收数据

4.关闭连接

它是在两台主机之间进行最基本的通信,没有协议的模板,不像URL和URLConnection那样会将内容封装到HTTP/1.0的协议当中。

public Socket(String host, int port) throws UnknownHostException,IOException

host一般会是" www.oreilly.com " 或 " metalab.unc.edu "这种类型的字符串

也可以是"196.121.0.106"这类的字符串通过构建为InetAddress达到同样的效果

public Socket(InetAddress address, int port) throws IOException

public Socket(String host, int port, InetAddress localAddr, int localPort)

throws IOException

public Socket(InetAddress address, int port, InetAddress localAddr, int

localPort) throws IOException

因为每个主机会分成65,536个不同的端口,因为socket实际上是主机上应用和应用的交流,所以说我们需要端口来标识我们建立连接之后,传送数据的最远位置。一般主机只有一个地址,在不设定端口的时候,会自动设定一个合适的端口。

public InputStream getInputStream() throws IOException

public OutputStream getOutputStream() throws IOException

在交流的时候,我们通过输入和输出流,通过输入流获得远程主机发送过来的数据,输出流负责向远程主机发送数据。

public synchronized void close() throws IOException

当一个输入流和输出流被关闭,那么如果再利用输入输出流,会抛出异常IOException

-----------------------------------------serverScoket------------------------------------------------------------------

在每个连接中,存在两个端,一个是客户端,一个是服务器,客户端负责发送请求,客户端负责回复请求。在我们实现一个服务器的时候,我们需要一个机制来等待客户端发送请求。一个serverSocket绑定在当前主机的一个端口,它监听远程的客户端发送请求,许多客户端可以同时向一台主机的同一端口,一个端口同时只能有一个serverScoket取监听,这样能够防止冲突。

java.net.ServerSocket

public ServerSocket(int port) throws IOException

public ServerSocket(int port, int backlog) throws IOException

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

一般情况下我们只是将端口放入,其他的采用默认值即可

如果在初始化一个serverSocket,但是这个端口已经被绑定,那么会抛出异常java.io.BingException,是IOException的子类,如果端口写0,那么就是告诉java自己选一个合适的端口。

public int getLocalPort()

会得到当前serverSocket的端口

public Socket accept() throws IOException

public void close() throws IOException

accept会阻塞当前线程,知道接到请求。

try {
ServerSocket ss = new ServerSocket(2345);
Socket s = ss.accept();
OutputStream out = s.getOutputStream();
// Send data to the client.
s.close();
}
catch (IOException e) {System.err.println(e);}
           

socket比较灵活,因为它相对于URL封装的内容更少。