网络编程
网络编程
1.IP地址
IP地址(Internet Protocol) 唯一标识网络上的每一台计算机
IP地址的组成 IPV4:32位,由4个8位二进制数组成
IPV6: 128位 十六进制的数据组成
2. 端口号
端口号标识正在计算机上运行的进程(程序)
不同的进程有不同的端口号
被规定为一个 16 位的整数 0-65535。
端口分类:
公认端口:0-1023。被预先定义的服务通信占用(如:HTTP占用端口80,FTP占用端口21,Telnet占用端口23)
注册端口:1024--49151。分配给用户进程或应用程序。(如:Tomcat占用端口8080,MySQL占用端口3306,Oracle占用端口1521等)。
动态/私有端口:49152-65535。
3. DNS
DNS:Domain Name System,域名系统
是一个分布式的数据库,负责将输入的域名解析为对应的IP地址
4. 网络5层/7层模型
网络7层模型太过理想化,最终未被实现,最终实现的是5层模型
5.Socket
端口号与IP地址的组合得出一个网络套接字:Socket。
Socket是多个计算机之间进行网络通信的载体。
6.基于TCP协议的网络编程
TCP的面向连接的 安全的 可靠的传输协议
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author WHD
* @description TODO
* @date 2024/1/26 14:25
* 服务器
*
* ServerSocket类实现
*
*/
public class Server {
public static void main(String[] args) {
System.out.println("服务器启动……………………");
ServerSocket serverSocket = null;
Socket socket = null;
BufferedReader reader = null;
InputStream inputStream = null;
try {
// 创建服务器对象 在8899端口号监听
serverSocket = new ServerSocket(8899);
// 接收请求 获取到Socket对象
socket = serverSocket.accept();
// 通过Socket对象获取到字节读取流
inputStream = socket.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream));
System.out.println("客户端发送的信息为:" + reader.readLine());
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello 客户端".getBytes());
socket.shutdownOutput();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
if(reader != null){
reader.close();
}
if(inputStream != null){
inputStream.close();
}
if(socket != null){
socket.close();
}
if(serverSocket != null){
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
import java.io.*;
import java.net.Socket;
/**
* @author WHD
* @description TODO
* @date 2024/1/26 14:25
* 客户端
*
* Socket类实现
*
*/
public class Client {
public static void main(String[] args) {
try {
// 创建Socket对象 用于发送数据
// localhost 以及 127.0.0.1 都表示本机
Socket socket = new Socket("localhost",8899);
// 通过Socket对象获取到字节写入流
OutputStream outputStream = socket.getOutputStream();
// 给服务器发送数据
outputStream.write("你好啊,服务器".getBytes());
// 关闭写入流 必须书写 相当于通知给服务器 发送完毕 服务器才能获取到这个状态 可以读取数据
socket.shutdownOutput();
InputStream inputStream = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
System.out.println("服务器响应的内容为:" + reader.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
}
7. 多客户端访问服务器
多个客户端访问同一个服务器,服务器需要单独分配不同的线程来处理客户端的请求。
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author WHD
* @description TODO
* @date 2024/1/26 15:03
*/
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8899);
while(true){
Socket socket = server.accept();
new ServerThread(socket).start();
}
}
}
import java.io.*;
import java.net.Socket;
/**
* @author WHD
* @description TODO
* @date 2024/1/26 15:05
* 处理请求的线程类
*/
public class ServerThread extends Thread {
private Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
InputStream inputStream = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
System.out.println("客户端发送的信息为:" + reader.readLine());
OutputStream outputStream = socket.getOutputStream();
outputStream.write("别问了,睡了".getBytes());
socket.shutdownOutput();
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.*;
import java.net.Socket;
/**
* @author WHD
* @description TODO
* @date 2024/1/26 15:02
* 客户端1
*/
public class Client1 {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 8899);
OutputStream outputStream = socket.getOutputStream();
outputStream.write("睡了吗?".getBytes());
socket.shutdownOutput();
InputStream inputStream = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
System.out.println("客户端的回话是:" + reader.readLine());
}
}
import java.io.*;
import java.net.Socket;
/**
* @author WHD
* @description TODO
* @date 2024/1/26 15:02
* 客户端1
*/
public class Client2 {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 8899);
OutputStream outputStream = socket.getOutputStream();
outputStream.write("真的睡了吗?".getBytes());
socket.shutdownOutput();
InputStream inputStream = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
System.out.println("客户端的回话是:" + reader.readLine());
}
}
import java.io.*;
import java.net.Socket;
/**
* @author WHD
* @description TODO
* @date 2024/1/26 15:02
* 客户端1
*/
public class Client3 {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 8899);
OutputStream outputStream = socket.getOutputStream();
outputStream.write("确定睡了吗?".getBytes());
socket.shutdownOutput();
InputStream inputStream = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
System.out.println("客户端的回话是:" + reader.readLine());
}
}
8.TCP协议三次握手四次挥手
TCP需要三次握手建立连接,四次挥手断开连接,过程非常复杂,麻烦,但是通过这种方式可以保证数据的安全性。
TCP协议的三次握手:
第一次:客户端向服务器发送连接请求
第二次:服务器向客户端响应连接请求
第三次:客户端与服务器建立连接
TCP协议的四次挥手:
第一次:客户端向服务器发送断开连接请求
第二次:服务器向客服端响应收到断开连接请求(因为TCP连接是双向的,所以此时服务器依然可以 向客户端发送信息)
第三次:客户端等待服务器发送信息完成,向服务器确定全部信息发送完毕,并且断开客户端与服务器的连接
第四次:服务器向客户端断开连接
9.UDP协议编程
UDP 用户数据报协议 非面向连接的 不安全 不可靠的 但是效率高的传输协议
import java.io.IOException;
import java.net.*;
/**
* @author WHD
* @description TODO
* @date 2024/1/26 15:28
* 基于UDP协议的数据传输
*
* DataGramPacket实现
*/
public class Client {
public static void main(String[] args) throws IOException {
// 定义发送信息的字符串
String msg = "hello ,服务器";
// 将字符串转换为byte数组
byte[] data = msg.getBytes();
// 根据字符串获取到InetAddress对象
InetAddress localhost = InetAddress.getByName("localhost");
// 构造DataGramPacket 对象 用于保存数据
DatagramPacket sendPacket = new DatagramPacket(data,data.length,localhost,8899);
// 创建Socket对象 用于发送数据包
DatagramSocket socket = new DatagramSocket();
// 发送数据
socket.send(sendPacket);
System.out.println("-------------------------开始读取数据-----------------------------");
byte [] receiveData = new byte[10];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
socket.receive(receivePacket);
byte[] byteData = receivePacket.getData();
System.out.println(new String(byteData,0,byteData.length));
}
}
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;
/**
* @author WHD
* @description TODO
* @date 2024/1/26 15:31
* 服务器
* DataGramSocket实现
*/
public class Server {
public static void main(String[] args) throws IOException {
// 创建Socket对象 用于接收数据报包
DatagramSocket socket = new DatagramSocket(8899);
// 定义数组长度为8 表示可以接收8个字节的数据
byte [] bag = new byte[8];
// 构造DataGramPacket对象 用于保存数据
DatagramPacket receivePacket = new DatagramPacket(bag,bag.length);
// 接收数据 数据将保存在 DataGramPacket对象中
socket.receive(receivePacket);
// 调用getData()方法 获取数据
byte[] data = receivePacket.getData();
// 将获取到数据 转换为字符串
System.out.println(new String(data,0,data.length));
System.out.println("-------------------开始回复信息------------------------");
String msg = "你好呀 客户端 ";
byte [] sendData = msg.getBytes();
SocketAddress socketAddress = receivePacket.getSocketAddress();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, socketAddress);
socket.send(sendPacket);
}
}