Java网络编程

文章目录

    • 一、网络模型—OSI模型
        • OSI网络七层模型
        • 五层模型
    • 二、TCP/IP协议
        • TCP报文
      • TCP的三次握手
        • 为什么要三次握手?
      • TCP的四次挥手
        • 为什么需要等待2MSL?
    • 四、Socket编程(TCP)
    • Socket编程(UDP)

一、网络模型—OSI模型

OSI网络七层模型

  • 物理层:
    定义设备标准,如网线的接口类型、管线的接口类型、各种传输介质的传输速率等

  • 链路层:
    数据链路层,定义了如何让格式化数据进行传输,以及如何让控制对物理介质的访问。这一层通常还提供错误检测和纠正,以确保数据的可靠传输。

  • 网络层:
    将数据传输到目标地址;目标地址可以使多个网络通过路由器连接而成的某一个地址,主要负责寻找地址和路由选择,网络层还可以实现拥塞控制、网际互连等功能在这一层,数据的单位称为数据包(packet)
    网络层协议的代表包括:IP、IPX、RIP、OSPF等

  • 传输层:
    提供端到端的服务,可以实现流量控制、负载均衡。传输层信息包括端口、控制字和校验和。传输层协议主要是TCP和UDP。传输层位于OSI的第四层,这层使用的设备时主机本身。

  • 会话层:
    维持通讯 ,记录断点。 http、session
    负责建立和断开通信连接(数据流动的逻辑通路),记忆数据的分隔等数据传输相关的管理

  • 表示层:
    格式转换、数据压缩
    将应用处理的信息转换为适合网络传输的格式,或将来自下一层的数据转换为上层能够处理的格式;主要负责数据格式的转换,确保一个系统的应用层信息可被另一个系统应用层读取具体来说,就是将设备固有的数据格式转换为网络标准传输格式,不同设备对同一比特流解释的结果可能会不同;因此,主要负责使它们保持一致

  • 应用层:
    直接面向用户的程序或服务。包括系统程序和用户程序,比如www、FTP、DNS、POP3和SMTP等都是应用层服务。HTTP,FTP,SMTP,HTTPS协议,网络服务协议

五层模型

  • 应用层(把应用层、表示层、会话层合并为应用层)
    Java网络编程_第1张图片

二、TCP/IP协议

(传输层TCP/网络层IP)

TCP报文

  • 序号:Seq(Sequence Number)序号占32位,用来标识从计算机A发送到计算机B的数据包的序号,计算机发送数据时对此进行标记。

  • 确认号:Ack(Acknowledge Number)确认号占32位,客户端和服务器端都可以发送,Ack = Seq + 1。

  • 标志位:每个标志位占用1Bit,共有6个,分别为 URG、ACK、PSH、RST、SYN、FIN,具体含义如下:

  • SYN:建立一个新连接。

  • FIN:断开一个连接。
    Java网络编程_第2张图片

TCP的三次握手

Java网络编程_第3张图片

为什么要三次握手?

  • 为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误

客户端发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达服务器。
本来这是一个早已失效的报文段。但服务器收到此失效的连接请求报文段后,就误认为是客户端再次发出的一个新的连接请求。于是就向客户端发出确认报文段,同意建立连接。
客户端不会向服务器的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。

TCP的四次挥手

Java网络编程_第4张图片

为什么需要等待2MSL?

MSL是Maximum Segment Lifetime英文的缩写,即"报文最大生存时间", 他是任何报文在网络中存在的最长时间,超过这个时间报文将被丢弃。2MSL即2倍的报文最大存活时间。

当主动发起关闭方发送完最后一个ACK包后无法确认对方是否有收到这个ACK包,所以2MSL的时间能保证如果对方没收到会重发第三次挥手的FIN包,且这个包有足够的时候发送回来。

如果在这个时间内还没收到重发的FIN包,便可以证明对方已收到该ACK包。在TIME_WAIT状态时两端的端口不能使用,要等到2MSL时间结束才可继续使用。当连接处于2MSL等待阶段时任何迟到的报文段都将被丢弃。

在实际应用中可以通过设置SO_REUSEADDR选项达到不必等待2MSL时间结束再使用此端口。

四、Socket编程(TCP)

Socket: 套接字,抽象对象,通过Socket的编程,完成网络编程。

public class TCPServer {

