java基础-网络编程

2024-04-17

IP地址

IPV4

是一个32位的二进制数,通常分为4个字节。表示成a.b.c.d的形式,以点分十进制表示;a、b、c、d都是0~255之间的十进制整数
分为4类
	A 0.0.0.0 到 127.255.255.255
	B 128.0.0.0 到 191.255.255.255
	C 192.0.0.0 到 223.255.255.255
	D 224.0.0.0 到 239.255.255.255
	D 240.0.0.0 到 247.255.255.255

IPV6

采用128位地址长度,共16个字节,写成8ge无符号整数,每个整数用4个十六进制为表示,树之间用冒号(:)分开

192.168开头的都是私有地址

端口号

可以唯一标识主机中的进程(应用程序)
范围0~65535,公认端口(被预先定义的服务通信占用)0~1023,注册端口(分配给用户进程或应用程序)1024~49151,动态/私有端口:49152~~65535

网络通信协议

通信协议分层思想

同层间可以通信、上一层可以调用下一层,而与再下一层不发生关系

OSI模型

是一个理想的模型、未能广泛推广
应用层              为应用程序提供服务
表示层              数据格式转化、数据加密
会话层              建立、管理和维护会话
传输层              建立、管理和维护端对端的连接
网络层              IP地址及路由选择 
数据链路层      提供介质访问和链路管理
物理层              物理传输

TCP/IP模型

是事实上的国际标准
应用层                        对应OSI应用层、表示层、会话层;有HTTP、FTP、Telnet、DNS协议
传输层                        对应OSI传输层;有TCP、UDP协议
网络层                        对应OSI网络层;有IP、ICMP、ARP协议
物理+数据连接层       对应OSI数据链路层、物理层;有Link协议

TCP协议

使用前需要先家里TCP连接,形成基于字节流的传输数据通道
传输前使用3次握手方式,点对点通信,是可靠的
使用重发机制,当另一个通信实体没有确认信息,则会再次重复刚才会送的消息
在连接中可进行大数据量的传输
传输完毕,需释放以建立的连接,效率低
释放连接时需要经过4次挥手

三次握手

第一次握手,客户端向服务器端发起TCP连接的请求;客户端发送syn报文,并置发送序号为X
第二次握手,服务端发送针对客户端TCP连接请求的确认;服务端发送syn+ACK报文,并置发送序号为Y,在确认需要为X+1
第三次握手,客户端发送确认的确认;客户端发送ACK报文,并置发送序号为Z,在确认需要为Y+1

四次挥手

第一次挥手:客户端向服务端提出结束连接,让服务器做最后的准备工作。
                    此时,客户端处于半关闭状态,即表示不在向服务器发送数据了,但是还可以接受数据;客户端发送Fin+Ack报文,并置发送序号为X
第二次挥手:服务器接收到客户端释放连接的请求后,会将最后的数据发送给客户端。
                    并告知上层的应用进程不在接收数据;服务端发送ACK报文,并置发送序号为Z,在确认序号为X+1
第三次挥手:服务器发送完数据后,会给客户端发送一个释放连接的报文。那么客户端接收后就知道可以正式释放连接了;
                    服务端发送Fin+Ack报文,并置发送序号为Y,在确认序号为X。
第四次挥手:客户端接收到服务器最后的释放连接报文,要回复一个彻底断开的报文。这样服务器收到后才会彻底释放连接。
                    这里客户端,发送完最后的报文后,会等待2MSL。因为有可能服务器没有收到最后的报文,那么服务器迟迟没收到,就会再次给客户端发送释放连接的报文,此时客户端在等待时间范围内接收到,会重新发送最后的报文,并重新计时。
                    如果等待2MSL后没有收到,那么彻底断开;客户端发送ACK报文,并置发送序号为X,在确认序号为Y

UDP协议

进行通信的两个应用进程:发送端、接收端
将数据、源、目的封装成数据包(传输的基本单位),不需要建立连接
发送不管对方是否准备好,接收方收到也不确认,不能保证数据的完整性,是不可靠的
每个数据报的大小限制在64K内
发送数据结束时无需释放资源,开销小,通信效率高
适用场景:音频、视频和普通数据的传输。例如视频会议

InetAddress类

代表一个IP地址的类

方法

// 获取指定IP地址/域名的InetAddress实例,P地址/域名不存在时会抛UnknownHostException
static InetAddress getByName(String host)
// 获取本机地址的InetAddress实例
static InetAddress getLoclHost()
// 获取域名
getHostName()
// 获取地址
getHostAddress()

Socket类

网络上具有唯一标识的IP地址和端口号组合在一起构成唯一能标识的标识符套接字

方法

// 获取socket的ip地址
InetAddress getInetAddress()
// 表明不在发送数据
shutdownOutput()

示例

public void client() {
	try {
		InetAddress inetAddress = InetAddress.getLoclHost();
		int port = 8989;
		Socket socket = new Socket(inetAddress, port);
		OutputStream out = socket.getOutputStream();
		out.write("你好,我是客户端".getBytes());
	} catch (IOException e) {

	} finally {
		try {
			if (out != null) {
				out.close();
			}
		} catch (IOException e) {
			
		}
		try {
			if (socket != null) {
				socket.close();
			}
		} catch (IOException e) {
			
		}
	}
}

