• 第62节:探索Java中的网络编程技术


    标题图

    前言

    感谢! 承蒙关照~

    探索Java中的网络编程技术

    网络编程就是io技术和网络技术的结合,网络模型的定义,只要共用网络模型就可以两者连接.网络模型参考.

    osi模型

    TCP/IP参考模型

    一座塔有七层,我们需要闯关.

    第一层物理层->第二层数据链路层->第三层网络层->第四层传输层->第五层会话层->第六层表示层->第七层应用层.

    物理层是主要定义物理设备标准,数据链路层是主要讲从物理层接收的数据进行MAC地址(网卡的地址)的封装与解封装.这层的数据较帧.

    网络层是将从下层接收到的数据进行IP地址的封装和解封装.传输层是定义一些传输数据的协议和端口号.

    会话层是将通过传输层建立数据传输的通路.表示层是进行对接收的数据进行解释,加密与解密.

    应用层主要是一些终端的应用.

    应用层 --> 传输层 --> 网络层 --> 主机至网络层

    效果

    效果

    电脑通讯要点:
    一需要IP地址:InetAddress(互联网协议即是规则)
    二需要端口号
    三需要传输协议

    IP地址,网络中设备的标识,不容易记住,可以用主机名,本地回环地址: 127.0.0.1 主机名就是 localhost了.所谓局域网就是局部范围内的,互联网就是全球的.

    端口号是用来标识进程的逻辑地址,不同进行的标识,有效的端口为0到65535,其中0到1024系统使用或保留的端口.

    传输协议即是通讯的规则,常见的协议为TCP, UDP.

    java.net

    InetAddress

    java.lang.Object
    -> java.net.InetAddress
    

    所有已实现的接口有:

    Serializable
    

    直接已知子类:

    Inet4Address, Inet6Address
    
    public class InetAddress extends Object implements Serializable
    

    这个类表示互联网协议已地址.

    效果

    地址类型

    Class Inet6Address

    java.lang.Object
    java.net.InetAddress
    java.net.Inet6Address
    
    public final class Inet6Address extends InetAddress
    

    效果

    获取ip地址:

    public class IPDemo {
     public static void main(String[] args) throws UnknownHostException {
      //获取本地主机地址对象
      InetAddress ip = InetAddress.getLocalHost();
      System.out.println(ip.getHostAddress() + ":" + ip.getHostName());
     }
    }
    

    域名解析

    C:WINDOWSsystem32driversetc
    

    InetAddress方法

    类型 方法 说明
    boolean equals(Object obj) 将此对象与指定对象进行比较
    byte[] getAddress() 返回此InetAddress对象的原始ip地址.
    static InetAddress[] getAllByName(String host) 给定主机的名称,根据系统上配置的名称服务返回其ip地址数组.
    static InetAddress getByAddress(byte[] addr) 给出原始IP地址的InetAddress对象
    static InetAddress getByAddress(String host, byte[] addr) 根据提供的主机名和ip地址创建InetAddress
    static InetAddress getByName(String host) 确定主机名称的ip地址
    String getCanonicalHostName() 获取此ip地址的完全限定域名
    String getHostAddress() 返回文本显示中的ip地址字符串
    String getHostName() 获取此ip地址的主机名

    网络编程:

    1,网络模型:7层—>4层

    端口

    1. 用于标识进程的逻辑地址,不同进程的标识
    2. 有效端口:0到65535,而0到1024系统使用或保留端口

    传输协议

    常见协议TCP``UDP

    TCP和UDP的区别:

    TCP: 面向连接,通过三次握手完成,速度慢,可靠。
    UDP: 面向无连接,速度快,不可靠。

    UDP是将数据及其源和目的封装成数据包中,不需要建立连接,每个数据报的大小在限制在64k内,因无连接,是不可靠的协议,不需要连接,但是速度快.

    TCP是需要进行连接的,形成传输数据的通道,在连接中进行大数据量传输,通过三次握手完成连接,是可靠的协议,效率低即是速度慢一点.

    网络编程-Socket

    网络通讯的要素:

    1. ip
    2. 端口
    3. 传输协议

    ip是用于标识网络中主机的数字标识,而端口是用于标识应用程序的数字,还有传输协议是用于进行数据传输的规则.

    实现UDP的通信,TCP传输:客户端,服务端.

    Socket是网络服务提供的一种机制,是通信两端必备的,都要有Socket,网络通信其实就是Socket间的通信,数据在两个Socket间通过io传输.

    两端发送端和接收端-UDP

    UDP发送端Demo

    public class UDPSend{
     public static void main(String[] args){
      System.out.println("udp发送端");
     }
    }
    

    DatagramSocket

    public class DatagramSocket extends Object
    

    此类表示用来发送和接收数据报包的套接字.

    数据报套接字是包投递服务的发送或接收点.每个在数据报套接字上发送或接收的包都是单独编址和路由的.从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达.

    DatagramSocket上总是启动UDP广播发送.为了接收广播包,将DatagramSocket绑定到通配符地址.

    效果

    void receive(DatagramPacket p)
    从此套接字接收数据报包
    send(DatagramPacket p)
    从此套接字发送数据报包
    
    public class UDPSend{
     public static void main(String[] args) throws IOException{
      System.out.println("udp发送端");
      DatagramSocket ds = new DatagramSocket();
      String text = "hello";
      byte[] buf = text.getBytes();
      // 将数据转成字节数组
      DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("123.23232.323.2"),10000);
      ds.send(dp);
      ds.close();
     }
    }
    // 建立upd的socket,具备发送或接收功能
    // 将数据封装到数据包中,数据包对象是DatagramPacket.
    // 使用socket对象的send方法将数据包发出去.
    // 关闭资源
    

    udp接收端

    public class updDemo {
     public static void main(String[] args) throws IOException {
      System.out.println("udp 接收端");
      // 先有udpsocket服务
      // 接收数据
      DatagramSocket ds = new DatagramSocket();
      byte[] buf = new byte[1024];
      DatagramPacket dp = new DatagramPacket(buf, buf.length);
      ds.receive(dp);
      String ip = dp.getAddress().getHostAddress();
      int port = dp.getPort():
      String text = new String(dp.getData(),0,dp.getLength());
      // 关闭资源。
      ds.close();
     }
    }
    

    receive

    public void receive(DatagramPacket p) throws IOException
    此套接字接收数据报包
    

    实现UDP的通信,udp传输涉及的两个对象,即可以发送,又可以接收.TCP传输:客户端,服务端.

    UDP键盘输入

    public class UDPSend {
    	public static void main(String[] args) throws IOException {
    		System.out.println("udp 发送端 run");
    //		1,建立udp的socket它具备者发送或者接收功能。
    		DatagramSocket ds = new DatagramSocket(9999);
    //		2,将数据封装到数据包中。数据包对象是DatagramPacket。数据来自于键盘录入。
    		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
    		String line = null;
    		while((line=bufr.readLine())!=null){
    			if("over".equals(line)){
    				break;
    			}
    			byte[] buf = line.getBytes();//将数据转成字节数组。
    //			将字节数组封装到数据包中。
    			DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.223"), 10001);
    //			3,使用socket对象的send方法将数据包发送出去。
    			ds.send(dp);
    		}
    //		4,关闭资源。
    		ds.close();
    	}
    }
    
    public class UDPRece {
    	public static void main(String[] args) throws IOException {
    		System.out.println("udp2 接收端 run");
    		DatagramSocket ds = new DatagramSocket(10001);
    		while (true) {
    			// 2,接收数据。
    			// 3,先定义数据包。
    			byte[] buf = new byte[1024];
    			DatagramPacket dp = new DatagramPacket(buf, buf.length);
    			ds.receive(dp);
    			// 4,通过数据包对象获取数据包的内容,发送端的ip。发送端的端口,发送过来的数据。
    			String ip = dp.getAddress().getHostAddress();
    			int port = dp.getPort();
    			String text = new String(dp.getData(), 0, dp.getLength());
    
    			System.out.println(ip + ":" + port + ":" + text);
    		}
    		// 5,关闭资源。
    //		ds.close();
    	}
    }
    

    案例:

    public class UDPChatTest {
    	public static void main(String[] args) throws IOException {
    		//发送端的socket 接收端的socket
    		DatagramSocket sendSocket = new DatagramSocket();
    		DatagramSocket receSocket = new DatagramSocket(10002);
    		
    		//创建任务对象。
    		Send send = new Send(sendSocket);
    		Rece rece = new Rece(receSocket);
    		
    		//创建线程并开启。
    		Thread t1 = new Thread(send);
    		Thread t2 = new Thread(rece);
    		t1.start();
    		t2.start();
    	}
    
    }
    
    // 发送任务
    class Send implements Runnable {
    
    	private DatagramSocket ds;
    
    	public Send(DatagramSocket ds) {
    		super();
    		this.ds = ds;
    	}
    
    	@Override
    	public void run() {
    		try {
    			BufferedReader bufr = new BufferedReader(new InputStreamReader(
    					System.in));
    			String line = null;
    			while ((line = bufr.readLine()) != null) {
    				byte[] buf = line.getBytes();// 将数据转成字节数组。
    				DatagramPacket dp = new DatagramPacket(buf, buf.length,
    						InetAddress.getByName("1928.1.223"), 10002);
    				ds.send(dp);
    				if ("886".equals(line)) {
    					break;
    				}
    			}
    
    			// 4,关闭资源。
    			ds.close();
    		} catch (IOException e) {
    
    		}
    	}
    }
    
    // 接收任务。
    class Rece implements Runnable {
    
    	private DatagramSocket ds;
    
    	public Rece(DatagramSocket ds) {
    		super();
    		this.ds = ds;
    	}
    
    	@Override
    	public void run() {
    		while (true) {
    
    			try {
    				byte[] buf = new byte[1024];
    				DatagramPacket dp = new DatagramPacket(buf, buf.length);
    				ds.receive(dp);// 阻塞
    				
    				String ip = dp.getAddress().getHostAddress();
    				int port = dp.getPort();
    				String text = new String(dp.getData(), 0, dp.getLength());
    				System.out.println(ip + ":" + port + ":" + text);
    				if(text.equals("886")){
    					System.out.println(ip+"....离开聊天室");
    				}
    			} catch (IOException e) {
    
    			}
    		}
    
    	}
    
    }
    

    tcp案例:

    public class TCPClient {
    	public static void main(String[] args) throws IOException {
    		System.out.println("客户端运行.......");
    //		1,建立tcp的客户端socket。明确服务端的地址和端口。
    		Socket s = new Socket("192.1.223",10003);
    //		2,如果通道建立成功就会出现socket io流。
    //			客户端需要做的就获取socket流的中输出流将数据发送目的地服务端。
    		OutputStream out = s.getOutputStream();
    //		3,通过socket输出流将数据发送。
    		out.write("hello tcp 来了!".getBytes());
    //		4,关闭资源。
    		s.close();
    	}
    }
    
    public class TCPServer {
    	public static void main(String[] args) throws IOException {
    		System.out.println("服务端开启.....");
    		ServerSocket ss = new ServerSocket(10003);
    		while (true) {
    			Socket s = ss.accept();
    			String ip = s.getInetAddress().getHostAddress();
    
    			InputStream in = s.getInputStream();
    			byte[] buf = new byte[1024];
    			int len = in.read(buf);
    			String text = new String(buf, 0, len);
    			System.out.println(text);
    			s.close();
    		}
    	}
    }
    

    案例:

    public class TCPClient2 {
    	public static void main(String[] args) throws UnknownHostException, IOException {
    		System.out.println("客户端2 启动.......");
    		Socket s = new Socket("192.1623", 10004);
    		OutputStream out = s.getOutputStream();
    		out.write("服务端,我来了".getBytes());
    		InputStream in = s.getInputStream();
    		byte[] buf = new byte[1024];
    		int len = in.read(buf);
    		String text = new String(buf,0,len);
    		System.out.println(text);
    //		关闭资源。
    		s.close();
    	}
    }
    
    public class TCPSever2 {
    	public static void main(String[] args) throws IOException {
    		System.out.println("服务端2启动.....");
    		ServerSocket ss = new ServerSocket(10004);
    		while (true) {
    			// 获取客户端对象。
    			Socket s = ss.accept();
    			// 读取客户端的发送过来的数据
    			InputStream in = s.getInputStream();
    			byte[] buf = new byte[1024];
    			int len = in.read(buf);
    			String text = new String(buf, 0, len);
    			System.out.println(text);
    			// 给客户端回馈数据。
    			OutputStream out = s.getOutputStream();
    			out.write("客户端,我已到收到,哦耶!".getBytes());
    			// 关闭客户端
    			s.close();
    		}
    		// 关闭服务端。如果不断的获取客户端,不用关闭服务端。
    //		ss.close();
    	}
    }
    

    达叔小生:往后余生,唯独有你
    You and me, we are family !
    90后帅气小伙,良好的开发习惯;独立思考的能力;主动并且善于沟通
    简书博客: 达叔小生
    https://www.jianshu.com/u/c785ece603d1

    结语

    • 下面我将继续对 其他知识 深入讲解 ,有兴趣可以继续关注
    • 小礼物走一走 or 点赞
  • 相关阅读:
    C++常见错误大全(转)
    在字符串中删除特定字符
    C++ const 的全面总结
    函数返回局部变量问题
    TerminateThread()结束一个线程会有什么结果?
    小刘同学的第五十五篇博文
    小刘同学的五十、五一、五二博文断更…
    小刘同学的第五十三篇博文
    小刘同学的第四十九篇博文
    小刘同学的第四十八篇博文
  • 原文地址:https://www.cnblogs.com/dashucoding/p/11140385.html
Copyright © 2020-2023  润新知