1、什么是网络编程
在网络通讯协议下,不同计算机上运行的程序,进行数据的传输
2、常见的软件架构
C/S
Client/Server 客户端/服务器 ,在用户本地需要下载并安装客户端程序,在远程有一个服务器端程序
B/S
Browser/Server 浏览器/服务器 ,只需要一个浏览器,用户通过不同的网址,客户访问不同的服务器
3、网络编程三要素
IP
设备在网络中的地址,是唯一的标识 常见的是(IPV4/IPV6)
Internet Protocol 是互联网协议地址,也成IP地址,是分配给上网设备的数字标签
IPV4 32bit4字节 分成4组 点分10进制 最多2的32次方个IP
IPV6 128bit8字节 分成8组 冒分16进制 最多2的128次方个IP
// InetAddress类的使用 public class MyInetAddressDemo01 { public static void main(String[] args) throws UnknownHostException { // 1.获取InetAddress对象 InetAddress inetAddress = InetAddress.getByName("Xin"); System.out.println(inetAddress); // 2.调用inetAddress里面的方法 String hostName = inetAddress.getHostName(); System.out.println(hostName); String ip = inetAddress.getHostAddress(); System.out.println(ip); } }
端口
应用程序在设备中唯一的标识
由两个整数组成,取值范围0~65535,0~1023之间用于一些知名的网络服务或应用
一个端口号只能被一个应用程序使用
协议
数据在网络中传输的规则,常见的协议有UDP,TCP,HTTP,HTTPS,FTP
UDP协议:
用户数据报协议,UDP是面向无连接通信协议,
速度快,有大小限制,一次最多发送64k,数据不安全,易丢失数据,不管是否连接成功
// UDP发送数据 public class InetDemo02 { public static void main(String[] args) throws IOException { /** * 创建发送端的DatagramSocket * 数据打包DatagramPacket * 发送数据 * 释放资源 */ // 1、创建发送端的DatagramSocket DatagramSocket ds = new DatagramSocket(); // 2、数据打包DatagramPacket String str = "Hello Word"; byte[] bys = str.getBytes(); InetAddress inetAddress = InetAddress.getByName("127.0.0.1"); int port = 10086; DatagramPacket dp = new DatagramPacket(bys,bys.length,inetAddress,port); // 3、发送数据 ds.send(dp); // 4、释放资源 ds.close(); } }
// UDP接收数据 // UDP接收数据 public class InetDemo03 { public static void main(String[] args) throws IOException { /** * 1.创建接收端的Socket对象(DatagramSocket) * 2.创建一个数据包,用于接收数据 * 3.调用接收数据的方法接收数据 * 4.解析数据包 * 5.释放资源 */ // 1.创建接收端的Socket对象(DatagramSocket) 端口与发送的端口一致 DatagramSocket ds = new DatagramSocket(10086); // 2.创建一个数据包,用于接收数据 byte[] bys = new byte[1024]; // 3.调用接收数据的方法接收数据 DatagramPacket dp = new DatagramPacket(bys, bys.length); // 该方法是阻塞的,直到接收到数据,才会继续向下执行 ds.receive(dp); // 4.解析数据包 byte[] data = dp.getData(); int length = dp.getLength(); InetAddress address = dp.getAddress(); int port = dp.getPort(); System.out.println(new String(data, 0, length)); System.out.println(address.getHostAddress() + ":" + port); System.out.println("接收完毕"); // 5.释放资源 ds.close(); } }
聊天室的例子 先启动接收端,再启动发送端
public class SendMessageDemo { public static void main(String[] args) throws IOException { // 发送数据 /** * 创建发送端的DatagramSocket * 数据打包DatagramPacket * 发送数据 * 释放资源 */ // 1.创建发送端的DatagramSocket 无参构造方法,系统会随机分配一个端口 DatagramSocket ds = new DatagramSocket(); // 2.打包数据,键盘录入 Scanner sc = new Scanner(System.in); System.out.println("请输入要发送的数据:"); // 快捷键 ctrl+alt+T while (true) { String s = sc.nextLine(); if ("886".equals(s)) { break; } byte[] bytes = s.getBytes(); // 3.发送的IP地址和端口 InetAddress inetAddress = InetAddress.getByName("127.0.0.1"); int port = 10086; // 4.打包数据 DatagramPacket dp = new DatagramPacket(bytes, bytes.length, inetAddress, port); // 5.发送数据 ds.send(dp); } // 6.释放资源 ds.close(); } } public class ReceiveMessageDemo { public static void main(String[] args) throws IOException { // 接收数据 不知道发送端什么时候截止, 所以需要循环接收 /** * 1.创建接收端的Socket对象(DatagramSocket) * 2.创建一个数据包,用于接收数据 * 3.调用接收数据的方法接收数据 * 4.解析数据包 * 5.释放资源 */ // 1.创建接收端的Socket对象(DatagramSocket) DatagramSocket ds = new DatagramSocket(10086); // 2.创建一个数据包,用于接收数据 byte[] bytes = new byte[1024]; DatagramPacket dp = new DatagramPacket(bytes, bytes.length); while (true) { ds.receive(dp); // 3.解析数据包 byte[] data = dp.getData(); int length = dp.getLength(); String ip = dp.getAddress().getHostAddress(); String name = dp.getAddress().getHostName(); // 4.打印 System.out.println("ip为:"+ip+"的"+name+"发送的数据为:"+new String(data,0,length)); } } }
TCP协议
传输控制协议TCP
TCP协议是面向连接的通信协议,速度慢,没有大小限制,数据安全,发送前先确保连接成功
三次握手,四次挥手协议
三次握手协议保证连接建立
四次挥手利用这个协议断开连接,而且保证连接通道里面的数据已经处理完毕
// Client public class TCPDemo01 { public static void main(String[] args) throws IOException { // 客户端发送数据 // 1. 创建一个Socket对象,指定服务器的IP地址和端口号 Socket scoket = new Socket("127.0.0.1", 8888); // 2.可以从连接通道中获取一个输出流,用于向服务器发送数据 OutputStream outputStream = scoket.getOutputStream(); // 3. 使用输出流发送数据 outputStream.write("aaa".getBytes()); // 4. 关闭连接 outputStream.close(); scoket.close(); } }
// Service public class TCPDemo02 { public static void main(String[] args) throws IOException { // 服务端接收数据 // 1.创建服务端对象 ServerSocket serverSocket = new ServerSocket(8888); // 2.监听客户端连接 Socket accept = serverSocket.accept(); // 3.获取输入流 InputStream inputStream = accept.getInputStream();会出现乱码 // 提高效率的话可以再加一个缓冲流 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream())); // 4.循环读取数据 int b; while ((b = bufferedReader.read()) != -1){ System.out.print((char)b); } // 5.关闭资源 bufferedReader.close(); accept.close(); } }
4.三次握手,四次挥手协议
三次握手:
第一次握手,客户端发送SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态。 (客户端向服务器端发出连接请求,等待服务器确认。) 第二次握手,服务器端收到SYN报文,回应一个SYN (SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。(服务器端向客户端回送一个响应,通知客户端收到了连接请求。) 第三次握手,客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。(客户端再次向服务器端发送确认信息,确认连接。)
四次挥手:
客户端打算关闭连接,此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文,也即 FIN 报文,之后客户端进入 FIN_WAIT_1 状态。 服务端收到该报文后,就向客户端发送 ACK 应答报文,接着服务端进入 CLOSED_WAIT 状态。 客户端收到服务端的 ACK 应答报文后,之后进入 FIN_WAIT_2 状态。 等待服务端处理完数据后,也向客户端发送 FIN 报文,之后服务端进入 LAST_ACK 状态。 客户端收到服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态 服务器收到了 ACK 应答报文后,就进入了 CLOSE 状态,至此服务端已经完成连接的关闭。 客户端在经过 2MSL 一段时间后,自动进入 CLOSE 状态,至此客户端也完成连接的关闭。
-
三次握手 A:我要过来了!B:我知道你要过来了!A:我现在过来!
-
四次挥手 A:我们分手吧!B:真的分手吗?B:真的真的要分手吗?A:是的!