1-基本概念
1.1-IP 地址和端口号
1.1.1-IP 地址
在TCP/IP 协议中为每台计算机制定的一个使其识别要接收数据的计算机和发送数据的计算机的标识号。目前IP 地址在计算机中用4个字节,也就是32位的二进制数来表示。为了方便记忆和使用,通常采用十进制数表示每个字节,并且每个字节之间用圆点隔开。如192.168.32.40
除了用IP 地址表示网络中的计算机,我们还可以用**DNS(域名服务)**形式表示。域名是由“.”分割的几个子域名组成。每次使用这种域名时,系统都会自动将其转换成数字形式的IP 地址后才能使用。
在网络中,IP 地址是唯一的,一个域名对应一个IP 地址,而一个IP 地址可以有多个域名对应。
1.1.2-端口
当IP 地址将数据送到该计算机时,每个被发送的网络数据包的头部都包含一个称为“端口”的部分,用于表示该数据包应交给接收数据的哪个网络应用程序。
每一个网络程序都必须要制定一个端口号,同一台计算机不能运行两个使用同一端口号的网络应用程序。端口数范围为0-65525之间。
1.2-URL
互联网是连接全球计算机的网络,人们通过它来获取所需要的信息资源。这些资源的集合就是World Wide Web,通常也称位Web 或WWW。URL 就是提供网络所提供的信息资源的标准识别方式。
URL(Uniform Resource Locator) 是统一资源定位符的简称。其提供互联网上资源的统一标识,也就是资源的地址。
URL 的一般格式:协议:资源地址
其由两部分组成:协议部分和资源地址部分,中间用冒号分隔。资源部分应该是资源的完整地址,包括主机名、端口号、文件名等。
资源地址一般格式:host:port/file-info
其中host 是网络中计算机的域名或IP 地址,port 是该计算机中用于监听服务的端口号。因为大部分应用程序协议定义了标准端口,故port 和用于将host 和port 分开的冒号“:”可以省略。file-info 就是网络所要求的资源。
1.3-TCP 与UDP
TCP/IP 协议中,有两个高级协议比较重要。分别是“传输控制协议”(Transmission Control Protocol,简称TCP)和“用户数据报协议”(User Datagram Protocol,简称UDP)
1.3.1-TCP
TCP 是面向连接的通信协议,其提供两台计算机之间的可靠无差错的数据传输。应用程序利用TCP 进行通信时,源和目标计算机会建立一个虚拟连接。这个连接一旦建立,两台计算机之间就可以进行双向交流数据。
1.3.2-UDP
UDP 是无连接通信协议,UDP 不保证数据的可靠传输,但能够向若干个目标发送数据,接收发自若干个源计算机的数据。
1.4-Socket
Socket 是网络驱动层提供给应用程序编程的接口和一种机制。
有人叫做“套接字”,但实际上翻译成“插座”更好一点,就如同我们的主机要将网线插上网线插座才可以与其他主机通讯。
Socket 在应用程序中创建,通过一种绑定机制与驱动程序建立关系,说明自己所对应的IP 和port。此后,应用程序送给Socket 的数据,由Socket 交给驱动程序向网络发送出去。计算机从网络上收到与该Socket 绑定的IP 和port 相关的数据后,由驱动程序交给目的Socket,应用程序便可以从该Socket 中提取收到的数据。网络应用程序就是这样通过Socket 进行数据的发送与接收。
Java 为UDP 和TCP 两种通信协议提供了相应的编程类,这些类存放于java.net 包中,与UDP 对应的是DatagramSocket,与TCP 对应的是ServerSocket(用于服务器端)和Socket(用于客户端)。
确切地说,网络通信是两个网络程序之间在收发数据,我们也可以在一台计算机上进行两个网络程序之间的通信,只需要使用不同的端口号即可。
2-URL 的使用
Java 提供的基本网络功能包含在java.net 软件包中。
2.1-使用URL 的方法
URL 类使用的是World Wide Web 上资源的标准地址格式。一个URL 类似于一个文件名,其给出了可以获取信息的位置。
- 应用URL 类构造方法创建URL 对象
创建一个URL 对象可以使用以下几种构造方法:
/* 使用一个代表完整URL的字符串创建URL对象 */
public URL(String fullURL)
/* 通过给出协议、主机名、文件名及一个可选择的端口号来创建一个URL对象 */
public URL(String protocol, String hostname, String filename)
public URL(String protocol, String hostname, int portNumber, String filename)
/* 基于已有的URL的某些信息创建一个新的URL */
public URL(URL contextURL, String spec)
注意: URL类的构造方法都要声明抛弃非运行时异常MalformedURLException,因此创建URL对象时的格式如下:
try{
URL url = new URL(...)
...
}
catch(MalformedURLException e){
...
}
- 获取URL对象的信息
URL对象的信息包括对象本身的属性,如协议名、主机名、端口号、文件名等。
下面是获取有关属性的方法:
public String GetProtocol() /* 返回该URL对象的协议名 */
public String GetHost() /* 返回该URL对象的主机名 */
public String GetPort() /* 返回该URL对象的端口号 */
public String GetFile() /* 返回该URL对象的文件名 */
public String GetRef() /* 返回该URL对象在文件中的引用标签。这是HTML页面的可选索引项,它在文件名之后,以一个#开始 */
public String toString() /* 获取代表URL对象的字符串 */
除可以获取URL对象的属性外,还可以使用以下两种方法获取存放在URL对象上的信息:
1)使用openConnection得到一个与URL的URLConnection连接。
通过URL类中的openConnection方法生成URLConnection类的对象,然后由URLConnection类提供的**getInputStream()**方法获取网络信息。
方法定义:
public URLConnection openConnection() throws IOException
该方法返回URL对象指定的一个远程对象的连接,它是一个URLConnection对象。
public InputStream getInputStream()
该方法返回一个InputStream类的对象。
2)使用**openStream()**方法得到一个到URL的InputStream流
应用URL类的openStream()方法可以与指定的URL建立连接并从中获取信息。
其方法的定义如下:
public final InputStream openStream() throws IOException
向网页http://www.baidu.com创建URL连接并执行openStream()方法打开数据流,然后对该数据流进行数据读取,即可返回“百度一下”页面的html信息:
public class my_net {
public static void main(String[] args) {
try {
URL myURL = new URL("http://www.baidu.com");
InputStream in = myURL.openStream();
int b;
while(((b=in.read()) != -1)) {
System.out.print((char) b);
}
}
catch(IOException e){
e.printStackTrace();
}
}
}
之前我们讲到InputStream是一个抽象类,不可实例化,但是在这里进行了实例化,为什么呢?
原因是在URL类下的openStream() 方法返回一个InputStream 类对象,此时返回的InputSteam 已经不是一个抽象类了,所以在这里这样实例化是可以的(其实就是将一个抽象类转化成了一个实例对象(实例对象已经实现了抽象类的构造方法))
由于char 不能表示汉字,所以上述例子打印出来的b 都是"?",下面用字符缓冲流的形式打开一个文件:
public class my_net {
public static void main(String[] args) {
String inputline;
try {
URL myURL = new URL("file:///C:/Users/waao_wuyou/Desktop/Curriculum_Design_html.txt");
/* 用URL 对象的openStream() 方法获得InputStream 对象 */
InputStream inputstream = myURL.openStream();
/* 通过inputstream 新建InputStreamReader 类的对象 */
InputStreamReader file = new InputStreamReader(inputstream);
BufferedReader in = new BufferedReader(file);
while((inputline=in.readLine())!=null) {
System.out.println(inputline);
}
in.close();
}
catch(MalformedURLException ee) {
ee.printStackTrace();
}
catch(IOException e){
e.printStackTrace();
}
}
}
这样一来,汉字就可以表示出来了,虽然打印出来可能是乱码。
3-Socket 的应用
实现Socket 通信需要两个类,分别是Socket 和ServerSocket 类,代表网络通信的两端:客户端服务器端。
当连接成功时,应用程序两端都会产生一个Socket 对象,对这个对象进行操作,就可以完成所需的通信。对于一个网络连接来说,Socket 时平等的,不会因为在服务器端或是在客户端而产生不同级别。
3.1-TCP Socket 通信基本步骤
1)创建Socket 对象
客户端常用构造方法:
Socket (String host, int port)
Socket (InetAddress address, int port)
host、port、address 是要连接的服务器的主机名、端口号和IP 地址。
服务器端常用构造方法:
ServerSocket (int port)
ServerSocket (int port, int users)
port 是与客户端定义相同的端口号,users 是服务器端能够接受的最大用户数。
不管在客户端还是服务器端,创建Socket 对象时都可能发生IOException 异常,为此可以按以下方式创建Socket 对象:
客户端:
try{
Socket questsocket = new Socket ("http://www.dhu.edu.cn", 10000);
}
catch(IOException e{
}
服务器端:
try{
ServerSocket serversocket = new ServerSocket (10000);
}
catch(IOException e{
}
2)建立与Socket 的连接
客户端只要创建了Socket 对象,就表示已经建立了与Socket 的连接。
服务器端除了创建Socket 对象外还需要用accept() 方法等待客户端的呼叫,即接受客户端的Socket 对象。即:
try{
Socket socket = serversocket.accept;
}
catch(IOException e){
}
accept() 方法用于产生“阻塞”,直到接收到一个客户端的连接,并且返回一个客户端的Socket 对象。
3)获取Socket 的输入流、输出流,并进行读写操作
获取Socket 输入流、输出流的两个方法:
- getInputStream() 方法获得网络连接输入,同时返回一个InputStream 类对象;
- getOutputStream() 方法使连接的另一端将得到输入,同时返回一个OutputStream 类对象。
然后通过InputStream 和OutputStream 对象,按照一定的协议进行读写操作。
注意: 其中getInputStream() 和getOutputStream() 方法均会产生一个IOException 异常,它必须被捕获,因为它们返回的流对象通常都会被另一个流对象使用。
4)关闭Socket
socket.close()