public void server() {
	try {
		int port = 8989;
		ServerSocket serverSocket = new ServerSocket(8989);
		// 阻塞式的方法
		Socket socket = serverSocket.accept();
		InputStream is = socket.getInputStream();
		byte[] buffer = new byte[1024];
		// 内部维护了一个byte数组
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		int len;
		while ((len = is.read(buffer)) != -1) {
			baos.write(buffer, 0, len);
		}
		System.out.println(baos.toString())
	} catch (IOException e) {

	} finally {
		try {
			if (baos != null) {
				baos.close();
			}
		} catch (IOException e) {
			
		}
		try {
			if (is != null) {
				is.close();
			}
		} catch (IOException e) {
			
		}
		try {
			if (socket != null) {
				socket.close();
			}
		} catch (IOException e) {
			
		}
		try {
			// 一般来说,服务端不关闭,一直等待客户端发送数据
			if (serverSocket != null) {
				serverSocket.close();
			}
		} catch (IOException e) {
			
		}
	}
	
}

发送文件示例

public void client() {
	try {
		InetAddress inetAddress = InetAddress.getLoclHost();
		int port = 8989;
		Socket socket = new Socket(inetAddress, port);
		File file = new File("pic.jpg");
		FileInputStream fileInputStream = new FileInputStream(file);
		OutputStream out = socket.getOutputStream();
		byte[] buffer = new byte[1024];
		int len;
		while ((len = is.read(buffer)) != -1) {
			out.write(buffer, 0, len);
		}
		socket.shutdownOutput();
		InputStream is = socket.getInputStream();
		byte[] buffer1 = new byte[1024];
		// 内部维护了一个byte数组
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		int len;
		while ((len = is.read(buffer1)) != -1) {
			baos.write(buffer1, 0, len);
		}
		System.out.println(baos.toString())
	} catch (IOException e) {

	} finally {
		try {
			if (baos != null) {
				baos.close();
			}
		} catch (IOException e) {
			
		}
		try {
			if (fileInputStream != null) {
				fileInputStream.close();
			}
		} catch (IOException e) {
			
		}
		try {
			if (is != null) {
				is.close();
			}
		} catch (IOException e) {
			
		}
		try {
			if (out != null) {
				out.close();
			}
		} catch (IOException e) {
			
		}
		try {
			if (socket != null) {
				socket.close();
			}
		} catch (IOException e) {
			
		}
	}
}

public void server() {
	try {
		int port = 8989;
		ServerSocket serverSocket = new ServerSocket(8989);
		// 阻塞式的方法
		Socket socket = serverSocket.accept();
		InputStream is = socket.getInputStream();
		byte[] buffer = new byte[1024];
		File file = new File("pi1c.jpg");
		FileOutputStream fileOutputStream = new FileOutputStream(file);
		int len;
		while ((len = is.read(buffer)) != -1) {
			fileOutputStream.write(buffer, 0, len);
		}


		OutputStream out = socket.getOutputStream();
		out.write("服务端已接收".getBytes());
	} catch (IOException e) {

	} finally {
		try {
			if (fileOutputStream != null) {
				fileOutputStream.close();
			}
		} catch (IOException e) {
			
		}
		try {
			if (out != null) {
				out.close();
			}
		} catch (IOException e) {
			
		}
		try {
			if (is != null) {
				is.close();
			}
		} catch (IOException e) {
			
		}
		try {
			if (socket != null) {
				socket.close();
			}
		} catch (IOException e) {
			
		}
		try {
			// 一般来说,服务端不关闭,一直等待客户端发送数据
			if (serverSocket != null) {
				serverSocket.close();
			}
		} catch (IOException e) {
			
		}
	}
}

DatagramScoket类

public void sender() {
	DatagramScoket datagramScoket = new DatagramScoket();
	InetAddress inetAddress = InetAddress.getLoclHost();
	int port = 8989;
	byte[] bytes = "我是发送端".getBytes();
	// 打包要发送的数据报,包含要发送的数据和接受端的ip和端口
	DatagramPacket packet = new DatagramPacket(bytes, 0 bytes.length, inetAddress, port);
	datagramScoket.send(packet);
	datagramScoket.close();
}
public void receiver() {
	int port = 8989;
	DatagramScoket datagramScoket = new DatagramScoket(port);
	byte[] bytes = new byte[1024 * 64];
	// 创建数据报的对象,用于接收发送端发送过来的数据
	DatagramPacket packet = new DatagramPacket(bytes, 0 bytes.length);
	datagramScoket.receive(packet);

	byte[] recData = packet.getData();
	System.out.println(new String(recData, 0, recData.getLength()))
	datagramScoket.close();
}

URL

统一资源定位符,一个具体的url就对应着互联网上某一资源的地址

URL类

方法

 // 创建一个url地址的类
URL url = new URL(String str);
// 获取该URL的协议名
String getProtocol()
// 获取该URL的主机名
String getHost()
// 获取该URL的端口号
String getPort()
// 获取该URL的文件路径
String getPath()
// 获取该URL的文件名
String getFile()
// 获取该URL的查询名
String getQuery()
// 获取url连接
URLConnection openConnection()

URLConnection类

// 获取输入流
InputStream getInputStream()
// 关闭url连接
disconnect()


{/if}