1️⃣网络编程概述
- Java是Internet 上的语言,它从语言级上提供了对网络应用程序的支持,程序员能够很容易开发常见的网络应用程序。
- Java提供的网络类库,可以实现无痛的网络连接,联网的底层细节被隐藏在Java 的本机安装系统里,由JVM 进行控制。并且Java 实现了一个跨平台的网络库,程序员面对的是一个统一的网络编程环境。
- 计算机网络:
把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息、共享硬件、软件、数据信息等资源。
- 网络编程的目的:
直接或间接地通过网络协议
与其它计算机实现数据交换,进行通讯。
- 网络编程中有两个主要的问题:
- 如何准确地定位网络上一台或多台主机;定位主机上的特定的应用
- 找到主机后如何可靠高效地进行数据传输
2️⃣网络通信要素概述
- IP
- 端口号
- 一定的规则(即:网络通信协议。有两套参考模型)
- OSI参考模型:模型过于理想化,未能在因特网上进行广泛推广
- TCP/IP参考模型(或TCP/IP协议):事实上的国际标准。
- 网络通信协议
1 2 3 4 5 6 7 8 9 10 11
| /** * 一、网络编程中有两个主要的问题: * 1.如何准确地定位网络上一台或多台主机;定位主机上的特定的应用 * 2.找到主机后如何可靠高效地进行数据传输 * * 二、网络编程中的两个要素: * 1.对应问题一:IP和端口号 * 2.对应问题二:提供网络通信协议:TCP/IP参考模型(应用层、传输层、网络层、物理+数据链路层) */
12345678910
|
3️⃣信要素1:IP和端口号
IP的理解与InetAddress类的实例化
- IP 地址:
InetAddress
- 唯一的标识Internet 上的计算机(通信实体)
- 本地回环地址(hostAddress):127.0.0.1 主机名(hostName):localhost
- IP地址分类方式1:IPV4和IPV6
- IPV4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已经用尽。以点分十进制表示,如192.168.0.1
- IPV6:128位(16个字节),写成8个无符号整数,每个整数用四个十六进制位表示,数之间用冒号(:)分开,如:3ffe:3201:1401:1280:c8ff:fe4d:db39:1984
- IP地址分类方式2:公网地址(万维网使用)和私有地址(局域网使用)。192.168.开头的就是私有地址,范围即为192.168.0.0–192.168.255.255,专门为组织机构内部使用
- 特点:不易记忆
- Internet上的主机有两种方式表示地址:
- 域名(hostName):www.wjiangquan.top
- IP地址(hostAddress):202.108.35.210
- InetAddress类主要表示IP地址,两个子类:Inet4Address、Inet6Address。
- InetAddress类对象含有一个Internet主机地址的域名和IP地址:www.wjiangquan.top
- 和202.108.35.210。
- 域名容易记忆,当在连接网络时输入一个主机的域名后,域名服务器(DNS)负责将域名转化成IP地址,这样才能和主机建立连接。-------域名解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| package hxut;
import java.net.InetAddress; import java.net.UnknownHostException;
public class InetAddressTest { public static void main(String[] args) { try { InetAddress inet1 = InetAddress.getByName("192.168.10.14"); System.out.println(inet1);
InetAddress inet2= InetAddress.getByName("www.wjiangquan.top"); System.out.println(inet2);
InetAddress inet3= InetAddress.getByName("www.baidu.com"); System.out.println(inet3);
InetAddress inet4 = InetAddress.getByName("127.0.0.1"); System.out.println(inet4);
InetAddress inet5 = InetAddress.getLocalHost(); System.out.println(inet5);
System.out.println(inet2.getHostName()); System.out.println(inet2.getHostAddress()); } catch (UnknownHostException e) { e.printStackTrace(); } } }
|
端口号的理解
- 端口号标识正在计算机上运行的进程(程序)
- 不同的进程有不同的端口号
- 被规定为一个
16
位的整数0~65535
。
- 端口分类
- 公认端口:
0~1023。
被预先定义的服务通信占用(如:HTTP占用端口80,FTP占用端口21,Telnet占用端口23)
- 注册端口:
1024~49151
。分配给用户进程或应用程序。(如:Tomcat占用端口8080,MySQL占用端口3306
,Oracle占用端口1521
等)。
- 动态/私有端口:
49152~65535
。
- 端口号与IP地址的组合得出一个网络套接字:
Socket
4️⃣通信要素2:网络协议
- 网络通信协议
计算机网络中实现通信必须有一些约定,即通信协议,对速率、传输代码、代码结构、传输控制步骤、出错控制等制定标准。
- 问题:网络协议太复杂
计算机网络通信涉及内容很多,比如指定源地址和目标地址,加密解密,压缩解压缩,差错控制,流量控制,路由控制,如何实现如此复杂的网络协议呢?
- 通信协议分层的思想
在制定协议时,把复杂成份分解成一些简单的成份,再将它们复合起来。最常用的复合方式是层次方式,即同层间可以通信、上一层可以调用下一层,而与再下一层不发生关系。各层互不影响,利于系统的开发和扩展。
TCP和UDP网络通信协议的对比
5️⃣TCP网络编程
1、例题1
客户端发送信息给服务端,服务端将数据显示在控制台上
例题1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
| package hxut;
import org.junit.Test;
import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException;
public class TCPTest { @Test public void client(){
Socket socket = null; OutputStream os = null; try { InetAddress inet = InetAddress.getByName("127.0.0.1");
socket = new Socket(inet,8899);
os = socket.getOutputStream();
os.write("你好,我是客户端".getBytes()); } 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(); } } } }
@Test public void test1(){ ServerSocket ss = null; Socket socket = null; InputStream is= null; ByteArrayOutputStream baos = null; try { ss = new ServerSocket(8899); socket = ss.accept(); is = socket.getInputStream();
baos = new ByteArrayOutputStream(); byte[] buffer = new byte[5]; int len; while ((len = is.read(buffer))!=-1){ baos.write(buffer,0,len); } System.out.println(baos.toString());
System.out.println("收到了来自于"+socket.getInetAddress()+"地址"); } 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(ss != null){ try { ss.close(); } catch (IOException e) { e.printStackTrace(); } }
} }
}
|
2、例题2
客户端发送文件给服务端,服务端将文件保存在本地。
⭐例题2
注意点:InputStream本身是抽象类,不可以实例化对象,(需要重写read()方法。
1 2 3 4 5 6
| InputStream is=new InputStream() { @Override public int read() throws IOException { return 0; } };
|
下面代码中使用InputStream is =null;(len=is.read(buffer))!=-1
这里面的is 指向的是scoket.getInputStream()
返回的对象,通过源码发现该对象已经重载过read()
方法,因此可以使用is.read();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public InputStream getInputStream() throws IOException { if (isClosed()) throw new SocketException("Socket is closed"); if (!isConnected()) throw new SocketException("Socket is not connected"); if (isInputShutdown()) throw new SocketException("Socket input is shutdown"); InputStream is = null; try { is = AccessController.doPrivileged( new PrivilegedExceptionAction<>() { public InputStream run() throws IOException { return impl.getInputStream(); } }); } catch (java.security.PrivilegedActionException e) { throw (IOException) e.getException(); } return is; }
|
Answer:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
| package pers.dhx_.java0623;
import org.junit.jupiter.api.Test;
import java.io.*; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket;
public class TCPTest3 { @Test public void client() { Socket socket = null; FileInputStream fis = null; OutputStream os = null; ByteArrayOutputStream baos = null; InputStream is = null; try { socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090); os = socket.getOutputStream(); fis = new FileInputStream(new File("E:\\vscode_background\\07af42bd8clmWoE.jpg")); byte[] buffer = new byte[1024]; int len; while ((len = fis.read(buffer)) != -1) { os.write(buffer, 0, len); } socket.shutdownOutput();
is = socket.getInputStream(); baos = new ByteArrayOutputStream(); byte[] buffer2 = new byte[1024]; int len1;
while ((len1 = is.read(buffer2)) != -1) { baos.write(buffer2, 0, len1); } System.out.println(baos.toString());
} catch (IOException e) { e.printStackTrace(); } finally { try { if (socket != null) { socket.close(); } if (baos != null) { baos.close(); } if (fis != null) { fis.close(); } if (os != null) { os.close(); } if (is != null) { is.close(); } } catch (IOException e) { e.printStackTrace(); } } }
@Test public void server() { ServerSocket ss = null; FileOutputStream fos = null; InputStream is = null; Socket socket = null; try { ss = new ServerSocket(9090); socket = ss.accept(); is = socket.getInputStream(); fos = new FileOutputStream("TDPTest.jpg"); byte[] buffer = new byte[1024]; int len; while ((len = is.read(buffer)) != -1) { fos.write(buffer, 0, len); } System.out.println("图片传输完成"); OutputStream os = socket.getOutputStream(); os.write("图片已收到".getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { try { if (fos != null) { fos.close(); if (is != null) { is.close(); } if (ss != null) { ss.close(); } if (socket != null) { socket.close(); } } } catch (IOException e) { e.printStackTrace(); } } } }
|
3、例题
从客户端发送文件给服务端,服务端保存到本地。并返回“发送成功”给客户端。 并关闭相应的连接。
例题3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| package hxut;
import org.junit.Test;
import java.io.*; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket;
public class TcpTest3 {
@Test public void test() throws IOException { Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9090); OutputStream os = socket.getOutputStream(); FileInputStream fis = new FileInputStream(new File("爱情与友情.jpg")); byte[] buffer = new byte[1024]; int len; while((len = fis.read(buffer)) != -1){ os.write(buffer,0,len); } socket.shutdownOutput();
InputStream is = socket.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] bufferr = new byte[20]; int len1; while((len1 = is.read(buffer)) != -1){ baos.write(buffer,0,len1); } System.out.println(baos.toString());
fis.close(); os.close(); socket.close(); baos.close(); }
@Test public void test2() throws IOException { ServerSocket ss = new ServerSocket(9090); Socket socket = ss.accept(); InputStream is = socket.getInputStream(); FileOutputStream fos = new FileOutputStream(new File("爱情与友情4.jpg")); byte[] buffer = new byte[1024]; int len; while((len = is.read(buffer)) != -1){ fos.write(buffer,0,len); }
System.out.println("图片传输完成");
OutputStream os = socket.getOutputStream(); os.write("你好,照片我已收到,风景不错!".getBytes());
fos.close(); is.close(); socket.close(); ss.close(); os.close(); } }
|
6️⃣UDP网络编程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| package pers.dhx_.java0623;
import org.junit.jupiter.api.Test;
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress;
public class UDPTest { @Test public void test() throws IOException { DatagramSocket socket = new DatagramSocket(); String str = "我是UDP方式发送的导弹"; byte[] data = str.getBytes(); InetAddress inet = InetAddress.getLocalHost(); DatagramPacket datagramPacket = new DatagramPacket(data, 0, data.length, inet, 9999); socket.send(datagramPacket); socket.close(); }
@Test public void test1() throws IOException { DatagramSocket socket = new DatagramSocket(9999); byte[] buffer = new byte[100]; DatagramPacket datagramPacket = new DatagramPacket(buffer, 0, buffer.length); socket.receive(datagramPacket); System.out.println(new String(datagramPacket.getData(), 0, datagramPacket.getLength())); socket.close(); } }
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
|
7️⃣URL编程
🎈URL类
URL类构造器
![image-20220623180946275](C:\Users\lenovo\Desktop\Java\SUMMER_JAVA\JavaSe _Note\image\image-20220623180946275.png)
URL类常用方法
URL的理解与实例化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| package hxut;
import java.net.MalformedURLException; import java.net.URL;
public class URLTest { public static void main(String[] args) throws MalformedURLException {
URL url = new URL(" http://127.0.0.1:8080/work/164.jpg?username=subei");
System.out.println(url.getProtocol());
System.out.println(url.getHost());
System.out.println(url.getPort());
System.out.println(url.getPath());
System.out.println(url.getFile());
System.out.println(url.getQuery()); }
}
|
🍅针对HTTP协议的URLConnection类
URL的方法 openStream():能从网络上读取数据
若希望输出数据,例如向服务器端的 CGI (公共网关接口-Common Gateway Interface-的简称,是用户浏览器和服务器端的应用程序进行连接的接口)程序发送一些数据,则必须先与URL建立连接,然后才能对其进行读写,此时需要使用URLConnection 。
URLConnection:表示到URL所引用的远程对象的连接。当与一个URL建立连接时,首先要在一个 URL 对象上通过方法 openConnection() 生成对应的 URLConnection对象。如果连接过程失败,将产生IOException.
URL netchinaren = new URL ("http://www.atguigu.com/index.shtml");
URLConnectonn u = netchinaren.openConnection( );
💃通过URLConnection对象获取的输入流和输出流,即可以与现有的CGI程序进行交互。
public Object getContent( ) throws IOException
public int getContentLength( )
public String getContentType( )
public long getDate( )
public long getLastModified( )
public InputStream getInputStream( )throws IOException
public OutputSteram getOutputStream( )throws IOException
URL网络编程实现Tomcat服务端数据下载(p630)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL;
public class URLTest1 { public static void main(String[] args) { HttpURLConnection urlConnection = null; InputStream is = null; FileOutputStream fos = null; try { URL url = new URL("http://127.0.0.1:8080/work/164.jpg");
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.connect();
is = urlConnection.getInputStream(); fos = new FileOutputStream("day10\\1643.jpg");
byte[] buffer = new byte[1024]; int len; while((len = is.read(buffer)) != -1){ fos.write(buffer,0,len); }
System.out.println("下载完成"); } catch (IOException e) { e.printStackTrace(); } finally { if(is != null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if(fos != null){ try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if(urlConnection != null){ urlConnection.disconnect(); } } } }
|
URI、URL和URN的区别
- URI,是uniform resource identifier,统一资源标识符,用来唯一的标识一个资源。而URL是uniform resource locator,统一资源定位符,它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate这个资源。而URN,uniform resource name,统一资源命名,是通过名字来标识资源,比如mailto:java-net@java.sun.com。也就是说,URI是以一种抽象的,高层次概念定义统一资源标识,而URL和URN则是具体的资源标识的方式。URL和URN都是一种URI。
- 在Java的URI中,一个URI实例可以代表绝对的,也可以是相对的,只要它符合URI的语法规则。而URL类则不仅符合语义,还包含了定位该资源的信息,因此它不能是相对的。