1. 概述
计算机网络:计算机网络是指将==地理位置不同的具有独立功能的多台计算机及其外部设备==,通过通信线路连接起来,在网络操作系统,网络管理软件及==网络通信协议==的管理和协调下,实现资源共享和信息传递的计算机系统。
网络编程的目的:无线电台,传播交流信息,数据交换,通信。
- javaweb:网页编程 B/S (Browser/Server)
- 网络编程:TCP/IP C/S (Client/Server)
2. 网络通信的要素
网络通信的要素
-
通信双方地址:
- ip:互联网协议地址(Internet Protocol Access)
- port:端口号
-
网络通信协议:
- TCP,UDP
TCP/IP 参考模型(也叫OSI七层模型):
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PIV42Y1v-1613961352614)(…/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/OSI%E8%AF%A6%E8%A7%A32.png)]
3. IP
ip在java中位置:java.net.InetAddress
-
ip用于定位一台计算机(唯一地址)
-
127.0.0.1:本机地址
-
ip地址分类
-
ipv4/ipv6(internet protocol version 4/6)
- ipv4,eg:127.0.0.1,总长度为32bit(4Byte),分为4组,每组为一个0~255的数,每组用冒汗分隔,共43亿个;30亿在北美,亚洲只有4亿个,2011年用尽
- ipv6,eg:fe80::2912:6519:9f57:3c64%2,总长度为128bit(16Byte),分为8组,每组为4个十六进制数,每组十六进制数间用冒号分隔,拥有(43亿×43亿×43亿×43亿)个地址
- 在某些情况下,一个IPv6地址中间可能包含很长的一段0,可以把连续的一段0压缩为“::”。但为保证地址解析的唯一性,地址中”::”只能出现一次,例如:
FF01:0:0:0:0:0:0:1101 → FF01::1101
0:0:0:0:0:0:0:1 → ::1
0:0:0:0:0:0:0:0 → ::
-
公网(互联网)- 私网(局域网)
- ABCDE类地址
-
域名(Domain Name)
-
public class TestInetAddress {
public static void main(String[] args) {
try {
// 获取本地的ip地址
InetAddress localAddress1 = InetAddress.getByName("127.0.0.1");
System.out.println(localAddress1);
// 获取本地的ip地址
InetAddress localAddress2 = InetAddress.getByName("localhost");
System.out.println(localAddress2);
// 获取本地的ip地址
InetAddress localAddress3 = InetAddress.getLocalHost();
System.out.println(localAddress3);
// 获取百度的ip地址
InetAddress baiduAddress = InetAddress.getByName("www.baidu.com");
System.out.println(baiduAddress);
// 常用方法
// 返回该对象的Byte类型的 InetAddress原IP地址
System.out.println(baiduAddress.getAddress());
// 返回String类型的 IP地址
System.out.println(baiduAddress.getHostAddress());
// 返回此IP地址的 完全限定的域名
System.out.println(baiduAddress.getCanonicalHostName());
// 返回此IP地址的 主机名
System.out.println(baiduAddress.getHostName());
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
4. Port
-
端口(Port):一般是指TCP/IP协议中的端口,
-
端口分为两种,一种是TCP端口,一种是UDP端口。计算机之间相互通信的时候,分为两种方式:一种是发送信息以后,可以确认信息是否到达,也就是有应答的方式,这种方式大多采用TCP协议;一种是发送以后就不管了,不去确认信息是否到达,这种方式大多采用UDP协议。对应这两种协议的服务提供的端口,也就分为TCP端口和UDP端口。
-
端口号的范围从0到65535,TCP端口有65536个,UDP端口也有65536个,单个协议下,端口号不能冲突
-
端口分类
-
公用端口:0~1023
- FTP:21
- Telnet:23
- HTTP:80
- HTTPS:443
-
程序注册端口:1024~49151,分配用户or程序
- Oracle:1521
- MySQL:3306
- Tomcat:8080
-
动态、私有:49152~65535
netstat -ano # 查看所有端口 netstat -ano|findstr "443" # 查看指定端口号(443) tasklist|findstr "12252" # 查看指定端口进程(12252)
-
InetSocketAddress
-
public static void main(String[] args) {
InetSocketAddress localSocketAddress1 = new InetSocketAddress("127.0.0.1", 8080);
System.out.println(localSocketAddress1);
InetSocketAddress localSocketAddress2 = new InetSocketAddress("localhost", 8080);
System.out.println(localSocketAddress2);
// 获得InetAddress
System.out.println(localSocketAddress1.getAddress());
// 获得hostname(主机名)
System.out.println(localSocketAddress1.getHostName());
// 获得hostname(主机名),和上面效果一样
System.out.println(localSocketAddress1.getHostString());
// 获得端口号
System.out.println(localSocketAddress1.getPort());
}
-
修改host
- host文件地址:C:\Windows\System32\drivers\etc\hosts
- host右键属性->去掉只读上的点
- 打开修改
5. 通信协议
5.1 TCP与UDP的区别
5.1.1 TCP:打电话
-
连接,稳定,传输完成,释放连接,效率低
-
三次握手
(three-way handshake):至少需要三次,保证稳定连接A:你愁啥? B:瞅你咋地? A:干一场!
-
四次挥手
(four-way wavehand)A:我要走了! B:你真的要走了吗? B:你真的真的要走了吗? A:我真的真的要走了!
先简单了解,到时候看书
-
分为客户端与服务端
5.1.2 UDP:发短信
- 不连接,不稳定,不管有没有准备好,都可以发给你
- 客户端、服务端:没有明确的界限
- DDoS:洪水攻击!(饱和攻击)
5.2 TCP发送消息
-
服务器端:
-
创建服务器端口 new ServerSocket()
ServerSocket serverSocket = new ServerSocket(9999);
-
阻塞式监听,会一直等待客户端连接 serverSocket.accept()
Socket socket = serverSocket.accept();
-
读取客户端消息 socket.getInputStream()
InputStream is = socket.getInputStream();
-
解析socket数据
ByteArrayOutputStream baoStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while((len = is.read(buffer)) != -1) { baoStream.write(buffer, 0, len); } System.out.println(baoStream.toString());
-
public class TcpServerDemo01 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream baoStream = null;
try {
// 1、创建服务器端口
serverSocket = new ServerSocket(9999);
while (true) {
// 2、等待客户端连接
socket = serverSocket.accept();
// 3、读取客户端的消息
is = socket.getInputStream();
// 字节数组流
baoStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while((len = is.read(buffer)) != -1) {
baoStream.write(buffer, 0, len);
}
System.out.println(baoStream.toString());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭资源
if (baoStream != null) {
try {
baoStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
-
客户端
-
创建服务器IP地址,端口号
serverIP = InetAddress.getByName("127.0.0.1"); int port = 9999;
-
创建socket连接
Socket socket = new Socket(serverIP, port);
-
发送消息
OutputStream os = socket.getOutputStream(); os.write("自由啊 自由啊!".getBytes(StandardCharsets.UTF_8));
-
public class TcpClientDemo01 {
public static void main(String[] args) {
InetAddress serverIP =null;
Socket socket = null;
OutputStream os = null;
try {
// 1、创建服务器IP地址,端口号
serverIP = InetAddress.getByName("127.0.0.1");
int port = 9999;
// 2、创建一个socket连接
socket = new Socket(serverIP, port);
// 3、发送消息 IO流
os = socket.getOutputStream();
os.write("自由啊 自由啊!".getBytes(StandardCharsets.UTF_8));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
5.3 TCP发送文件
- 客户端:
public class TcpClientDemo02 {
public static void main(String[] args) throws IOException {
// 1、创建Socket
Socket socket = new Socket(InetAddress.getByName("localhost"), 9090);
// 2、创建OutputStream
OutputStream os = socket.getOutputStream();
// 3、创建FileInputStream
FileInputStream fis = new FileInputStream(new File("19伦.jpg"));
// 4、写入文件
byte[] buffer = new byte[1024];
int len = 0;
while ((len = fis.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
// 关闭输出,开始输入
socket.shutdownOutput();
// 确定服务器接受完毕
InputStream is = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer2 = new byte[1024];
int len2 = 0;
while((len = is.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
System.out.println(baos.toString());
// 5、关闭资源
fis.close();
os.close();
socket.close();
}
}
- 服务器端
public class TcpServerDemo02 {
public static void main(String[] args) throws IOException {
// 1、创建ServerSocket
ServerSocket serverSocket = new ServerSocket(9090);
// 2、创建socket
Socket socket = serverSocket.accept();
// 3、创建getInputStream
InputStream is = socket.getInputStream();
// 4、创建FileOutputStream
FileOutputStream fos = new FileOutputStream(new File("收到19伦.jpg"));
// 5、解析数据
byte[] buffer = new byte[1024];
int len = 0;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
// 通知客户端接收完毕
OutputStream os = socket.getOutputStream();
os.write("自由啊 自由啊!".getBytes(StandardCharsets.UTF_8));
// 6、关闭资源
fos.close();
is.close();
socket.close();
serverSocket.close();
}
}
5.4 TCP模板
// 客户端
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);
OutputStream os = socket.getOutputStream();
os.write("自由啊 自由啊!".getBytes(StandardCharsets.UTF_8));
// 服务器端
ServerSocket serverSocket = new ServerSocket(9090);
Socket socket = serverSocket.accept();
InputStream is = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while((len = is.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
System.out.println(baos.toString());
发送文件见5.3节
5.5 Tomcat
服务器
- 自定义 Server
- Tomcat Server
客户端
-
自定义 Client
-
浏览器 Browser
Tomcat打开方式:
-
进入E:\EssentialSoftware\Apache-Tomcat-9.0.43\bin
-
打开startup.bat
-
浏览器打开http://localhost:8080/即可
5.6 UDP发送消息
客户端:
public class UdpClientDemo01 {
public static void main(String[] args) throws IOException {
// 1、数据报socket
DatagramSocket socket = new DatagramSocket();
// 2、新建packet(包)
String msg = "你好啊????????????";
InetAddress localhost = InetAddress.getByName("localhost");
int port = 9000;
DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.length(),
localhost, port);
// 3、发送packet
socket.send(packet);
// 4、关闭socket
socket.close();
}
}
服务器端:
public class UdpServerDemo01 {
public static void main(String[] args) throws IOException {
// 1、数据报socket
DatagramSocket socket = new DatagramSocket(9000);
// 2、新建packet(用于接收数据)
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
// 3、阻塞接收packet
socket.receive(packet);
System.out.println(packet.getAddress());
System.out.println(packet.getAddress().getHostAddress());
System.out.println(new String(packet.getData(), 0, packet.getLength()));
// 4、关闭socket
socket.close();
}
}
5.7 UDP实现聊天
发送方:
public class UdpSender {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket();
// 键盘输入
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String sendData = reader.readLine();
byte[] sendDatas = sendData.getBytes();
DatagramPacket packet = new DatagramPacket(sendDatas, 0, sendDatas.length,
new InetSocketAddress("localhost", 8888));
socket.send(packet);
if (sendDatas.equals("exit")) {
break;
}
}
socket.close();
}
}
接收方:
public class UdpReceiver {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(8888);
while (true) {
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
socket.receive(packet);
String receiveData = new String(packet.getData());
System.out.println(receiveData);
if (receiveData.equals("exit")) {
break;
}
}
socket.close();
}
}
5.8 UDP多线程在线咨询
public class UdpTalkSend implements Runnable{
DatagramSocket socket = null;
BufferedReader reader = null;
private int fromPort;
private int toPort;
private String toIP;
public UdpTalkSend(int fromPort, int toPort, String toIP) {
this.fromPort = fromPort;
this.toPort = toPort;
this.toIP = toIP;
try {
socket = new DatagramSocket(this.fromPort);
reader = new BufferedReader(new InputStreamReader(System.in));
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
try {
String sendData = reader.readLine();
byte[] sendDatas = sendData.getBytes();
DatagramPacket packet = new DatagramPacket(sendDatas, 0, sendDatas.length,
new InetSocketAddress(this.toIP, this.toPort));
socket.send(packet);
if (sendData.equals("exit")) {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}
public class UdpTalkReceive implements Runnable{
DatagramSocket socket = null;
private String msgFrom;
private int port;
public UdpTalkReceive(String msgFrom, int port){
this.msgFrom = msgFrom;
this.port = port;
try {
socket = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
try {
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
socket.receive(packet);
String receiveData = new String(packet.getData());
System.out.println(msgFrom + ":" + receiveData);
if (receiveData.equals("exit")) {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}
学生端:
public class UdpTalkStudent {
public static void main(String[] args) {
new Thread(new UdpTalkSend(7777, 9999, "localhost")).start();
new Thread(new UdpTalkReceive("teacher", 8888)).start();
}
}
老师端:
public class UdpTalkTeacher {
public static void main(String[] args) {
new Thread(new UdpTalkSend(5555, 8888, "localhost")).start();
new Thread(new UdpTalkReceive("student", 9999)).start();
}
}
5.9 UDP模板
// 发送方
DatagramSocket socket = new DatagramSocket();
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String sendData = reader.readLine();
byte[] sendDatas = sendData.getBytes();
DatagramPacket packet = new DatagramPacket(sendDatas, 0, sendDatas.length,
new InetSocketAddress("localhost", 8888));
socket.send(packet);
if (sendDatas.equals("exit")) {
break;
}
}
socket.close();
// 接收方
DatagramSocket socket = new DatagramSocket(8888);
while (true) {
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
socket.receive(packet);
String receiveData = new String(packet.getData());
System.out.println(receiveData);
if (receiveData.equals("exit")) {
break;
}
}
socket.close();
6. URL
URL:Uniform Resource Locator (统一资源定位符),用于定位互联网上的某一个资源,每一个资源都有URL。
6.1 URL网址
http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument
protocol 😕/ hostname[:port] / path / [;parameters][?query]#fragment
http
是协议。它表明了浏览器必须使用何种协议。它通常都是HTTP协议或是HTTP协议的安全版,即HTTPS。Web需要它们二者之一,但浏览器也知道如何处理其他协议,比如mailto
:(打开邮件客户端)或者 ftp
:(处理文件传输),所以当你看到这些协议时,不必惊讶。
www.example.com
是域名。 它表明正在请求哪个Web服务器。或者,可以直接使用IP address, 但是因为它不太方便,所以它不经常在网络上使用。.
:80
是端口。 它表示用于访问Web服务器上的资源的技术“门”。如果Web服务器使用HTTP协议的标准端口(HTTP为80,HTTPS为443)来授予其资源的访问权限,则通常会被忽略。否则是强制性的。
/path/to/myfile.html
是网络服务器上资源的路径。在Web的早期阶段,像这样的路径表示Web服务器上的物理文件位置。如今,它主要是由没有任何物理现实的Web服务器处理的抽象。
?key1=value1&key2=value2
是提供给网络服务器的额外参数。 这些参数是用 &
符号分隔的键/值对列表。在返回资源之前,Web服务器可以使用这些参数来执行额外的操作。每个Web服务器都有自己关于参数的规则,唯一可靠的方式来知道特定Web服务器是否处理参数是通过询问Web服务器所有者。
#SomewhereInTheDocument
是资源本身的另一部分的锚点. 锚点表示资源中的一种“书签”,给浏览器显示位于该“加书签”位置的内容的方向。例如,在HTML文档上,浏览器将滚动到定义锚点的位置;在视频或音频文档上,浏览器将尝试转到锚代表的时间。值得注意的是,#后面的部分(也称为片段标识符(fragment))从来没有发送到请求的服务器。
6.2 URL下载网络文件
进入Tomcat下载地址
在/webapps/yifang下新建文件helloworld
打开Tomcat
public class URLDownloadFile {
public static void main(String[] args) throws IOException {
// 1、下载地址
URL url = new URL("http://localhost:8080/yifang/helloworld");
// 2、连接资源 Http
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
InputStream is = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("helloworld.txt");
byte[] buffer = new byte[1024];
int len = 0;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
// 3、关闭资源
fos.close();
is.close();
urlConnection.disconnect();
}
}