网络编程
1.1 概述
网络编程的目的:
-
传播交流信息
-
数据交换
-
通信
想要达到这个效果需要什么:
- 如何准确的定位网络上的一台主机 192.168.16.124:端口,定位到这个计算机上的某个资源
- 找到了这个主机,如何传输数据呢?
JavaWEB
:网页编程,属B/S
网络编程:TCP/IP,属C/S
1.2 网络通讯的要素
实现网络的通信需要通信双方地址:
IP
- 端口号
- 例:
192.168.16.124
:2345
规则:网络通信的协议
TCP/IP参考模型:
我们主要应用的是他的传输层
:
TCP
UDP
小结:
- 网络编程中有两个主要的问题
- 如何
准确的定位
到网络上的一台或者多台主机 - 找到主机之后如何进行
通信
- 如何
- 网络编程中的要素
IP
和端口号- 网络通信协议
udp
,tcp
- 万物皆对象,对于获取
IP
相关信息JAVA也有对应的内部类:InetAddress
1.3 IP
ip
地址:InetAddress
-
唯一定位一台网络上计算机
-
127.0.0.1
、localhost
代表本机 -
ip
地址的分类-
ipv4
/ipv6
-
IPV4
:如127.0.0.1
,它是由4个字节组成。0~255
,大概有40多亿个;其中30亿在北美,亚洲大概有4亿。在2011年就用尽了; -
IPV6
:128位。8个无符号整数!由a~e
,1~9
组成12001: 0bb2: aaaa: 0015:0000:0000: 1aaa:1312
-
-
公网(互联网)、私网(局域网)
IP
分ABCD
类,A类网段在255/2,B类在255/2/2,以此类推
192.168.xx.xx
一般都是组的局域网,专门给住址内部使用的
-
-
域名:
- 它和
IP
是一 一对应的 - 域名只是为了解决
IP
不好记的问题
- 它和
1.4 端口
端口表示计算机上的一个程序的进程:
-
不同的进程有不同的端口号!用来区分软件!
-
端口被规定范围在0~65535
-
TCP/UDP:
65535 * 2
,单个协议下端口号不能冲突,当TCP
和UDP
可以使用相同端口,因为他俩协议是不同的 -
端口分类
-
公有端口基本使用了
0~1023
范围HTTP
:80HTTPS
:443FTP
:443Telent
:23- …
-
普通程序可以注册的端口:
1024~49151
Tomcat
:8080Oracle
:1521- …
-
动态、私有端口:
49152~65535
-
# 查看所有端口 netstat -nao # 查看指定端口 netstat -ano|findstr "8080" # 查看指定端口的进程 tasklist|findstr "9644"
-
-
1.5 通信协议
TCP
与UDP
对比
TCP
相当于打电话
- 连接稳定
- 连接时三次握手、断开时四次挥手
- 有客户端和服务端
- 传输完成,释放连接,效率低
UDP
相当于发短信
- 不连接,不稳定
- 客户端、服务端:没有明确的界限
- 不管接收方有没有准备好,都可以发送信息
1.6 TCP
文件上传
-
客户端
-
/** * @Description: 模拟网络传输---客户端 * @Author Djn * @Date 2020/11/11 * @Since V1.0 add-->连接时:客户端soket发出,服务端soket接收,接收到之后才开始执行业务 * 断开时:服务端soket输入,客户端soket接收,客户端接收后连接才断开 * @Version V1.0 **/ public class TestTcpClint { public static void main(String[] args) throws Exception { //1. 创建一个Socket连接 因为是网络传输InetAddress.getByName来获取网络主机名称,所以主方法要抛出一个UnknownHostException找不到主机的异常交由调用它的方法处理,或直接抛出异常的主类Exception Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000); //2. 创建一个输出流 因为是模拟客户端向服务端发送文件,所以是向服务器输出 OutputStream os = socket.getOutputStream(); //3. 读取文件 使用文件的输入流先读取.png的文件 FileInputStream fis = new FileInputStream(new File("clint.png")); //4. 写出文件 设定缓冲区1024,后续输入或输出去缓冲区里读取 byte[] buffer = new byte[1024]; //设定输入流文件变量 int lenth; //循环取出 输入流输入的内容,当输入流长度为-1时停止输入 while ((lenth = fis.read(buffer)) != -1) { os.write(buffer, 0, lenth); } //5. 通知服务器发送结束 socket.shutdownOutput(); //6. 确定服务器接收完毕后才断开连接 socket连接使用输入流接收服务端输出流发送过来的内容 InputStream inputStream = socket.getInputStream(); //因为服务端那边返回的是.getBytes() 所以new一个byteArray来接收 ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer2 = new byte[1024]; int len; while ((len = inputStream.read(buffer2)) != -1) { baos.write(buffer2, 0, len); } System.out.println(baos.toString()); //7. 关闭资源 baos.close(); inputStream.close(); fis.close(); os.close(); socket.close(); } }
-
-
服务端
-
/** * @Description: 模仿网络连接的三次握手,四次分手 * @Author Djn * @Date 2020/11/11 * @Since V1.0 add--> * @Version V1.0 **/ public class TestTcpServer { public static void main(String[] args) throws Exception { //1. 创建服务 因为是网络文件传输ServerSocket,所以主方法要抛出一个IOException异常交由调用它的方法处理,或直接抛出异常的主类Exception ServerSocket serverSocket = new ServerSocket(9000); //2. 监听客户端的连接 .accept()阻塞式监听:一直监听到客户端连接上来代码才往后走 Socket socket = serverSocket.accept(); //3. 获取输入流 InputStream is = socket.getInputStream(); //4. 文件输出 FileOutputStream fos = new FileOutputStream(new File("receive.png")); byte[] buffer = new byte[1024]; //设定输入流文件变量 int lenth; //循环取出 输入流输入的内容,当输入流长度为-1时停止输入 while ((lenth=is.read(buffer))!=-1){ fos.write(buffer,0,lenth); } //5. 告诉客户端我已经接收完毕了 使用输出流想soket输出内容 OutputStream os = socket.getOutputStream(); os.write("我收完毕了,客户端可以断开连接了".getBytes()); //关闭资源 fos.close(); is.close(); socket.close(); serverSocket.close(); } }
-
1.7 UDP
UDP
像发短信,只要知道要发送目标的地址即可,不需要连接
发送端
public class udpClient {
// 抛出连接异常
public static void main(String[] args) throws Exception{
// 1.建立一个soket
DatagramSocket socket = new DatagramSocket();
// 2.建立一个包
String msg = "Hello server!";
// 发送目标
InetAddress localhost = InetAddress.getByName("localhost");
int port = 9009;
// 数据,数据长度的起始位置,发送目标的IP+端口
DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);
// 3.发送包
socket.send(packet);
// 4.关闭流
socket.close();
}
}
1.8 URL
**DNS
域名解析:**就是将www.baidu.com这个域名解析成xxx.xxx.xxx.xxx
的IP
https://www.baidu.com/
-
**统一资源定位符:**定位互联网上的某一个资源
-
协议://ip地址:端口/项目名/资源
URL
的使用
public static void main(String[] args) throws Exception {
URL url = new URL("https://blog.csdn.net/weixin_45532227/article/details/107832563");
// 协议名
System.out.println(url.getProtocol());
// 主机名
System.out.println(url.getHost());
// ip
System.out.println(url.getPort());
// 项目路径
System.out.println(url.getPath());
// 资源名称--文件名称,文件的全路径
System.out.println(url.getFile());
// 查询参数
System.out.println(url.getQuery());
}
爬取资源(音乐)
/**
* @Description: 测试爬取xxx网的音乐
* @Author Djn
* @Date 2020/11/13
* @Since V1.0 add-->
* @Version V1.0
**/
public class MP3Url {
public static void main(String[] args) throws Exception {
//要爬取的目标地址
URL url = new URL("https://这里瞎写的,自己按照网址实际音乐文件的包写/***.m4a");
// 使用url的.openConnection()方法连接到这个资源
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
// 拿到这个资源的流
InputStrea m inputStream = httpURLConnection.getInputStream();
// 使用文件输出流,输出爬取的文件名称并下载到本地
FileOutputStream fos = new FileOutputStream("布格拉广场.m4a");
// 设置写出的缓冲区
byte[] bytes = new byte[1024];
// 定义流的长度
int len;
// 循环读取这个流的长度,直到长度为-1为止
while ((len = inputStream.read(bytes)) != -1) {
//写出
fos.write(bytes, 0, len);
}
// 关闭流
fos.close();
inputStream.close();
//断开连接
httpURLConnection.disconnect();
}
}