Java基础-网络编程-全章详解
网络编程
1.1、概述
现在的世界,可以实现你在家里(海口)发送一个消息,很短的时间内,在印度的阿老师们就能够收到。这就是一个常见的网络使用的例子。
地球村的概念提出,更加完美的诠释了网络的效应。
在上世纪,最常用的通讯方式,还是信件。以下是信件的简式结构:

计算机网络:
计算机网络是指将**地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来**,在网络操作系统,网络管理软件及**网络通信协议**的管理和协调下,实现资源共享和信息传递的计算机系统。
网络编程的目的:
类比于无线电台,用于进行传播交流信息。进行数据交换,通信。
需要达到的效果,成果是什么:
1.如何准确定位网络上的一台主机?
- 通过端口号来进行。Eg:192.167.7.7
2.找到了主机,如何进行数据传递?
- ……
1.2、网络通信要素
随便举个例子,人工智能中的智能汽车。
目前适用于工程,码头等人少的地方,少数地方在尝试上路。由于伦理道德问题,难以大规模上路。网络通信的内容是很复杂,繁多的。
怎样实现网络通信?
通信双方的地址:
-
IP
-
端口
-
局域网地址等……
规则?网络通信协议
以TCP/IP协议为例:

我们重点学习传输层(TCP,UDP协议),以其为主题,进行讲解。
小结:
1.网络编程中有两个主要问题:
- 如何准确的定位到网络上的一台或多台主机。
打开CMD,直接输入“ping + 目标网址”进行地址跳跃查询。

- 找到主机后如何进行通信。
2.网络编程中的要素:
-
IP和端口号。
-
网络通信协议。
3.Java中万物皆对象,使用何种对象进行信息传输?
1.3、IP地址
Java中如何进行IP地址的获取?
使用“InetAddress”关键词。
-
IP的作用:唯一定位一台网络上的计算机。
-
特殊IP地址的记忆:127.0.0.1:本机地址,又称为localhost。
-
IP地址的分类:
一、IPV4/IPV6
1.IPV4:127.0.0.1,由4个字节居中,每个字节的大小为0到255,约有42亿个地址。其中约有30亿在北美,4亿在亚洲。在2011年地址已用尽。
2.IPV6:fe70::5477:2017:d5ac:7958%7,由128位,8个无符号整数组成。具有更多的地址数,可满足地球上每一粒沙子分配一个地址。
二、公网(互联网)/私网(局域网)
1.ABCD类地址:

2.192.168.XX.XX,等,专供某些组织使用。
- 域名:方便记忆的IP地址问题。
在阿里云上可以搜查你感兴趣的IP地址的价格。
代码测试:
package com.edwin.lesson1;
import java.net.InetAddress;
import java.net.UnknownHostException;
/*** @author EdwinD* @create 2020.08.20 下午 01:24* @desc 测试Ip地址。**/
public class TextInetAddress {public static void main(String[] args) {try {
// 查询本机地址
// 方法一:InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");System.out.println(inetAddress1);
// 方法二:InetAddress inetAddress2 = InetAddress.getByName("localhost");System.out.println(inetAddress2);
// 方法三:InetAddress inetAddress3 = InetAddress.getLocalHost();System.out.println(inetAddress3);// 查询百度的地址InetAddress inetAddress4 = InetAddress.getByName("www.baidu.com");System.out.println(inetAddress4);// 常用的方法System.out.println(inetAddress4.getAddress());System.out.println(inetAddress4.getCanonicalHostName());//规范的名字System.out.println(inetAddress4.getHostAddress());//IPSystem.out.println(inetAddress4.getHostName());//域名,或者自己电脑的名字} catch (UnknownHostException e) {e.printStackTrace();}}
}
输出效果:

1.4、端口
端口表示计算机上的一个程序的进程。
IP和端口号好比一个大楼和里面一个个房间。
-
不同的进程有不同的端口号。用来区分软件。
-
范围规定:0—65535。
-
分为TCP和UDP两个,都是65535个。两个协议下,端口号不能够重复。
-
端口分类:
1.共有端口:0—1023
-
HTTP:80
-
HTTPS:443
-
FTP:21
-
Telent:23
2.程序注册端口:1024—49151,用于分配给用于或者程序。
-
Tomcat:8080
-
Mysql:3306
-
Oracle:1521
3.动态、私有:49152—65535
netstat -ano;#查看所有的端口

netstat -ano|findstr "XXXX";#查看指定的XXXX端口号

tasklist|findstr "XXXX";#查找某个端口的进程

代码:
package com.edwin.lesson1;import java.net.InetSocketAddress;/*** @author EdwinD* @create 2020.08.20 下午 03:11* @desc 套接字**/
public class TestInetSocketAddress {public static void main(String[] args) {InetSocketAddress socketAddress1 = new InetSocketAddress("127.0.0.1", 8080);System.out.println(socketAddress1);InetSocketAddress socketAddress2 = new InetSocketAddress("localhost", 8080);System.out.println(socketAddress2);System.out.println(socketAddress1.getAddress());System.out.println(socketAddress1.getHostName());System.out.println(socketAddress1.getPort() );}
}
输出:

运行原理:

1.5、通信协议
所谓协议,就是一些约定,用于大家一起更好地使用一些东西。就比如中国人的官方语言是普通话。
**网络通信协议:**针对网络的一些规定。一些特殊单位:速率,传输码率,代码结构,传输控制等……
但是这些协议错综复杂,十分难顶。
因此,有了一个“大事化小”的方法:分层。
这其中,最重要的协议是:TCP/IP协议簇

其中重要的:
-
TCP:用户传输协议
-
UDP:用户数据报协议
其中出名的协议:
-
TCP:
-
IP:网络连接协议
TCP和UDP对比
1.TCP:
-
建立连接,稳定。
-
“三次握手”连接和“四次挥手”断开。
//三次握手:至少进行3次,才能保障连接。
A:你愁啥?
B:瞅你咋地?
A:干你丫的!
三次握手:

//四次挥手:至少进行4此,才能保障断开。
A:我要走了。
B:你真的要走了吗?
B:你真的真的要走了吗?
A:我真的真的要走了。
四次挥手:

- 客户端、服务端界限明朗。
2.UDP:
-
不连接,不稳定。
-
客户端、服务端的界限不明朗。
-
不论对方是否准备好,都可以给对方发消息。
-
DDOS:洪水攻击,一次性发送大量的数据,进行饱和攻击。
1.6、TCP
传输中添加通道的原理:

从一端来的输入,可能无法被另外一边的理解,添加了这个通道,就相当于进行了一次翻译,让两边都能理解。
1、文字传输
客户端
1.连接服务器—>Socket
2.发送消息
3.代码:
package com.edwin.lesson2;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
/*** @author EdwinD* @create 2020.08.20 下午 05:07* @desc 客户端1**/
public class TcpClient1 {public static void main(String[] args) {Socket socket = null;OutputStream os = null;try {// 1.需要知道服务器的地址InetAddress serverIP = InetAddress.getByName("127.0.0.1");// 2.设置连接端口号int port = 7777;// 3.创建一个socket,进行连接。Socket是有参数的,默认无参数socket = new Socket(serverIP, port);// 4.发送消息:IO流os = socket.getOutputStream();os.write("Welcome,EdwinD is Learning Web".getBytes());} catch (Exception 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();}}}}
}
服务器
1.建立服务的端口—>ServerSocket
2.等待用户的连接—>Accept
3.代码:
package com.edwin.lesson2;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/*** @author EdwinD* @create 2020.08.20 下午 05:08* @desc 服务端1**/
public class TcpServer1 {public static void main(String[] args) {ServerSocket serverSocket = null;Socket socket = null;InputStream is = null;ByteArrayOutputStream baos = null;try {// 提供服务器的地址:serverSocket,套接字。// 1.我有一个地址serverSocket = new ServerSocket(7777);while (true) {// 2.等待客户链接过来,这里的socket等同于TcpClient1里面的socket,socket = serverSocket.accept();// 3.读取客户端is = socket.getInputStream();/*byte[] buffer = new byte[1024];int len;while((len = is.read(buffer))! = -1){String msg = new String(buffer,0,len);System.out.println(msg);}*/baos = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len;while ((len = is.read(buffer)) != -1) {baos.write(buffer, 0, len);}System.out.println(baos.toString());}} catch (IOException e) {e.printStackTrace();}finally {
// 关闭资源if (baos != null) {try {baos.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();}}}}
}
输出:

2、文件上传
同样分为客户端和服务端。
客户:
package com.edwin.lesson2;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
/*** @author EdwinD* @create 2020.08.20 下午 06:06* @desc 客户端2**/
public class TcpClient2 {public static void main(String[] args) throws IOException {
// 1.创建一个Socket连接
// 注意port不可以和Client1的重合,否则会报错。Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 7788);
// 2.创建一个输出流OutputStream os = socket.getOutputStream();
// 3.文件流FileInputStream fils = new FileInputStream(new File("Study.jpg"));
// 4.写出文件byte[] buffer = new byte[1024];int len;while ((len = fils.read(buffer)) != -1) {os.write(buffer, 0, len);}// 通知服务器,已经结束了socket.shutdownInput();// 确定接受完毕,才能断开连接InputStream inputStream = socket.getInputStream();// 接受的是String类型的数组,ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] buffer2 = new byte[1024];int len2;while ((len2 = inputStream.read(buffer2)) != -1) {baos.write(buffer2, 0, len2);}System.out.println(baos.toString());// 5.关闭资源baos.close();inputStream.close();fils.close();os.close();socket.close();}
}
服务:
package com.edwin.lesson2;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/*** @author EdwinD* @create 2020.08.20 下午 06:14* @desc 服务端2**/
public class TcpServer2 {public static void main(String[] args) throws IOException {
// 1.创建服务ServerSocket serverSocket = new ServerSocket(7788);
// 2.监听客户端的连接Socket socket = serverSocket.accept();//阻塞式监听,会一直等待客户端连接,一旦链接,就失败了。
// 3.得到输入流InputStream is = socket.getInputStream();
// 4.文件输出FileOutputStream receive = new FileOutputStream(new File("receive.jpg"));byte[] buffer = new byte[1024];int len;while ((len = is.read(buffer)) != -1) {receive.write(buffer, 0, len);}// 通知客户端,接收完成OutputStream os = socket.getOutputStream();os.write("接受完毕,可以断开。".getBytes());// 5.关闭资源receive.close();is.close();socket.close();serverSocket.close();}
}
输出:

1.7、Tomcat
上两个例子,我们的客户端和服务端,均由自定义写出来的。
服务器:
-
自定义
-
使用Tomcat
客户端:
-
自定义
-
浏览器
1.8、UDP
类比发短信,不需要进行连接,但是需要知道对方的地址。
1.发送消息
发送端:
package com.edwin.lesson3;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
/*** @author EdwinD* @create 2020.08.20 下午 08:48* @desc 客户端1,不需要连接服务器**/
public class UdpClient1 {public static void main(String[] args) throws Exception {
// 1.建立一个SocketDatagramSocket socket = new DatagramSocket();// 2.建一个包String msg = "Hello,服务器。";// 发送给谁InetAddress localhost = InetAddress.getByName("localhost");int port = 9090;
// 参数内容:数据,数据的起始,数据的长度,数据要发送给谁。DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);// 3.发送包socket.send(packet);// 4.关闭流socket.close();}
}
接收端:
package com.edwin.lesson3;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/*** @author EdwinD* @create 2020.08.21 下午 09:19* @desc Udp服务端1**/
public class UdpServer1 {public static void main(String[] args) throws IOException {
// 开放端口DatagramSocket socket = new DatagramSocket(9090);
// 接受数据包byte[] buffer = new byte[1024];DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
// 阻塞接受socket.receive(packet);System.out.println(packet.getAddress().getHostAddress());System.out.println(new String(packet.getData(),0, packet.getLength()));
// 关闭连接socket.close();}
}
输出效果:

2.单方向聊天
一方可以不停给对方发送消息。
代码块儿
发送方:
package com.edwin.chat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
/*** @author EdwinD* @create 2020.08.23 上午 10:28* @desc 发送2.0**/
public class UdpSender2 {public static void main(String[] args) throws IOException {DatagramSocket socket = new DatagramSocket(8868);// 准备数据:读取控制台写入:System.inBufferedReader reader = new BufferedReader(new InputStreamReader(System.in));while (true) {String data = reader.readLine();byte[] datas = data.getBytes();DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress("localhost", 6686));socket.send(packet);if (data.equals("bye")) {break;}}socket.close();}
}
接收方:
package com.edwin.chat;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/*** @author EdwinD* @create 2020.08.23 上午 10:29* @desc 接收2.0**/
public class UdpReceive2 {public static void main(String[] args) throws IOException {DatagramSocket sock = new DatagramSocket(6686);while (true) {
// 准备接收包裹byte[] container = new byte[1024];DatagramPacket packet = new DatagramPacket(container, 0, container.length);
// 阻塞式接受包裹sock.receive(packet);
// 断开连接—>byebyte[] data = packet.getData();String receiveData = new String(data, 0, data.length);System.out.println(receiveData);if (receiveData.equals("bye")) {break;}}sock.close();}
}
效果输出:

后期改进后,连两方均可是发送方,也可以是接收方。
3.双方互通聊天
双方聊天需要保障,两个人发出的消息均可被对方接受。
体系结构:

代码区:
TalkSend:
package com.edwin.chat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
/*** @author EdwinD* @create 2020.08.23 上午 10:54* @desc 聊天发送**/
public class TalkSend implements Runnable {DatagramSocket socket = null;BufferedReader reader = null;private int fromIp;private String toIp;private int toPort;public TalkSend(int fromIp, String toIp, int toPort) throws SocketException {this.fromIp = fromIp;this.toIp = toIp;this.toPort = toPort;try {socket = new DatagramSocket(fromIp);
// 准备数据:读取控制台写入:System.inreader = new BufferedReader(new InputStreamReader(System.in));} catch (Exception e) {e.printStackTrace();}}@Overridepublic void run() {while (true) {String data = null;try {data = reader.readLine();} catch (IOException e) {e.printStackTrace();}byte[] datas = data.getBytes();DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress(this.toIp, this.toPort));try {socket.send(packet);} catch (IOException e) {e.printStackTrace();}if (data.equals("bye")) {break;}}socket.close();}
}
TalkReceive:
package com.edwin.chat;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/*** @author EdwinD* @create 2020.08.23 上午 11:19* @desc 聊天接收**/
public class TalkReceive implements Runnable{DatagramSocket sock = null;private int port;private String msgFrom;public TalkReceive(int port,String msgFrom) {this.port = port;this.msgFrom = msgFrom;try {sock = new DatagramSocket(port);} catch (SocketException e) {e.printStackTrace();}}@Overridepublic void run() {while (true) {try {
// 准备接收包裹byte[] container = new byte[1024];DatagramPacket packet = new DatagramPacket(container, 0, container.length);
// 阻塞式接受包裹sock.receive(packet);
// 断开连接—>byebyte[] data = packet.getData();String receiveData = new String(data, 0, data.length);System.out.println(msgFrom+":"+receiveData);if (receiveData.equals("bye")) {break;}} catch (IOException e) {e.printStackTrace();}}sock.close();}
}
TalkStudent:
package com.edwin.chat;
import java.net.SocketException;
/*** @author EdwinD* @create 2020.08.23 上午 11:25* @desc 学生端,双线程聊天。**/
public class TalkStudent {public static void main(String[] args) throws SocketException {
// 开启两个线程new Thread(new TalkSend(7777,"localhost",9999)).start();new Thread(new TalkReceive(8888,"老师")).start();}
}
TalkTeacher:
package com.edwin.chat;
import java.net.SocketException;
/*** @author EdwinD* @create 2020.08.23 上午 11:26* @desc 老师端,双线程聊天。**/
public class TalkTeacher {public static void main(String[] args) throws SocketException {
// 开启两个线程new Thread(new TalkSend(5555,"localhost",8888)).start();new Thread(new TalkReceive(9999,"学生")).start();}
}
效果输出:
IDEA中:

CMD中:
在使用了IDEA中的交互聊天后,我们考虑能否分窗口进行聊天,我们找到目录下class文件的所在地。

在目录下打开CMD,进行class文件的操作。
在路径前输入CMD加空格后回车,即可。

启动TalkStudent,但是无法启动。

因为,这里需要将:com.edwin.chat一同加在TalkStudent之前,他们是一个有机的整体。

启动IDEA中的TalkTeacher后,进行互动,效果如下:

由于CMD的格式原因,导致双方中文乱码,更改IDEA中的输出格式即可。
1.9、URL
URL:统一资源定位系统(uniform resource locator;URL)是因特网的万维网服务程序上用于指定信息位置的表示方法。它最初是由[蒂姆- 伯纳斯- 李](https://baike.baidu.com/item/蒂姆- 伯纳斯- 李)发明用来作为万维网的地址。
用于进行定位互联网上的某一特定资源。
DNS:域名解析。用于将某一个IP地址用WWW.XXXX.com表示出来。
# URL的本质是一个协议
# 表达的内容,是IP地址和端口号,项目名和资源等。
1.URL相关的参数
测试形代码:
package com.edwin.lesson4;
import java.net.MalformedURLException;
import java.net.URL;
/*** @author EdwinD* @create 2020.08.23 下午 12:35* @desc URL**/
public class URL1 {public static void main(String[] args) throws MalformedURLException {URL url = new URL("http://loaclhost:8080/helloworld/index.jsp?username=edwin&password=1234");System.out.println(url.getProtocol());//获得协议名System.out.println(url.getHost());//主机ipSystem.out.println(url.getPort());//端口System.out.println(url.getPath());//全路径System.out.println(url.getFile());//文件System.out.println(url.getQuery());//参数}
}
输出效果:

相关的参数不一定真实。
2.网络抓包,文件下载
可以通过某个确定的Url,进行网络特定资源的下载。我们可以先从本地的文件开始:
(1)本地文件
在本地的Tomcat里创建一个web页面:

内容:

打开本地的Tomcat文件夹里面bin目录里面的“startup.bat”:

访问Tomcat的http://localhost:8080/Edwin_Web_Try/Secret.txt:

代码:
package com.edwin.lesson4;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
/*** @author EdwinD* @create 2020.08.23 下午 09:52* @desc Url下载文件**/
public class UrlDownload {public static void main(String[] args) throws IOException {
// 建立Url连接,设置下载地址.URL url = new URL("http://localhost:8080/Edwin_Web_Try/Secret.txt");
// 连接到这个资源的Url,httpHttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();InputStream inputStream = urlConnection.getInputStream();FileOutputStream fos = new FileOutputStream("Secret2.txt");byte[] bytes = new byte[1024];int len;while ((len = inputStream.read(bytes)) != -1) {fos.write(bytes, 0, len);}fos.close();inputStream.close();urlConnection.disconnect();}
}
输出效果:

(2)网络资源下载
1.图片类:
转换成网络连接:
https://th.wallhaven.cc/small/4y/4y2mo7.jpg
图片效果:

双击打开图片:

代码:
package com.edwin.lesson4;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
/*** @author EdwinD* @create 2020.08.23 下午 09:52* @desc Url下载文件**/
public class UrlDownload {public static void main(String[] args) throws IOException {
// 建立Url连接,设置下载地址.URL url = new URL("https://p1.music.126.net/KDZoWvE6pjfeZ56bVD6giw==/109951164009637404.png");
// 连接到这个资源的Url,httpHttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();InputStream inputStream = urlConnection.getInputStream();FileOutputStream fos = new FileOutputStream("Vip.png");byte[] bytes = new byte[1024];int len;while ((len = inputStream.read(bytes)) != -1) {fos.write(bytes, 0, len);}fos.close();inputStream.close();urlConnection.disconnect();}
}
输出效果:

2.歌曲类:
安全版:
通过ctrl+shift+c或者直接打开F12,打开网络后台控制页。

双击打开:

将链接复制到我们下载文件的地方,Url。
代码:
package com.edwin.lesson4;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
/*** @author EdwinD* @create 2020.08.23 下午 09:52* @desc Url下载文件**/
public class UrlDownload {public static void main(String[] args) throws IOException {
// 建立Url连接,设置下载地址.URL url = new URL("https://m701.music.126.net/20200824091233/d716ecaacea305a909aa539f0da1658d/jdyyaac/045a/0253/065e/303e34d46a59c98f75c41471b3b57a4c.m4a");
// 连接到这个资源的Url,httpHttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();InputStream inputStream = urlConnection.getInputStream();//下载文件命名。FileOutputStream fos = new FileOutputStream("J-fla.m4a");byte[] bytes = new byte[1024];int len;while ((len = inputStream.read(bytes)) != -1) {fos.write(bytes, 0, len);}//关闭资源fos.close();inputStream.close();urlConnection.disconnect();}
}
输出效果:

路漫漫其修远兮,吾将上下而求索。
参考文献
《【狂神说Java】网络编程实战讲解》
视频链接
2020.08.24
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
