思维导图:
第13章:网络编程
学习目标:
- 理解TCP/IP网络模型的四个层次。
- 区分UDP和TCP的特点。
- 掌握IP地址和端口号的作用。
- 学会使用
InetAddress
类。 - 使用
ServerSocket
和Socket
编写多线程TCP通信程序。 - 使用
DatagramPacket
和DatagramSocket
编写多线程UDP通信程序。
网络基础:
- 计算机网络是连接不同地理位置的多台计算机,以共享资源和传递信息。
探索网络基础:13.1 网络编程入门
在现代社会,网络已经成为我们生活和工作中不可或缺的一部分。无论是发送电子邮件、在线购物,还是和朋友进行视频聊天,网络都扮演着重要的角色。但你有没有想过,是什么让这一切成为可能?答案就是网络编程。今天,我们将深入探索网络编程的基础——从TCP/IP模型到实际的程序设计。
学习网络编程,为什么重要?
在开始之前,让我们先了解一下学习网络编程的重要性。简单来说,网络编程允许不同计算机上的程序相互通信,实现数据和资源的共享。它是构建现代网络应用的基石,无论是一个简单的网站还是一个复杂的分布式系统,都离不开网络编程的支持。
TCP/IP的层次结构
TCP/IP是网络通信的基础。它包含四个层次:链路层、网络层、传输层和应用层。每一层都有其特定的功能和协议。例如,传输层的TCP和UDP协议负责控制数据的传输和接收。理解这些层次及其功能对于深入学习网络编程至关重要。
UDP与TCP的特点
在网络编程中,最常用的两种传输协议是UDP和TCP。UDP是无连接的,速度快但不可靠;而TCP是面向连接的,虽然速度比UDP慢,但它能保证数据的准确性和可靠性。根据你的需要,选择合适的协议至关重要。
IP地址和端口号的作用
每台连接到网络的设备都有一个独一无二的IP地址,就像每个人都有一个独特的身份证号。而端口号则像是大楼的房间号,它帮助确保信息准确送达特定的程序。理解IP地址和端口号的作用对于进行网络通信至关重要。
实践篇:InetAddress类的使用
在Java中,我们可以使用InetAddress类来操作IP地址。通过这个类,你可以获取本机或远程主机的IP地址,检查主机是否可达,等等。通过几行简单的代码,你就能掌握基本的网络操作。
TCP和UDP程序设计
最后,我们将探讨如何使用Java进行TCP和UDP程序设计。通过ServerSocket类和Socket类,我们可以创建多线程的TCP服务器和客户端。而DatagramPacket类和DatagramSocket类则用于构建UDP通信程序。通过实际的编程实践,你将能够将理论知识应用于现实世界。
结语
网络编程是一个深奥而又迷人的领域。通过学习它,你不仅能够理解数字世界的运作原理,还能创造出属于自己的网络应用。希望这篇博客能够激发你对网络编程的兴趣,让你在这个数字时代中更加自如地驾驭网络。走吧,让我们开始这段激动人心的旅程吧!
13.1 网络基础
网络通信协议简介: 网络通信协议是规定计算机如何通过网络进行数据交换的规则。最重要的网络协议集是TCP/IP,它将网络分为四层:链路层、网络层、传输层和应用层。
- 链路层:处理与电缆或其他传输媒介有关的物理接口细节。
- 网络层:负责将数据分组并发送到目标计算机或网络,例如IP协议。
- 传输层:控制数据的端点到端点通信,例如TCP和UDP。
- 应用层:处理应用程序的通信功能,例如HTTP、FTP和SMTP。
TCP和UDP的简介及比较:
- TCP (Transmission Control Protocol):一种面向连接的协议,提供可靠的、有序的和无差错的数据传输。适用于要求高可靠性的应用,例如网页浏览、文件传输。
- UDP (User Datagram Protocol):一种无连接的协议,提供快速的数据传输服务,但不保证数据的可靠性、有序性或完整性。适用于对速度要求高但对可靠性要求不高的应用,例如在线视频或游戏。
代码示例
1. 获取本机IP地址:
使用Java的InetAddress类,我们可以获取本机的IP地址。
import java.net.InetAddress;
public class IPAddressExample {
public static void main(String[] args) {
try {
InetAddress ip = InetAddress.getLocalHost();
System.out.println("本机IP地址:" + ip.getHostAddress());
} catch (Exception e) {
e.printStackTrace();
}
}
}
2. TCP客户端和服务器简单示例:
- TCP服务器端(等待客户端连接并发送消息):
import java.io.*;
import java.net.*;
public class TCPServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(6789);
System.out.println("等待客户端连接...");
Socket connectionSocket = serverSocket.accept();
System.out.println("客户端连接成功!");
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
outToClient.writeBytes("你好,来自服务器的问候!\n");
serverSocket.close();
}
}
- TCP客户端(连接服务器并接收消息):
import java.io.*;
import java.net.*;
public class TCPClient {
public static void main(String[] args) throws IOException {
Socket clientSocket = new Socket("localhost", 6789);
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String message = inFromServer.readLine();
System.out.println("来自服务器的消息: " + message);
clientSocket.close();
}
}
3. UDP消息发送和接收示例:
- UDP发送端:
import java.io.*;
import java.net.*;
public class UDPSender {
public static void main(String args[]) throws Exception {
DatagramSocket clientSocket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getByName("localhost");
byte[] sendData = new byte[1024];
String sentence = "Hello from UDP client";
sendData = sentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9876);
clientSocket.send(sendPacket);
clientSocket.close();
}
}
- UDP接收端:
import java.io.*;
import java.net.*;
public class UDPReceiver {
public static void main(String args[]) throws Exception {
DatagramSocket serverSocket = new DatagramSocket(9876);
byte[] receiveData = new byte[1024];
while (true) {
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
String sentence = new String(receivePacket.getData());
System.out.println("接收到的数据: " + sentence);
}
}
}
结论:
理解网络基础和网络编程是开发现代网络应用的关键。通过了解不同的通信协议及其特点,以及实践基本的网络编程,你可以开始构建自己的网络应用并深入探索更复杂的网络技术。
13.1.2 TCP与UDP协议
在网络通信中,TCP和UDP是两个主要的传输层协议,它们定义了数据如何在网络中传输。
1. TCP (Transmission Control Protocol):
-
定义: TCP是一个面向连接的协议,它在数据传输前要求发送端和接收端建立一个稳定的连接。
-
特点:
- 可靠性: TCP提供可靠的通信传输,通过三次握手过程建立连接,保证了数据的准确无误。
- 顺序控制: TCP能保证数据包的顺序和完整性。
- 拥塞控制: TCP会根据网络状况自动调整数据发送速率。
-
用途: 适用于那些对数据准确性要求高的应用,如文件传输、电子邮件、网页浏览等。
-
三次握手过程:
- 客户端发送连接请求到服务器。
- 服务器接收连接并回送确认消息。
- 客户端接收确认并再次发送确认信息。
2. UDP (User Datagram Protocol):
-
定义: UDP是一个无连接的协议,它不需要在发送数据之前建立连接。
-
特点:
- 无连接: 数据发送和接收不需要建立连接,减少了开销和延迟。
- 高效: 由于没有复杂的控制机制,UDP的传输速度很快。
- 不可靠: 不保证数据的顺序和完整性,可能会丢包。
-
用途: 适用于对速度要求高但对可靠性要求不高的应用,如在线视频、游戏。
代码示例:
- TCP服务器端简单示例:
import java.io.*;
import java.net.*;
public class TCPServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(6789); // 创建服务器端Socket
System.out.println("等待客户端连接...");
Socket connectionSocket = serverSocket.accept(); // 等待客户端连接
System.out.println("客户端连接成功!");
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
outToClient.writeBytes("你好,来自服务器的问候!\n"); // 向客户端发送消息
serverSocket.close(); // 关闭连接
}
}
- UDP发送和接收示例:
- 发送端:
import java.io.*;
import java.net.*;
public class UDPSender {
public static void main(String args[]) throws Exception {
DatagramSocket clientSocket = new DatagramSocket(); // 创建UDP Socket
InetAddress IPAddress = InetAddress.getByName("localhost");
byte[] sendData = "Hello from UDP client".getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9876);
clientSocket.send(sendPacket); // 发送数据
clientSocket.close(); // 关闭Socket
}
}
- 接收端:
import java.io.*;
import java.net.*;
public class UDPReceiver {
public static void main(String args[]) throws Exception {
DatagramSocket serverSocket = new DatagramSocket(9876); // 创建UDP Socket
byte[] receiveData = new byte[1024];
while(true) {
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket); // 接收数据
String sentence = new String(receivePacket.getData());
System.out.println("接收到的数据: " + sentence);
}
}
}
结论:
选择TCP或UDP取决于你的应用需求。如果你需要可靠、顺序的数据传输,那么TCP是一个好选择。如果你需要快速、效率高的传输,而且可以容忍一些数据丢失,那么UDP可能更合适。
13.1.3 IP地址和端口号
在进行网络编程时,理解IP地址和端口号的概念至关重要,因为它们是网络通信的基础。
1. IP地址:
-
定义: IP地址是互联网上每台终端设备的唯一标识。它使得网络中的请求能够找到具体的计算机。
-
格式: IPv4地址由4个字节组成,通常表示为四个十进制数,每个数位于0到255之间,例如
192.168.0.1
。 -
分类:
- A类:
1.0.0.1
至126.255.255.254
- 大型网络。 - B类:
128.0.0.1
至191.255.255.254
- 中型网络。 - C类:
192.0.0.1
至223.255.255.254
- 小型网络。 - D类:
224.0.0.0
至239.255.255.255
- 多播地址。 - E类:
240.0.0.0
至255.255.255.255
- 未来使用。
- A类:
-
特殊地址:
127.0.0.1
通常被用作回环测试。 -
实用示例: 在Windows中,可以使用
ipconfig
命令查看本机的IP地址。
2. 端口号:
-
定义: 端口号是计算机上运行的特定服务的逻辑地址。就像一个大楼(计算机)有多个房间(服务),每个房间有自己的房间号(端口号)。
-
范围:
0
至65535
。其中,0
至1023
通常为系统或者众所周知的服务保留,如HTTP服务通常使用端口80
。 -
作用: 端口号使得一台计算机可以同时运行多个网络服务,并确保数据准确地发送到正确的服务。
13.1.4 InetAddress类
Java中的InetAddress
类是与IP地址相关的一个重要类,它提供了一系列方法来操作和获取IP地址信息。
InetAddress类的主要方法:
-
InetAddress getByName(String host)
:- 功能: 通过主机名获取对应的
InetAddress
实例。 - 应用场景: 当你知道主机名(如www.example.com)时,使用此方法可以获取其IP地址。
- 功能: 通过主机名获取对应的
-
InetAddress getByAddress(byte[] addr)
:- 功能: 通过字节数组形式的IP地址获取
InetAddress
实例。 - 应用场景: 当你有IP地址的字节表示时(比如从文件中读取),可以用此方法创建
InetAddress
对象。
- 功能: 通过字节数组形式的IP地址获取
-
InetAddress getLocalHost()
:- 功能: 获取表示本地主机的
InetAddress
实例。 - 应用场景: 当你想要获取当前计算机的IP地址时使用。
- 功能: 获取表示本地主机的
-
byte[] getAddress()
:- 功能: 获取
InetAddress
对象的IP地址,并将其存放在字节数组中。 - 应用场景: 当你需要以字节形式处理或存储IP地址时使用。
- 功能: 获取
-
String getHostAddress()
:- 功能: 获取字符串格式的IP地址。
- 应用场景: 当你需要以可读形式显示或记录IP地址时使用。
-
String getHostName()
:- 功能: 获取
InetAddress
对象对应的主机名。 - 应用场景: 当你从IP地址想要反查对应的主机名时使用。
- 功能: 获取
-
boolean isReachable(int timeout)
:- 功能: 测试是否可以在指定时间内到达该地址。
- 应用场景: 检测网络连接是否正常或主机是否在线时使用。
代码示例:
import java.net.InetAddress;
public class InetAddressExample {
public static void main(String[] args) {
try {
// 获取本地主机的InetAddress实例
InetAddress localAddress = InetAddress.getLocalHost();
System.out.println("本机的IP地址:" + localAddress.getHostAddress());
// 获取指定主机名的InetAddress实例
InetAddress remoteAddress = InetAddress.getByName("www.itcast.cn");
System.out.println("www.itcast.cn的IP地址:" + remoteAddress.getHostAddress());
// 检查是否可以在3秒内到达指定主机
boolean isReachable = remoteAddress.isReachable(3000);
System.out.println("3秒内是否可达www.itcast.cn:" + isReachable);
} catch (Exception e) {
e.printStackTrace();
}
}
}
结论:
InetAddress
类是处理网络编程中IP相关问题的关键类。它为我们提供了一系列方法来获取和检查IP地址。熟练掌握这个类的使用对于进行网络编程来说是非常重要的。
13.1.5 URL编程
URL简介:
- 定义: URL(Uniform Resource Locator)是互联网上某一资源的地址,用于定位互联网上的文档(如HTML文件)、图像、视频等资源。
- 结构: 一个典型的URL包含以下几部分:
- 传输协议: 如HTTP、FTP等。
- 主机名: 资源所在的计算机名称,可以是IP地址或域名。
- 端口号: 服务使用的端口号(可选,默认为80)。
- 文件名: 访问的文件名称,包括完整路径。
- 引用: 资源内部的某个参考点(可选)。
Java中的URL类:
Java提供了URL
类来处理网络上的资源。它是java.lang.Object
类的直接子类,用于表示URL并提供了一系列方法来操作它。
常用方法:
-
URL(String spec)
:- 功能: 根据String表示的URL创建一个URL对象。
- 用例:
URL url = new URL("http://www.example.com");
-
URL(String protocol, String host, int port, String file)
:- 功能: 创建一个URL对象,指定协议、主机名、端口号和文件名。
- 用例:
URL url = new URL("http", "www.example.com", 80, "/index.html");
-
URLConnection openConnection()
:- 功能: 打开到此URL的连接并返回一个URLConnection对象。
- 用例:
URLConnection urlConnection = url.openConnection();
-
InputStream openStream()
:- 功能: 打开到此URL的连接并返回用于读取此URL资源的InputStream。
- 用例:
InputStream input = url.openStream();
示例代码:
访问并打印指定URL的内容。
import java.io.InputStream;
import java.net.URL;
import java.util.Scanner;
public class Example02 {
public static void main(String[] args) throws Exception {
// 创建URL对象
URL url = new URL("http", "www.itcast.cn", 80, "/subject/uidszly/index.html");
// 打开URL的输入流
InputStream input = url.openStream();
Scanner scanner = new Scanner(input).useDelimiter("\n");
// 读取并打印URL内容
while (scanner.hasNext()) {
System.out.println(scanner.next());
}
}
}
结论:
通过理解URL的结构和Java中URL类的使用,我们可以方便地访问和处理互联网上的资源。掌握这些知识对于进行网络编程和开发基于互联网的应用至关重要。
-
IP地址:
- 每台互联网设备的唯一标识。
- IPv4使用4字节二进制数表示(32位长)。
- 常以点分十进制形式表示(如127.0.0.1)。
- 分为网络地址和主机地址两部分,用于区分互联网上的不同网络和设备。
-
工具命令:
ipconfig
:在Windows操作系统中使用,用于查看本机网络配置信息,包括IP地址。- 例如,在命令提示符(cmd)中输入
ipconfig
可以看到类似IPv4地址:172.16.48.173
的输出,显示了当前设备的IPv4地址。
- 例如,在命令提示符(cmd)中输入
ping
:网络工具命令用于测试主机之间网络连接的可达性。- 例如,使用
ping 127.0.0.1
可以测试本机的网络通信是否正常,这个地址是一个特殊的IP地址,被用于称为回环测试的网络测试。
- 例如,使用
- 在Windows命令行中运行
ipconfig
以获取网络配置信息,包括IP地址。 - 使用
ping
命令检测目标IP地址的连通性,例如ping www.example.com
。 - 分类:
- A类地址:1.0.0.1至126.255.255.254
- B类地址:128.0.0.1至191.255.255.254
- C类地址:192.0.0.1至223.255.255.254
- D类地址:224.0.0.0至239.255.255.255(多播使用)
- E类地址:240.0.0.0至255.255.255.255(实验和研究)
- 特殊地址127.X.X.X用于回环测试,常用127.0.0.1测试本机网络。
- 服务在主机上的唯一标识,与IP地址一起确定网络中的特定服务。
- 范围:0至65535,其中0至1023通常为系统保留。
- 常见端口:
- HTTP:80
- Telnet:21
- FTP:23
- 端口号避免冲突:选择大于1023的数值以避开系统服务。
- IP地址和端口号一起用于网络中的服务定位和数据交互。
- 如图13-5所示,源计算机通过IP地址和端口号与目标计算机上的特定服务通信。
- 避免将私有IP地址范围(如192.168.X.X)与公有IP地址混淆。
- 特别注意保留地址的使用场景,例如127.0.0.1通常用于本地测试。
- 当编写网络程序时,避免使用已知服务的标准端口,以防止端口冲突。
13.1.4 InetAddress
类:
-
InetAddress类简介:
- Java网络编程中用于封装IP地址的类。
- 提供了操作和查询IP地址的方法集。
- getByName(String host): 通过主机名获取其IP地址的
InetAddress
实例。 - getByAddress(byte[] addr): 通过IP地址的字节数组获取
InetAddress
实例。 - getLocalHost(): 获取代表本机的
InetAddress
实例。 - getAddress(): 返回封装在当前
InetAddress
实例中的IP地址的字节数组。 - getHostAddress(): 获取当前
InetAddress
实例的字符串形式的IP地址。 - getHostName(): 获取当前
InetAddress
实例的主机名。 - isReachable(int timeout): 测试是否可以在指定时间内到达该地址。
- 使用
getLocalHost()
获取本地主机IP。 - 使用
getByName()
查询特定主机名的IP地址。 - 使用
isReachable()
测试IP地址的可达性。 - 获取并打印本地主机IP地址。
- 查询
www.itcast.cn
的IP地址并打印。 - 检查
www.itcast.cn
的IP地址在3秒内是否可达。 - 显示了本地IP地址和
www.itcast.cn
的IP地址。 - 显示了可达性测试的结果,即
true
或false
。 - 正确处理
InetAddress
的异常,如未知主机异常。 - 理解
getByName()
可能会进行DNS查询,而getByAddress()
不会。 - 知道
isReachable()
方法可能受到本地防火墙和网络设置的影响。
13.1.5 URL编程:
-
URL概述:
- URL(统一资源定位器)是互联网上资源的地址。
- 包括HTML文件、图像、音频、视频等。
- 通过URL,浏览器或其他程序可以找到并访问这些资源。
- 传输协议: 访问资源使用的协议名,如HTTP、FTP。
- 主机名: 资源所在的计算机名称,可以是IP地址或域名。
- 端口号: 服务使用的端口,默认为协议标准端口(如HTTP为80)。
- 文件名/路径: 访问的资源路径,包括文件的完整路径。
- 引用: 资源内部的定位点,如文档内部的锚点。
java.net.URL
类提供了表示和操作URL的方法。- 直接子类于
java.lang.Object
。 URL(String spec)
: 根据字符串形式的URL创建URL对象。URL(String protocol, String host, int port, String file)
: 指定协议、主机、端口号和文件名创建URL对象。URLConnection openConnection()
: 打开到此URL的连接。InputStream openStream()
: 打开到此URL的连接并返回输入流。- 创建
URL
对象来访问www.itcast.cn
。 - 使用
openStream()
方法打开连接并读取内容。 - 使用
Scanner
读取并打印网站内容。 - 处理
MalformedURLException
,它在URL格式错误时抛出。 - 理解URL的不同部分,尤其是协议、主机和路径,因为它们决定了资源的位置。
- 注意安全性和性能问题,如HTTPS协议的使用和缓存策略。
案例分析:
Example01.java
:演示了如何使用InetAddress
类获取和检查IP地址。Example02.java
:演示了如何使用URL
类访问网络资源。
总结:
重点:
- TCP/IP网络模型: 理解TCP/IP网络模型的四个层次:链路层、网络层、传输层和应用层。每一层都有特定的功能和协议。
- TCP与UDP: 区分TCP(面向连接的协议)和UDP(无连接的协议)以及它们的应用场景。
- IP地址: 理解IP地址的作用和结构,包括如何通过IPv4地址识别网络中的设备。
- 端口号: 掌握端口号的概念及其在网络通信中的作用。
InetAddress
类: 学会使用Java中的InetAddress
类来管理和使用IP地址。- URL编程: 理解URL的结构和如何通过URL类在Java中访问网络资源。
难点:
- TCP/IP层次的理解: 对于初学者来说,理解每一层所负责的具体通信任务和它们如何相互作用可能比较困难。
- TCP三次握手过程: TCP连接建立的三次握手过程涉及到细节,理解这一过程对于新学者来说可能较为复杂。
- 网络编程概念: 网络编程涉及多个概念的整合应用,如Socket编程、多线程处理等。
易错点:
- 混淆TCP和UDP: 在描述TCP和UDP的特点时,容易混淆它们的特性,特别是在它们的用途和可靠性方面。
- IP地址分类: IPv4地址的分类(A、B、C、D、E类地址)可能会弄错,特别是在子网掩码和特殊地址用途(如127.0.0.1)的理解上。
- 端口号的使用: 在实际编程中,可能错误地使用了保留端口号,导致冲突。
InetAddress
类的方法应用: 在使用InetAddress
类时,可能会混淆其方法的用途,如getByName()
和getLocalHost()
的区别。- URL格式错误: 在编写和解析URL时,可能会忽略正确的格式,特别是忽视端口号和资源路径的正确书写。