一、概述
- 地球村:你在西安,你一个美国的朋友!
- 信件:
-
计算机网络:
计算机网络是指将**地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来**,在网络操作系统,网络管理软件及**网络通信协议**的管理和协调下,实现资源共享和信息传递的计算机系统。
-
网络编程的目的:
无线电台 —> 传播交流信息、数据交换、通信
-
想要达到这个效果需要什么:
- 如何准确地定位网络上的一台主机 192.168.16.124: 端口,定位到这个计算机上的某个资源
- 找到了这个主机,如何传输数据呢?
-
网络编程和网页编程
- 网络编程 TCP/IP C/S
- 网页编程 JavaWeb B/S
二、网络通信的要素
-
如何实现网络的通信?
-
通信双方的地址:
IP、端口号
-
规则:网络通信的协议:http、ftp、smtp、tcp、udp…
TCP/IP参考模型:
三、IP
-
IP地址:InetAddress类
-
唯一定位一台网络上的计算机
-
本机 localhost:127.0.0.1
-
IP地址的分类:
-
ipv4 / ipv6
-
ipv4:127.0.0.1,4个字节组成,0~255,42亿:北美30亿,亚洲4亿,2011年已用尽;
-
ipv6:fe80::35bb:3e82:d451:cb96%19,128位,8个无符号整数;
2001:0bb2:aaaa:0015:0000:0000:1aaa:1312
-
-
公网(互联网)/ 私网(局域网)
-
ABCD类地址(查资料)
IP地址分为五类,A类保留给政府机构,B类分配给中等规模的公司,C类分配给任何需要的人,D类用于组播,E类用于实验,各类可容纳的地址数目不同。
其中A类、B类、和C类这三类地址用于TCP/IP节点,其它两类D类和E类被用于特殊用途。
A、B、C三类IP地址的特征:当将IP地址写成二进制形式时,A类地址的第一位总是O,B类地址的前两位总是10,C类地址的前三位总是110。1. A类IP地址
一个A类IP地址由1字节的网络地址和3字节主机地址组成,网络地址的最高位必须是“0”, 地址范围从1.0.0.0 到126.0.0.0。可用的A类网络有126个,每个网络能容纳1亿多个主机。
⑴ A类地址第1字节为网络地址,其它3个字节为主机地址。
⑵ A类地址范围:1.0.0.1—126.155.255.254
⑶ A类地址中的私有地址和保留地址:
① 10.X.X.X是私有地址(所谓的私有地址就是在互联网上不使用,而被用在局域网络中的地址)。
② 127.X.X.X是保留地址,用做循环测试用的。2. B类IP地址
一个B类IP地址由2个字节的网络地址和2个字节的主机地址组成,网络地址的最高位必须是“10”,地址范围从128.0.0.0到191.255.255.255。可用的B类网络有16382个,每个网络能容纳6万多个主机 。
⑴ B类地址第1字节和第2字节为网络地址,其它2个字节为主机地址。
⑵ B类地址范围:128.0.0.1—191.255.255.254。
⑶ B类地址的私有地址和保留地址
① 172.16.0.0—172.31.255.255是私有地址
② 169.254.X.X是保留地址。如果你的IP地址是自动获取IP地址,而你在网络上又没有找到可用的DHCP服务器。就会得到其中一个IP。3. C类IP地址
一个C类IP地址由3字节的网络地址和1字节的主机地址组成,网络地址的最高位必须是“110”。范围从192.0.0.0到223.255.255.255。C类网络可达209万余个,每个网络能容纳254个主机。
⑴ C类地址第1字节、第2字节和第3个字节为网络地址,第4个个字节为主机地址。另外第1个字节的前三位固定为110。
⑵ C类地址范围:192.0.0.1—223.255.255.254。
⑶ C类地址中的私有地址:
192.168.X.X是私有地址。4. D类地址用于多点广播(Multicast)。
D类IP地址第一个字节以“1110”开始,它是一个专门保留的地址。它并不指向特定的网络,目前这一类地址被用在多点广播(Multicast)中。多点广播地址用来一次寻址一组计算机,它标识共享同一协议的一组计算机。
⑴ D类地址不分网络地址和主机地址,它的第1个字节的前四位固定为1110。
⑵ D类地址范围:224.0.0.1—239.255.255.2545. E类IP地址
以“11110”开始,为将来使用保留。
全零(“0.0.0.0”)地址对应于当前主机。全“1”的IP地址(“255.255.255.255”)是当前子网的广播地址。
⑴ E类地址也不分网络地址和主机地址,它的第1个字节的前五位固定为11110。
⑵ E类地址范围:240.0.0.1—255.255.255.2546. 在IP地址3种主要类型里,各保留了3个区域作为私有地址,其地址范围如下:
A类地址:10.0.0.0~10.255.255.255
B类地址:172.16.0.0~172.31.255.255
C类地址:192.168.0.0~192.168.255.255
7. 子网掩码
**子网掩码(subnet mask)**又叫网络掩码、地址掩码、子网络遮罩,它是一种用来指明一个IP地址的哪些位标识的是主机所在的子网,以及哪些位标识的是主机的位掩码。
**子网掩码不能单独存在,它必须结合IP地址一起使用。**子网掩码只有一个作用,就是将某个IP地址划分成网络地址和主机地址两部分。子网掩码是一个32位地址,用于屏蔽IP地址的一部分以区别网络标识和主机标识,并说明该IP地址是在局域网上,还是在远程网上。
子网掩码——屏蔽一个IP地址的网络部分的“全1”比特模式。
对于A类地址来说,默认的子网掩码是255.0.0.0;
对于B类地址来说默认的子网掩码是255.255.0.0;
对于C类地址来说默认的子网掩码是255.255.255.0。 -
192.168.xx.xx:专门给组织内部使用的
-
-
-
域名:记忆IP问题!
- IP:www.vip.com
package com.cwlin.lesson01;
import java.net.InetAddress;
import java.net.UnknownHostException;
//测试IP
public class TestInetAddress {
public static void main(String[] args) {
try {
//查询本机地址
InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");
System.out.println(inetAddress1);
InetAddress inetAddress3 = InetAddress.getByName("localhost");
System.out.println(inetAddress3);
InetAddress inetAddress4 = InetAddress.getLocalHost();
System.out.println(inetAddress4);
//查询网站ip地址
InetAddress inetAddress2 = InetAddress.getByName("www.baidu.com");
System.out.println(inetAddress2);
//常用方法
//System.out.println(inetAddress2.getAddress()); //地址
System.out.println(inetAddress2.getCanonicalHostName()); //规范的名字
System.out.println(inetAddress2.getHostAddress()); //ip
System.out.println(inetAddress2.getHostName()); //域名,或者自己电脑的名字
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
四、端口
-
端口表示计算机上的一个程序的进程。
-
不同的进程有不同的端口号,用来区分软件!
-
被规定为0~65535
-
TCP/UDP:65535*2,TCP:80和UDP:80不冲突;在单个协议下,端口号不能冲突
-
端口分类:
- 公有端口 0~1023
- HTTP: 80;
- HTTPS: 443;
- FTP: 21;
- Telent: 23
- 程序注册端口 1024~49151,分配给用户或者程序
- Tomcat: 8080
- MySQL: 3306
- Oracle: 1521
- 动态、私有:49152~65535
netstat -ano #查看所有端口 netstat -ano|findstr "49664" #查看指定端口 tasklist|findstr "21796" #查看指定端口的进程
- 公有端口 0~1023
package com.cwlin.lesson01;
import java.net.InetAddress;
import java.net.InetSocketAddress;
//测试ip+port
public class TestInetSocketAddress {
public static void main(String[] args) {
InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1",8080);
InetSocketAddress socketAddress2 = new InetSocketAddress("localhost",8080);
System.out.println(socketAddress);
System.out.println(socketAddress2);
System.out.println(socketAddress.getAddress()); //ip
System.out.println(socketAddress.getPort()); //端口
System.out.println(socketAddress.getHostName()); //地址(hosts文件可修改)
}
}
五、通信协议
-
协议:约定,
-
网络通信协议:速率、传输码率、代码结构、传输控制…
-
问题:非常复杂?
-
解决:大事化小!分层!
-
TCP/IP协议簇:实际上是一组协议
-
重要协议:
- TCP:用户传输协议
- UDP:用户数据报协议
-
出名的协议:
- TCP:传输控制协议
- IP:网络互联协议
-
TCP和UDP的对比
-
TCP:打电话
-
连接,稳定
-
三次握手、四次挥手
-
客户端、服务端
-
传输完成,释放连接,效率低
-
-
UDP:发短信
- 不连接,不稳定
- 客户端、服务端:没有明确的界限
- 不管有没有准备好,都可以发给你
- 导弹
- DDOS:洪水攻击!(饱和攻击)
-
TCP的三次握手、四次挥手
-
概述:
最少需要三次,保证连接稳定! A: 你愁啥? B: 瞅你咋地? A: 干一场! 最少需要四次,保证彻底断开! A: 我要走了! B: 我真的要走了吗? B: 你真的真的要走了吗? A: 我真的要走了!
-
详解:
- 通俗理解:
-
-
六、TCP
6.1、发送消息
- 客户端
- 连接服务Socket
- 发送消息
package com.cwlin.lesson02;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
//客户端
public class TcpClientDemo01 {
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
try {
//1.要知道服务器的地址、端口号
InetAddress 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());
} 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();
}
}
}
}
}
-
服务器
-
建立服务的端口 ServerSocket
-
等待用户的连接 accept
-
接收用户的消息
-
package com.cwlin.lesson02;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//服务端
public class TcpServerDemo01 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
//1.我得有一个地址
serverSocket = new ServerSocket(9999); //插槽
while (true){
//2.等待客户端连接过来
socket = serverSocket.accept();
//3.读取客户端的消息
is = socket.getInputStream();
//管道流
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());
}
/* 比较的方法,若中文在中间断掉,会乱码
byte[] buffer = new byte[1024];
int len;
while ((len=is.read(buffer))!=-1){
String msg = new String(buffer, 0, len);
System.out.println(msg);
}
*/
} 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();
}
}
}
}
}
6.2、文件上传
- 客户端
package com.cwlin.lesson02;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class TcpClientDemo02 {
public static void main(String[] args) throws Exception {
//1.创建一个Socket连接
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
//2.创建一个输出流
OutputStream os = socket.getOutputStream();
//3.读取文件
FileInputStream fis = new FileInputStream(new File("send.png"));
//4.写入文件
byte[] buffer = new byte[1024];
int len;
while ((len=fis.read(buffer)) != -1){
os.write(buffer,0,len);
}
//通知服务器已经传输结束
socket.shutdownOutput();
//确定服务器接收完毕,才能断开连接
InputStream inputStream = socket.getInputStream();
//String byte[]
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer2 = new byte[1024];
int len2;
while ((len2=inputStream.read(buffer2)) != -1){
byteArrayOutputStream.write(buffer2,0,len2);
}
System.out.println(byteArrayOutputStream.toString());
//5.关闭资源
byteArrayOutputStream.close();
inputStream.close();
fis.close();
os.close();
socket.close();
}
}
- 服务器
package com.cwlin.lesson02;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServerDemo02 {
public static void main(String[] args) throws Exception {
//1.创建服务
ServerSocket serverSocket = new ServerSocket(9000);
//2.监听客户端的连接
Socket socket = serverSocket.accept();
//3.获取输入流
InputStream is = socket.getInputStream();
//4.文件输出
FileOutputStream fos = new FileOutputStream(new File("receive.png"));
byte[] buffer = new byte[1024];
int len;
while ((len=is.read(buffer)) != -1){
fos.write(buffer,0,len);
}
//通知客户端已经接收完毕
OutputStream outputStream = socket.getOutputStream();
outputStream.write("已经接收完毕,可以断开".getBytes());
//5.关闭资源
fos.close();
is.close();
socket.close();
serverSocket.close();
}
}
6.3、Tomcat
-
服务端
- 自定义 S
- Tomcat服务器 S:Java后台开发!
-
客户端
- 自定义 C
- 浏览器 B
七、UDP
7.1、发送消息:不用连接,只需要知道对方的地址!
- 发送端
package com.cwlin.lesson03;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
//不需要连接服务器
public class UdpClientDemo01 {
public static void main(String[] args) throws Exception {
//1.建立一个Socket
DatagramSocket socket = new DatagramSocket();
//2.建个包
String msg = "你好啊,服务器!";
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.cwlin.lesson03;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
//还是要等待客户端的连接!
public class UdpServerDemo01 {
public static void main(String[] args) throws Exception {
//开放端口
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();
}
}
7.2、咨询:循环发送消息和接收消息!
- 发送端:循环发送消息
package com.cwlin.chat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class UdpSenderDemo01 {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(8888);
//准备数据:控制台读取System.in
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true){
String data = reader.readLine();
byte[] sendData = data.getBytes();
DatagramPacket packet = new DatagramPacket(sendData,0,sendData.length,new InetSocketAddress("localhost",6666));
socket.send(packet);
if (data.equals("bye")){
break;
}
}
socket.close();
}
}
- 接收端:循环接收消息
package com.cwlin.chat;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UdpReceiveDemo01 {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(6666);
while (true){
//准备接收包裹
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container,0,container.length);
socket.receive(packet); //阻塞式接收包裹
//断开连接 bye
byte[] data = packet.getData();
String receiveData = new String(data, 0, data.length);
System.out.println(receiveData);
if (receiveData.equals("bye")){
break;
}
}
}
}
7.3、在线咨询:两个人都可以是发送方和接收方!
- 发送线程
package com.cwlin.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;
public class TalkSend implements Runnable {
DatagramSocket socket = null;
BufferedReader reader = null;
private int fromPort;
private String toIP;
private int toPort;
public TalkSend(int fromPort, String toIP, int toPort) {
this.fromPort = fromPort;
this.toIP = toIP;
this.toPort = toPort;
try {
socket = new DatagramSocket(fromPort);
reader = new BufferedReader(new InputStreamReader(System.in));
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true){
String data = null;
try {
data = reader.readLine();
byte[] sendData = data.getBytes();
DatagramPacket packet = new DatagramPacket(sendData,0,sendData.length,new InetSocketAddress(this.toIP,this.toPort));
socket.send(packet);
if (data.equals("bye")){
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}
- 接收线程
package com.cwlin.chat;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class TalkReceive implements Runnable {
DatagramSocket socket = null;
private int port;
private String msgFrom;
public TalkReceive(int port, String msgFrom) {
this.port = port;
this.msgFrom = msgFrom;
try {
socket = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true){
try {
//准备接收包裹
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container,0,container.length);
socket.receive(packet); //阻塞式接收包裹
//断开连接 bye
byte[] 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();
}
}
}
}
- 老师端
package com.cwlin.chat;
public class TalkTeacher {
public static void main(String[] args) {
//开启两个线程
new Thread(new TalkSend(5555,"localhost",8888)).start();
new Thread(new TalkReceive(9999,"学生")).start();
}
}
- 学生端
package com.cwlin.chat;
public class TalkStudent {
public static void main(String[] args) {
//开启两个线程
new Thread(new TalkSend(7777,"localhost",9999)).start();
new Thread(new TalkReceive(8888,"老师")).start();
}
}
八、URL
8.1、概述
-
统一资源定位符:定位资源、定位互联网上的某一个资源
-
DNS域名解析 www.baidu.com xxx.x.x.x
-
格式:
协议://IP地址:端口/项目名/资源
8.2、URL基本内容
package com.cwlin.lesson05;
import java.net.MalformedURLException;
import java.net.URL;
public class URLDemo01 {
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("http://localhsot:8080/helloworld/index.jsp?username=cwlin&password=123456");
System.out.println(url.getProtocol()); //协议:http
System.out.println(url.getHost()); //主机IP:localhost
System.out.println(url.getPort()); //端口:8080
System.out.println(url.getPath()); //文件:/helloworld/index.jsp
System.out.println(url.getQuery()); //参数:username=cwlin&password=123456
System.out.println(url.getFile()); //全路径:/helloworld/index.jsp?username=cwlin&password=123456
}
}
8.3、URL下载网络资源
package com.cwlin.lesson05;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class URLDownload {
public static void main(String[] args) throws Exception {
//1.下载地址
//网页图片: https://p2.music.126.net/4WuOpPZeK7hH8bqn28G-Dg==/109951165315490238.jpg?param=130y130
//网页音乐: https://ws.stream.qqmusic.qq.com/C4000046fqfQ3mSaUo.m4a?guid=446211115&vkey=C8A1B9D42E3F101F2A7D0F98AEECA5CE2F5AB629A9533212BA47BB36B8680B85796E7C91E2D71DF5295FD18BAE714E50A6F89C5B04E3786B&uin=1208793450&fromtag=66
URL url = new URL("http://localhost:8080/cwlin/SecurityFile.txt");
//2.连接到这个资源 HTTP
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("漫长的告白.m4a");
byte[] buffer = new byte[1024];
int len;
while ((len=inputStream.read(buffer))!=-1){
fos.write(buffer,0,len); //写出这个数据
}
fos.close();
inputStream.close();
urlConnection.disconnect(); //断开连接
}
}