网络编程知识点整理
Octets :和Byte(字节) 都表示8bit(位)
bps:表示bit per second Bps:表示byte per second
ifInOctets:端口输入的总字节数(累计数目),到达最大值counter32时,清零
ifInUcastPkts:端口输入单传总包(报文)数(累计数目),到达最大值counter32时,清零
counter32:表示0-2^32B ,最大值为4GB
TCP和UDP数据报文:
MTU(最大传输字节):1500字节
UDP(1500B):20(IP头) + 8(UDP头) + 1472(数据区)
TCP(1500B):20(IP头) + 20(TCP头) + 1460(数据区)
1.1概述
计算机网络:
计算机网络是指将 地理位置不同 的具有独立功能的 多台计算机及外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件 及 网络通信协议 的管理和协调下,实现资源共享和信息传递的计算机系统
网络编程的目的:
传播交流信息,数据交换,通信
想要达到这个效果需要什么:
1.如何准确的定位网络上的一台主机 IP:端口,定位到这个计算机上的某个资源
2.找到这个主机,如何传输数据呢?
JavaWeb:网页编程 B/S
网络编程:TCP/IP C/S
1.2网络通信的要素
如何实现网络的通信?
通信双方地址:
- ip
- 端口号
规则:网络通信协议
OSI七层网络模型 TCP/IP参考模型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pnL0pQdz-1616079993670)(F:\Desktop\整理\1032624621.bmp)]
重点:传输层
1.网络编程中有两个主要的问题
- 如何准确的定位到网络上的一台或多台主机
- 找到主机之后,如何进行通信
2.网络编程中的要素
- IP和端口号
- 网络通信协议
3.万物皆对象
1.3 IP地址
ip地址:InetAddress
-
唯一定位一台网络上的计算机
-
127.0.0.1 :本机IP
-
ip地址分类
-
IPv4/IPv6
-
IPv4 127.0.0.1 4个字节组成,0-255,42亿个,亚洲4亿,2011年用完了
-
IPv6 128位,8个无符号整数
2001:0bb2:aaaa:0015:0000:0000:1aaa:1312
-
-
公网(互联网)-私网(局域网)
- ABCD类地址
- 192.168.xx.xx 专门给组织内部使用的
-
域名:记忆IP问题
- IP:www.baidu.com
// 查询本机地址 InetAddress[] name = InetAddress.getAllByName("127.0.0.1"); InetAddress[] name1 = InetAddress.getAllByName("localhost"); InetAddress localHost = InetAddress.getLocalHost(); // 常用方法 System.out.println(localHost.getCanonicalHostName());// 规范的名字 localHost.getHostAddress(); localHost.getHostName(); // 查询网站ip地址 InetAddress[] name2 = InetAddress.getAllByName("www.baidu.com"); System.out.println(name[0]); System.out.println(name1[0]); System.out.println(localHost); System.out.println(name2[0]);
-
1.4 端口
表示端口计算机上的一个程序进程。
-
不同的进程有不同的端口号,用来区分软件
-
被规定为0-65535
-
TCP,UDP:65535*2,单个协议下,端口号不能冲突
-
端口分类
-
公有端口:0-1023
- HTTP: 80
- HTTPS: 443
- FTP: 21
- Telent: 23
-
程序注册端口:1014-49151,分配用户或者程序的
- Tomcat: 8080
- MySQL: 3306
- Oracle: 1521
-
动态、私有:49152-65535(尽量不要用)
InetSocketAddress
InetSocketAddress socketAddress = new InetSocketAddress("127.0.01", 8080); InetSocketAddress socketAddress1 = new InetSocketAddress("localhost", 8080); System.out.println(socketAddress); System.out.println(socketAddress1); System.out.println(socketAddress.getAddress()); System.out.println(socketAddress.getHostName());// 地址 System.out.println(socketAddress.getPort());// 端口
-
1.5 通信协议
协议:约定,
网络通信协议:速率、传输码率、代码结构、传输控制…
问题:复杂
分层
TCP/IP协议:实际上是一组协议
重要:
- TCP:用户传输协议
- UDP:用户数据报协议
TCP UDP 对比
TCP 打电话
-
连接、稳定
-
三次握手、四次挥手
最少需要三次,保证稳定连接 A:在一起吗 B:好 A:太好了 四次挥手 A:我要断开 B:知道了 B:你真的要走了吗 A:我真的要走了
-
客户端、服务端
-
传输完成,释放连接、效率低
UDP 发短信
- 不连接、不稳定
- 客户端、服务端:没有明确的界限
- 不管有没有准备好,都可以发给你
- DDOS:洪水攻击(饱和攻击)
1.6 TCP
客户端
- 连接服务器Socket
- 发送消息
public class TCPClientDemo {
public static void main(String[] args) {
try {
// 1.需要知道服务器的地址
InetAddress serverIP = InetAddress.getByName("127.0.0.1");
int port = 9999;
// 创建一个socket连接,连接到服务端的IP和端口
Socket socket = new Socket(serverIP,port);
// 3.发送消息,先声明输出字节流
OutputStream outputStream = socket.getOutputStream();
String str = "学习java吧";
byte[] bytes = str.getBytes();
// 将信息写入输出字节流
outputStream.write(bytes);
// 应该写到finally里
outputStream.flush();
outputStream.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
服务器
- 建立服务的端口 ServerSocket
- 等待用户的连接 accept
- 接收消息
public class TCPServerDemo {
public static void main(String[] args) throws IOException {
// 声明
ByteArrayOutputStream outputStream = null;
InputStream inputStream = null;
Socket socket = null;
ServerSocket serverSocket = null;
try {
// 1. 我得有一个地址
serverSocket = new ServerSocket(9999);
while (true) {
// 2.等待客户端连接过来
socket = serverSocket.accept();
// 3.读取客户端的消息,使用输入字节流读取
inputStream = socket.getInputStream();
// 管道流(处理流)
outputStream = new ByteArrayOutputStream();
byte[] bytes = new byte[(int)inputStream.available()];
int len = 0;
// 将输入字节流中的信息读到bytes数组
while ((len = inputStream.read(bytes)) != -1) {
// 将bytes数组中的信息写入处理流
outputStream.write(bytes);
}
System.out.println(outputStream.toString());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 异常抛出省略了
outputStream.flush();
outputStream.close();
inputStream.close();
socket.close();
serverSocket.close();
}
}
}
文件上传
服务器
public class TCPServerDemo02 {
public static void main(String[] args) throws Exception{
// 1.创建服务
ServerSocket serverSocket = new ServerSocket(9000);
// 2.监听客户端的连接
Socket socket = serverSocket.accept();// 阻塞式监听,会一直等待客户端连接
// 3.获取输入流
InputStream inputStream = socket.getInputStream();
// 4. 文件输出
File file = new File("F:/sse/sse002.txt");
FileOutputStream fos = new FileOutputStream(file);
byte[] bytes = new byte[inputStream.available()];
int len = 0;
while ((len = inputStream.read(bytes)) != -1) {
fos.write(bytes,0,len);
}
// 通知客户端,接收完毕了
OutputStream outputStream = socket.getOutputStream();
outputStream.write("完毕了".getBytes());
fos.flush();
fos.close();
inputStream.close();
socket.close();
serverSocket.close();
}
}
客户端
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 outputStream = socket.getOutputStream();
// 3.文件流
File file = new File("F:/java/test.txt");
FileInputStream fis = new FileInputStream(file);
// 4.写出文件
byte[] buffer = new byte[(int)fis.available()];
int len = 0;
while ((len = fis.read(buffer)) != -1) {
outputStream.write(buffer,0,len);
}
// 通知服务器,传输完了
socket.shutdownOutput();
// 确定服务器接收完毕,才能断开连接
InputStream inputStream = socket.getInputStream();
// string byte[]
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] bytes2 = new byte[inputStream.available()];
int len2 = 0;
while ((len2 = inputStream.read(bytes2)) != -1) {
baos.write(bytes2,0,len2);
}
System.out.println(baos.toString());
fis.close();
outputStream.flush();
outputStream.close();
socket.close();
}
}
Tomcat
服务端
- 自定义 S
- Tomcat服务器 :java后台开发
客户端
- 自定义 C
- 浏览器 B
1.7 UDP
发短信:不用连接,不需要知道地址
发送消息,发送端
// 不需要链接服务器
public class UDPClientDemo01 {
public static void main(String[] args) throws Exception{
// 1.建立一个socket
DatagramSocket socket = new DatagramSocket();
// 2. 建个包
String msg = "你好,服务器";
byte[] bytes = msg.getBytes();
// 发送给谁
InetAddress localhost = InetAddress.getByName("localhost");
int port = 9090;
// 数据、数据的长度、要发给谁
DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length, localhost, port);
// 3. 发送包
socket.send(packet);
// 4.关闭socket
socket.close();
}
}
接收端
// 还是要等待客户端的连接
public class UDPServerDemo01 {
public static void main(String[] args) throws Exception{
// 开放端口
DatagramSocket socket = new DatagramSocket(9090);
// 接受数据包
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length);
socket.receive(packet); // 阻塞接收
// 打印
System.out.println(packet.getAddress().getHostAddress());
System.out.println(new String(packet.getData(),0,packet.getLength()));
// 关闭连接
socket.close();
}
}
循环发送消息
发送方:
public class UDPSenderDemo {
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[] bytes = data.getBytes();
DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length,new InetSocketAddress("localhost",8080));
socket.send(packet);
if (data.trim().equals("bye")) {
break;
}
}
socket.close();
}
}
接收方:
public class UDPReceiveDemo {
public static void main(String[] args) throws Exception{
DatagramSocket socket = new DatagramSocket(8080);
while (true) {
// 准备接收的包
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container,0,container.length);
socket.receive(packet);// 阻塞式接收包
// 接收断开连接 的消息
byte[] data = packet.getData();
String receiveData = new String(data, 0, data.length);
System.out.println(receiveData);// 打印接收消息
if (receiveData.trim().equals("bye")) {
break;
}
}
socket.close();
}
}
在线咨询:两个人可以是发送方,也都可以是接收方
发送线程
public class TestSend implements Runnable{
DatagramSocket socket = null;
BufferedReader reader = null;
private int fromPort;
private String toIP;
private int toPort;
public TestSend(int fromPort, String toIP, int toPort) {
this.fromPort = fromPort;
this.toIP = toIP;
this.toPort = toPort;
try {
socket = new DatagramSocket(fromPort);
// 准备数据 :控制台读取 System.in
reader = new BufferedReader(new InputStreamReader(System.in));
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
try {
String data = reader.readLine();
byte[] bytes = data.getBytes();
// 设置要发送的ip和端口
DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length,new InetSocketAddress(this.toIP,this.toPort));
socket.send(packet);
if (data.trim().equals("bye")) {
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
socket.close();
}
}
接收线程
public class TestReceive implements Runnable{
DatagramSocket socket = null;
private int port;
private String msgFrom;
public TestReceive(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);// 阻塞式接收包
// 接收断开连接 的消息
byte[] data = packet.getData();
String receiveData = new String(data, 0, data.length);
// 打印接收消息
System.out.println(msgFrom+":"+receiveData);
if (receiveData.trim().equals("bye")) {
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
socket.close();
}
}
调用程序
public class TalkStudent {
public static void main(String[] args) {
// 开启两个线程
new Thread(new TestSend(7777,"localhost",9999)).start();
new Thread(new TestReceive(8888,"老师")).start();
}
}
public class TalkTeacher {
public static void main(String[] args) {
new Thread(new TestSend(5555,"localhost",8888)).start();
new Thread(new TestReceive(9999,"学生")).start();
}
}
1.8 URL
统一资源定位符:定位资源的,定位网络上的某一个资源
DNS域名解析:www.baidu.com -->xxx.xxx.xxx.xxx
URL格式
协议://ip地址:端口号/项目名/资源
public class URLDemo {
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("http://192.168.53.41:8080/ump-console/organizationMessage.jsp?id=B4Vl420a5hpa2180zpzx");
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());// 参数
}
}
URL下载网络资源
public class URLDown {
public static void main(String[] args) throws Exception {
// 1.下载地址
URL url = new URL("http://192.168.53.41:8080/ump-console/img/node/ups.png");
// 2.连接到这个资源 HTTP
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
// 获取输入字节流
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("ups.png");
byte[] bytes = new byte[inputStream.available()];
int len;
while ((len = inputStream.read(bytes)) != -1) {
fos.write(bytes,0,len);// 写出数据
}
fos.flush();
fos.close();
inputStream.close();
urlConnection.disconnect();// 断开连接
}
}