	public static void main(String[] args) throws Exception {

		final int PORT = 9090;

		// 创建ServerSocket,指定端口
		ServerSocket server = new ServerSocket(PORT);
		System.out.println("服务器启动成功....");

		boolean f = true;
		while (f) {
			// 监听端口,等待客户端请求
			Socket socket = server.accept();
			
			// 解析
			
			InputStream stream = socket.getInputStream();
			
			InputStreamReader in = new InputStreamReader(stream,"utf-8");
			
			char[] buffer = new char[64];
			
			while(in.read(buffer)!=-1) {
				String line= new String(buffer);
				System.out.print(line);
				Arrays.fill(buffer, (char)0);//清空buffer
			}
			System.out.println();

		

		}
		server.close();

	}

}

public class TCPClient {

	public static void main(String[] args) throws Exception {
		final int PORT = 9090;

		final String HOST = "127.0.0.1"; // ip地址

		Scanner sc = new Scanner(System.in);

		Socket socket = new Socket(HOST, PORT);
		while (true) {

			System.out.print("请问输入: ");
			String s = sc.nextLine();

			OutputStream out = socket.getOutputStream();

			OutputStreamWriter ow = new OutputStreamWriter(out);

			ow.write(s);

			ow.flush();
			socket.close();
		}

		//

	}

}

Socket编程(UDP)

/**
 * 接收端
 * 
 * @author Administrator
 *
 */
public class UDPServer {

	public static void main(String[] args) throws IOException {
		final int PORT = 9090;

		DatagramSocket socket = new DatagramSocket(PORT);
		
		System.out.println("接收端启动......");
		
		byte[] buffer =new byte[1024];
		
		DatagramPacket  packet =
				new DatagramPacket(buffer, buffer.length);
		
		socket.receive(packet);
		
		String msg = new String(packet.getData());
		System.out.println("[接收端] 收到数据>>>" + msg);
		socket.close();

	}

}

package com.dyit.udp;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/**
 * 发送端
 * 
 * @author Administrator
 *
 */
public class UDPClient {

	public static void main(String[] args) throws Exception {
		final int PORT = 9090;
		final String HOST = "127.0.0.1";
		
		DatagramSocket socket = new DatagramSocket();
		
		String msg = "测试发送端发送一条信息";
		byte[] buffer = msg.getBytes();
		DatagramPacket packet = new DatagramPacket(
				buffer, 
				buffer.length, 
				InetAddress.getByName(HOST),
				PORT);
		
		System.out.println("[发送端]发送信息..............");
		socket.send(packet);
		socket.close();
	}
	
}

package com.singleton;

import java.lang.invoke.MethodHandle;
import java.lang.reflect.Method;


/**
 * 反射 ——invoke()方法的使用
 * @author wdy
 *
 */
public class MethodDemo {
	static class Car {
		private String brand;
		private String color;
		private double price;

		public void setBrand(String brand) {
			this.brand = brand;
		}

		public void setColor(String color) {
			this.color = color;
		}

		public void setPrice(double price) {
			this.price = price;
		}

		public String getBrand() {
			return brand;
		}

		public String getColor() {
			return color;
		}

		public double getPrice() {
			return price;
		}

		public void run() {
			System.out.println("跑的飞快.....");
		}

		@Override
		public String toString() {
			return "Car [brand=" + brand + ", color=" + color + ", price=" + price + "]";
		}

	}

	public static void main(String[] args) throws Exception {
		
		

		Car c = new Car();
		c.setBrand("蔚蓝");
		c.setColor("浅蓝色");
		c.setPrice(300000.00);
		
		
		Class<Car> clazz = Car.class;//先访问class对象
		
		//Method[] methods = clazz.getDeclaredMethods();
		Method method = clazz.getDeclaredMethod("run");//  再访问run方法 。访问run方法
		method.invoke(c); //c对象调用当前方法    无参数  invoke()
		
		Method setMethod = clazz.getDeclaredMethod("setColor", String.class);//(方法名,参数类型)
		
		setMethod.invoke(c, "黑白色");//(对象,传入实际参数)不带返回值
		
		System.out.println(c);
		
		Method getMethod = clazz.getDeclaredMethod("getPrice");
		Object retVal = getMethod.invoke(c);//带返回值的 
		System.out.println(retVal);

	}
}

你可能感兴趣的:(网络,java,网络协议)