• Java Socket


    计算机通讯模型

    两种通讯模型介绍

    OSI七层模型:由国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联合制定的开放系统互连参考模型

    TCP/IP四层模型:TCP/IP是一组用于实现网络互连的通信协议。Internet网络体系结构以TCP/IP为核心

    共同点:分层概念、都能够提供面向连接无连接两种通信服务机制

    不同点:

    由于OSI模型和协议比较复杂,所以并没有得到广泛的应用,而TCP/IP模型因其开放性和易用性在实践中得到了广泛的应用,TCP/IP协议栈也成为互联网的主流协议;

    模型结构图

    OSI七层模型

    TCP/IP四层模型

    Java Socket编程针对的就是tcp/ip通讯模型中的传输层

    TCP/IP模型通讯要素

    IP地址(IP Address)

    IP地址(英语:Internet Protocol Address)是一种在Internet上的给主机编址的方式;

    常见的IP地址,分为IPv4与IPv6两大类;

    IP地址是网络上每台主机的唯一标识;

    端口(Port)

    主机中不同的应用有这不同的端口号,即端口号用于区别不同的应用;

    主机端口号范围为0-65535,其中0-1023位为系统保留;

    如常用的协议的端口号:HTTP 80、SSH 22、FTP 21、Telnet 23;

    传输层协议(Protocol )

    TCP (Transmission Control Protocol)

    可靠传输:必须通讯双方连接成功才能通讯,这种操作称之为向连接 ;

    三次握手方式建立连接,四次握手端口连接;

    UDP(User Datagram Protocol)

    不可靠传输:无需双方连接成功就可以通讯,这种操作称之为无连接 ;

    速度比TCP传输要快,但可能会有数据丢包的情况,即数据可能不会被接受到 ,一般用于聊天程序;

    Java Socket编程

    部分工具类

    InetAddress:解析地址

    public class T1 {
    
    	public static void main(String[] args) throws Exception {
    
    		// 获取本机的InetAddress对象
    		InetAddress localHost = InetAddress.getLocalHost();
    		// 获取指定主机名称的InetAddress对象
    		InetAddress localHost2 = InetAddress.getByName("www.baidu.com");
    		
    		System.out.println("主机名称:" + localHost.getHostName());
    		System.out.println("主机地址:" + localHost.getHostAddress());
    		System.out.println("===========================================");
    		System.out.println("主机名称:" + localHost2.getHostName());
    		System.out.println("主机地址:" + localHost2.getHostAddress());
    	
    		/* 数据结果:
    		
    			主机名称:DESKTOP-543IILF
    			主机地址:192.168.0.1
    			===========================================
    			主机名称:www.baidu.com
    			主机地址:14.215.177.38
    		 * */
    	}
    }
    

    URL:解析url

    public class T2 {
    
    	public static void main(String[] args) throws Exception {
    
    		/**
    		 * 	解析URL使用
    		 */
    		URL url = new URL("http://www.baidu.com");
    		System.out.println("协议:" + url.getProtocol());
    		System.out.println("主机(域名/ip地址):" + url.getHost());
    		System.out.println("端口:" + url.getPort()); 
    		// 如果URL方案或URL的URLStreamHandler未定义默认端口号,则返回-1
    		
    		URLConnection connection = url.openConnection();
    		
    		// 输出http://www.baidu.com的内容
    		InputStream in = connection.getInputStream();
    		byte[] buff = new byte[1024];
    		while(in.read(buff) != -1) {
    			System.out.println(new String(buff));
    		}
    		
    	}
    }
    

    URLEncoder、URLDecoder:URL的编解码

    public class T3 {
    
    	public static void main(String[] args) throws Exception {
    
    		String encode = URLEncoder.encode("http://www.baidu.com/123/张三", "GBK");
    		System.out.println(encode);
    		
    		String gbk_decode = URLDecoder.decode(encode, "GBK");
    		System.out.println("GBK解码:" + gbk_decode);
    		
    		/* 输出:
    			http%3A%2F%2Fwww.baidu.com%2F123%2F%D5%C5%C8%FD
    			GBK解码:http://www.baidu.com/123/张三
    		 */
    	}
    }
    

    TCP编程

    服务端

    // 注意:TCP通讯必须是服务端先启动
    public class Server {
    
    	public static void main(String[] args) throws Exception {
    
    		ServerSocket server = new ServerSocket(55555);
    		Socket socket = null;
    		
    		for(;;) {
    			
    			// 监听接入服务器的连接
    			socket = server.accept(); 
    			
    			// 读客户端
    			BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    			
    			// 写客户端
    			BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
    
    			
    			/**
    			 * 	服务端是先读取内容后发送内容
    			 */
    			String text = null;
    			while((text=in.readLine()) != null) {
    				System.out.println("客服端:" + text);
    				out.write("by server"); // 写到缓存区
    				out.newLine(); /** 写入一个行分隔符,效果作用于readLine方法 */
    				out.flush(); // 刷新缓冲区
    			}
    		}
    	}
    }
    

    客户端

    public class Client {
    
    	public static void main(String[] args) throws Exception {
    		
    		InetAddress localHost = InetAddress.getLocalHost();
    		Socket socket = new Socket(localHost.getHostAddress(), 55555);
    		
    		// 读控制台
    		Scanner scanner = new Scanner(System.in);
    		
    		// 读服务器
    		BufferedReader readServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    		
    		// 写服务器
    		BufferedWriter outServer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
    		
    		
    		/**
    		 * 	客户端是先发送内容后读取内容
    		 */
    		String consoleText = null;
    		while((consoleText=scanner.nextLine()) != null) {
    			
    			if("over".equals(consoleText.trim())) {
    				socket.shutdownOutput(); // 告诉服务端已经发送完信息,否者抛异常 Connect reset
    				System.exit(0); // 正常退出
    			}
    			
    			outServer.write(consoleText); // 写到缓存区
    			outServer.newLine(); /** 写入一个行分隔符,效果作用于readLine方法 */
    			outServer.flush();  // 刷新缓冲区
    			
    			System.out.println(readServer.readLine());
    		}
    	}
    }
    

    效果

    UDP编程

    服务端

    /**
     * 	UDP通信 服务器和客户端的port必须是不同的
     * 	先接受消息的就可以认为是服务端,阻塞等待数据包的到来
     */
    public class Server {
    
    	public static void main(String[] args) throws Exception {
    
    		// 监听 55555 端口的消息
    		DatagramSocket datagramSocket = new DatagramSocket(55555);
    		
    		for(;;) {
    			// 接收 55555 端口监听到的消息
    			byte[] buff = new byte[1024];
    			DatagramPacket cpacket = new DatagramPacket(buff, buff.length);
    			datagramSocket.receive(cpacket);
    			System.out.println("client:" + new String(buff, 0, buff.length));
    			
    			// 发送消息到 44444 端口
    			byte[] cbuff = "by server".getBytes();
    			DatagramPacket spacket = new DatagramPacket(cbuff, cbuff.length, InetAddress.getLocalHost(), 44444);
    			datagramSocket.send(spacket);				
    		}
    	}
    }
    

    客户端

    public class Client {
    
    	public static void main(String[] args) throws Exception {
    
    		// 监听 44444 端口的消息
    		DatagramSocket datagramSocket = new DatagramSocket(44444);
    		
    		// 发送消息
    		Scanner scanner = new Scanner(System.in);
    		String text = null;
    		while((text=scanner.nextLine()) != null) {
    			if("over".equals(text.trim())) {
    				System.exit(0); //正常退出
    			}
    			// 发送消息到 55555 端口
    			byte[] cbuff = text.trim().getBytes();
    			DatagramPacket cpacket = new DatagramPacket(cbuff, cbuff.length, InetAddress.getLocalHost(), 55555);
    			datagramSocket.send(cpacket);
    			
    			// 接收 44444 端口监听到的消息
    			byte[] buff = new byte[1024];
    			DatagramPacket spacket = new DatagramPacket(buff, buff.length);
    			datagramSocket.receive(spacket);
    			System.out.println("server:" + new String(buff, 0, buff.length));
    		}
    	}
    }
    

    效果

  • 相关阅读:
    Comparable与Comparator
    【源码】String类、jdk1.6subString内存泄漏、字符串拼接几种区别、
    JAVA整型包装类的缓存策略
    通过tomcat把项目http请求转为https请求
    git rebase总结及git使用规范
    记一次对象序列化不打印value值为null的属性问题
    Layui-Tables+PHP分页
    Python操作字符串-截取IP地址
    命令行启动VMware虚拟机
    bat批处理备份桌面所有文档
  • 原文地址:https://www.cnblogs.com/tandi19960505/p/9717906.html
Copyright © 2020-2023  润新知