Java之 网络编程
1. 网络编程概述
1.1 计算机网络:
分布在不同地域的计算机,通过硬件等网络设备使用通信线路互相连接形成的一个网格系统。
计算机网络,可以很方便的进行信息的传递,资源的共享!
1.2 计算机的IP地址:
- IP地址: 是计算机在互联网中的唯一标识,就像人在社会中的身份证号码。
- 内网IP、公网IP
- 本机IP: 127.0.0.1
- 本机域名: localhost
1.3 网络中网站的域名:
域名可以简单的理解为IP地址的别名。当输入域名后(例如www.baidu.com),计算机会访问域名解析商,然后得到ip地址,再进行访问。
1.4 计算机的端口号:
- 端口号的范围:0-65535 之间。
- 端口号的概念:与ip地址很相似,IP地址是计算机在网络中的唯一标识。端口号是计算机中程序的标识。用于在一台计算机中区分不同的应用程序。一个应用程序可以占用n个端口。
- 注意:端口号在使用时,应尽量避免0-1024之间的端口号,因为已经被一些知名的软件和 windows操作系统所占用了。
1.5 计算机之间的通信协议:
概念: 是计算机与计算机之间交流的标准。是对数据的传输速率、传入接口、步骤控制、出错控制等等制定的一套标准!通信双方必须同时遵守,最终完成数据交换。
常用的通信协议:
- http协议:超文本传输协议。80端口号
- https协议:安全的超文本传输协议。443端口号
- ftp协议:文件传输协议。21端口号
- TCP协议:传输控制协议
- UDP协议:用户数据报协议
TCP协议: 传输控制协议(Transmission Control Protocol)。TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端之间建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。
三次握手: TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠。
- 第一次握手:客户端向服务器发出连接请求,等待服务器确认。
- 第二次握手:服务器向客户端回送一个响应,通知客户端收到了连接请求。
- 第三次握手:客户端再次向服务器发送确认信息,确认连接。
完成三次握手,连接建立后,客户端和服务器就可以开始进行数据传输了。由于这种面向连接的特性,TCP协议可以保证传输数据的安全,所以应用十分广泛,例如下载文件、浏览网页等。
UDP协议: 用户数据报协议(User Datagram Protocol)。UDP协议是一个面向无连接的协议。传输数据时,不需要建立连接,不管对方端服务是否启动,直接将数据、数据源和目的地都封装在数据包中,直接发送。每个数据包的大小限制在64K以内。它是不可靠协议,因为无连接,所以传输速度快,但是容易丢失数据。日常应用中,例如视频会议、QQ聊天等。
网络编程程序的分类:
- B/S程序:浏览器与服务器程序
- C/S程序:客户端与服务器程序
TCP协议-OSI网络模型:
- TCP协议:指的是从一台计算机的软件中,将数据发送到另一台计算机的软件中的过程。
- 七层网络模型:应用层->层->会话层->传输层->网络层->数据链路层->物理
三次握手和四次挥手:
- 三次握手:tcp协议客户端与服务器连接时,在三次握手操作,保消息能准确无误的发送。
- 四次挥手:断开连接时,存在四次挥手操作。
2. TCP程序
TCP协议的C/S程序:
需要使用到两个类,来编写TCP协议的CS程序。
- 搭建服务器类:ServerSocket
- 搭建客户端类:Socket
套接字/通信端点: 两方使用socket
进行交流
3. ServerSocket搭建服务器类
概念: 用于创建服务器。创建完毕后,会绑定一个端口号。然后此服务器可以等待客户端连接。每连接一个客户端,服务器就会得到一个新的Socket对象,用于跟客户端进行通信。
常用构造方法:ServerSocket(int port);
创建一个基于TCP/IP协议的服务器,并绑定指定的端口号。
注意: 参数port的范围是: 0-65535 (建议1025-65535)
常用方法:
变量和类型 | 方法 | 描述 |
---|---|---|
Socket | accept(); | 等待客户端连接。此方法会导致线程的阻塞!直到一个新的客户端连接成功,return Socket套接字对象后,线程再继续执行。(即创建服务器,等待客户端连接,取得通信端点) |
Void | close(); | 释放占用的端口号,关闭服务器。 |
4. Socket搭建客户端类
概念: 是两台计算机之间通信的端点,是网络驱动提供给应用程序编程的一种接口、一套标准、一种机制。
常用构造方法:Socket(String ip,int port);
创建一个套接字,并连接指定ip和端口号的服务器。(即创建通信点,与服务器连接)
- 参数1:服务器的ip地址。
- 参数2:服务器软件的端口号。.
常用方法:
变量和类型 | 方法 | 描述 |
---|---|---|
OutputStream | getOutputStream(); | 返回的是,指向通信的另一端点的输出流。 |
InputStream | getInputStream(); | 返回的是,指向通信的另一端点的输入流。 |
void | close(); | 关闭套接字。 |
int | getPort() | 返回此套接字连接的远程端口号。 |
InetAddress | getInetAddress() | 返回套接字连接的地址。 |
boolean | isClosed() | 返回套接字的关闭状态。 |
boolean | isConnected() | 返回套接字的连接状态。 |
注意: 在网络编程时,获取输入输出流的操作,对于客户端与服务器来说是相对的。
客户端的输入流,输入的是服务器的输出流输出的内容。
客户端的输出流,输出到的是服务器的输入流中。
所以,客户端与服务器获取流的顺序必须是相反的。
例如: 客户端先得到了输入流,那服务器必须先获取输出流。
eg:
/**
* 服务器端
*/
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(55565);
//创建服务器,等待客户端连接,取得通信端点
Socket socket = serverSocket.accept();
//对客户端传数据
OutputStream out = socket.getOutputStream();
PrintStream ps = new PrintStream(out);
ps.println("你好客户端");
}
/**
* 客户端
*/
public static void main(String[] args) throws IOException {
//创建通信点,与服务器连接
Socket socket = new Socket("localhost",55565);
//从服务器接收数据
InputStream in = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String text = br.readLine();
System.out.println(text);
}
5. 在服务器中加入多线程
概念: 避免一个服务器接收多个客户端的时候,主线程因为需要时间处理与该客户端的数据交互而导致下一个客户端连接不上。
eg:
/**
* 服务器端连接多客户端出现问题
*/
public static void main(String[] args) throws IOException, InterruptedException {
ServerSocket serverSocket = new ServerSocket(55565);
//创建服务器,等待客户端连接,取得通信端点
while (true){
Socket socket = serverSocket.accept();
//假设中间处理需要时间时,while循环被阻塞,此时另一个客户端进行连接就会导致连接不上
Thread.sleep(6000);
}
}
/**
* 服务器端使用多线程连接多客户端
*/
public static void main(String[] args) throws IOException, InterruptedException {
ServerSocket serverSocket = new ServerSocket(55565);
//创建服务器,等待客户端连接,取得通信端点
while (true){
Socket socket = serverSocket.accept();
//此时创建一个线程对这个客户端进行处理,while循环继续,不影响其他客户端连接
new Thread(){
@Override
public void run() {
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
}
6. InetAddress描述IP地址的类
概念: InetAddress这个类的对象,用于描述IP。某些类或接口传入IP地址的参数格式要求为InetAddress对象类型。
得到InetAddress对象的方式:
InetAddress ip = InetAddress.getByName("192.168.102.228");
注意:
- 在TCP协议中,通过套接字Socket的getInetAddress方法,可以得到套接字连接的ip地址。
- 在UDP协议中,通过数据包DatagramPacket的getAddress方法,可以得到数据包来自哪个ip。
常用方法:
变量和类型 | 方法 | 描述 |
---|---|---|
String | getHostAddress() | 获取ip地址字符串 |
String | getHostName() | 计算机名称,当名称无法获取时,获取的为ip地址。 |
7. UDP协议(了解)
概念: 用户数据报协议,与tcp协议不同,UDP的连接是不可信的。数据发送的成功与失败 与数据报是无关的。
7.1 DatagramSocket数据报套接字类
概念: 用于发送与接收数据包的Socket。
构造方法:DatagramSocket(int port);
参数:端口号
常用方法:
变量和类型 | 方法 | 描述 |
---|---|---|
void | close() | 关闭套接字。 |
void | send(DatagramPacket dp) | 将一个数据包dp发送出去。 |
void | receive(DatagramPacket dp) | 接收一个数据包并存储到参数dp中。 |
7.2 DatagramPacket数据包类
概念: 用于发送或接收数据时,盛放数据的对象!
构造方法:
(1)用于发送数据时,组装数据:DatagramPacket(byte[] bytes,int startIndex,int len,InetAddress ip,int port);
- 参数1. 要发送的数据,是字节数组的形式
- 参数2. 有效数据在数组中的起始位置
- 参数3. 有效数据在数组中的长度
- 参数4. 当前这个数据包,准备发送到的IP地址,InetAddress这个类的对象,用于描述IP。
- 参数5. 当前这个数据包,准备发送到目标计算机的哪个端口号。
(2)用于接收数据时,存储数据:DatagramPacket(byte[] bytes,int len)
- 参数1. 用于存储数据的数组
- 参数2. 允许存储的最大长度
常用方法:
变量和类型 | 方法 | 描述 |
---|---|---|
byte[] | getData() | 用于获取数据包中的有效字节数组 |
int | getLength | 用于获取数据包中的有效数据的长度. |
8. URL(了解)
HTTP协议概念:
HyperText Transfer Protocol 超文本传输协议,是TCP/IP协议集中的协议,是一个简单的请求-响应协议,指定了客户端发送给服务器的消息以及服务器的响应。所有的WWW文件都必须遵守这个标准。
URL概念:
URL是统一资源定位符(Uniform Resource Locator)的简称,它表示Internet上某一资源的地址。通过URL用户可以访问各种网络资源,比如常见的WWW以及FTP站点。浏览器可以通过解析给定的URL在网络上查找相应的文件或其他资源。
URL语法格式:
protocol://resourceName
协议名(protocol)指明获取资源所使用的传输协议,如 HTTP、FTP 和 file 等,资源名(resourceName)则 应该是资源的完整地址,包括主机名、端口号、文件名或文件内部的一个引用。下面是一些简单的URL示例
http://www.sun.com/ 协议名://主机名
http://localhost:8080/Test/admin/login.jsp 协议名://机器名:端口号/文件名
8.1 URL类
概念: 在java.net包中包含专门用来处理URL的类 URL,可以获得URL的相关信息,例如URL的协议名和主机名等。
常用构造方法: URL url = new URL(String urlString)
使用基本地址和相对URL构造一个URL对象。urlString为地址。
常用方法:
变量和类型 | 方法 | 描述 |
---|---|---|
String | getFile() | 获取该URL的路径+文件名 |
URLConnection | openConnection() | 打开链接,并得到链接对象 |
8.2 URLConnection类
概念: 获得URL的通信连接。在java.net包中,定义了专门的URLConnection类来表示与URL 建立的通信连接,URLConnection类的对象使用URL类的openConnection()方法获得。
常用方法:
变量和类型 | 方法 | 描述 |
---|---|---|
long | getContentLengthLong() | 获取网址指向文件的大小 |
void | setDoInput(boolean input) | URL 连接可用于输入和/或输出。如果打算使用 URL 连接进行输入,则将 DoInput 标志设置 为 true;如果不打算使用,则设置为 false。默认值为 true。 |
void | setDoOutput(boolean output) | URL 连接可用于输入和/或输出。如果打算使用 URL 连接进行输出,则将 DoOutput 标志设置 为 true;如果不打算使用,则设置为 false。默认值为 false |
0 | setRequestProperty(String key,String value) | 设置由键值对指定的常规请求属性。如果具有密钥的属性已存在,则旧值将被新值覆盖。 |
InputStream | getInputStream() | 返回 URL 的输入流,用于读取资源 |
OutputStream | getOutputStream() | 返回 URL 的输出流, 用于写入资源 |
int | getContentLength() | 返回头部 content-length 字段 |
0 | getResponseCode() | 返回服务器发送的 HTTP 状态码 |
0 | close() | 关闭连接 |
8.3 HTTPURLConnection类
概念: 如果URL中使用的网络协议为HTTP协议或HTTPS协议,就可以将URLConnection类型强制转换为 HttpURLConnection。
变量和类型 | 方法 | 描述 |
---|---|---|
0 | setRequestMethod(String method) | 设置 URL 请求的方法,它是 HTTP 方法 GET,POST,HEAD,OPTIONS,PUT,DELETE 和 TRACE 之一。默认方法是 GET(注意:这里方法类型必须大写)。 |
eg(获取文件名):
URL url = new URL("网址");
String name = url.getFile();
//获取文件路径+名称, 并从最后一个/开始截取, 截取到结尾
name = name.substring(name.lastIndexOf("/")+1,name.length())
8.4 URL编码
概念: 在java开发中,有时候需要将中文进行转码,保证传输的时候不出现乱码;最常用的方式是URLEncode与URLDecod。
URLEncode:
将普通字符串转换成 application/x-www-from-urlencoded 字符
eg:
//字符串中的非西欧字符的内容,会被转化成%XX%XX XX 为十六进制的数字
String urlString = URLEncoder.encode("你好", "UTF-8");
System.out.println(urlString);//输出:%E4%BD%A0%E5%A5%BD
URLDecode
将 application/x-www-from-urlencoded 字符串转换成普通字符串
eg:
String keyWord = URLDecoder.decode("%E4%BD%A0%E5%A5%BD", "UTF-8");
System.out.println(keyWord);//输出:你好