package com.it.demo01_quickstart; /* 案例: 讲解网络编程相关概念. 网络编程简介: 概述: 网络编程也叫: 套接字编程, Socket编程, 就是用来实现 网络互联的 不同计算机上 运行的程序间 可以进行数据交互. 大白话翻译: 就是用来实现 不同电脑间 进行数据传输的. 三大要素: IP地址: 概述: 设备在网络中的唯一标识. 192.168.37.56 组成: 网络(关)号码 + 主机地址 分类: 城域网: 1 + 3 第一段是网关号码, 后三段是主机地址. 广域网: 2 + 2 一般应用于校园网 局域网: 3 + 1 两个DOS指令: ipconfig /all 查看IP ping ip地址/网址 -t 测试网络连接 两个特殊的IP: 127.0.0.1 本地回环(回路)地址, 即: 代表本机. 255.255.255.255 广播地址 InetAddress类: IP地址的包装类 String形式的IP -> InetAddress类型的 IP地址对象. public static InetAddress getByName(String ip地址/主机名); 根据字符串形式的ip(或者主机名), 获取其对应的 IP地址对象. InetAddress类型的 IP地址对象 -> String形式的IP public String getHostAddress(); 根据IP地址对象, 获取字符串形式的IP public String getHostName(); 根据IP地址对象, 获取字符串形式的 主机名 端口号: 概述: 程序在设备上的唯一标识. 范围: 0-65535 注意事项: 0-1023之间的端口号不要用, 因为已经被系统占用了或者用作保留端口. 协议: 概述: 就是设备间传输数据时, 需要遵守的规则, 约定. 分类: UDP协议: //类似于: 群聊 1. 面向无连接. 2. 采用数据报包(DatagramPacket)的形式发送数据, 每个包的大小不能超过64KB. 3. 不安全(不可靠)协议. 4. 效率相对较高. 5. 不区分客户端和服务器端, 叫发送端和接收端. TCP协议: //类似于: 打电话 1. 面向有连接(三次握手) 2. 采用IO流的形式发送数据, 理论上来讲无数据大小限制. 3. 安全(可靠)协议. 4. 效率相对较低. 5. 区分客户端和服务器端. 软件结构: 常用的软件主要分为: CS结构 和 BS结构 CS结构: Client(客户端) 和 Server(服务器端) 例如: QQ, 微信, LOL 特点: 需求安装客户端, 服务器端升级的时候, 客户端同步也要升级. 好处: 1. 降低服务器压力, 因为可以把一些必要的 大的文件, 提前让用户安装. 2. 用户体验较好. 因为一些必要文件已经提前下载好了, 所以此类产品界面一般做的比较好看. 弊端: 当服务器端升级的时候, 客户端同步也要升级. BS结构: Browser(浏览器端) 和 Server(服务器端) 例如: 天猫, 京东 特点: 无需安装特定软件, 只要有一个浏览器就可以访问. 好处: 1. 更灵活, 用户无需安装特定软件, 只要有一个浏览器就可以访问. 2. 用户体验较好, 只要有一个浏览器, 就可以访问了, 无需安装其他软件, 也无需定时更新指定的客户端. 弊端: 1. 服务器压力过大, 因为浏览器端所需的所有的数据都会从 服务器端下载. 2. 需要用户记忆大量的网址... */ public class Demo01 { public static void main(String[] args) { } }
package com.it.demo02_inetaddress; import java.net.InetAddress; import java.net.UnknownHostException; /* 案例: 演示InetAddress IP地址包装类. InetAddress类的成员方法: IP地址的包装类 String形式的IP -> InetAddress类型的 IP地址对象. public static InetAddress getByName(String ip地址/主机名); 根据字符串形式的ip(或者主机名), 获取其对应的 IP地址对象. InetAddress类型的 IP地址对象 -> String形式的IP public String getHostAddress(); 根据IP地址对象, 获取字符串形式的IP public String getHostName(); 根据IP地址对象, 获取字符串形式的 主机名 */ public class Demo01 { public static void main(String[] args) throws UnknownHostException { //需求1: String -> InetAddress //根据ip地址获取, 推荐方式. String ip = "192.168.88.5"; InetAddress inet1 = InetAddress.getByName(ip); System.out.println(inet1); //如果是通过ip获取的 IP对象, 打印的时候只有: ip地址 System.out.println("---------------------"); //根据主机名获取, 了解. String hostName = "HangGe"; InetAddress inet2 = InetAddress.getByName(hostName); System.out.println(inet2); //如果是通过 主机名获取的, 打印的时候是: 主机名, ip地址. System.out.println("---------------------"); //需求2: InetAddress -> String System.out.println(inet1.getHostAddress()); //192.168.88.5 System.out.println(inet1.getHostName()); //HangGe } }
package com.it.demo03_udp; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.Socket; /* 案例: 演示UDP协议发送和接收数据 */ //接收端. public class ReceiveDemo { public static void main(String[] args) throws Exception { //1. 创建接收端的Socket对象, 指定端口号. DatagramSocket ds = new DatagramSocket(12345); //2. 创建DatagramPacket对象, 用来接收 发送端发过来的数据. // 要装数据的数组 数组的可用长度 //使用这个构造方法: DatagramPacket(byte[] buf, int length) byte[] bys = new byte[1024]; DatagramPacket dp = new DatagramPacket(bys, bys.length); //3. 通过接收端的Socket对象, 接收发送端发过来的数据, 并存储到 数据报包对象中. ds.receive(dp); //4. 从数据报包对象中获取数据. byte[] data = dp.getData(); //从数据报包对象中获取数据. int len = dp.getLength(); //从数据报包对象中获取 具体的有效字节数. String s = new String(data, 0, len); //5. 打印数据. System.out.println(s); //6. 关闭接收端的Socket对象. ds.close(); } }
package com.it.demo03_udp; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; /* 案例: 演示UDP协议发送和接收数据. 补充: 网络通信的原理 网络通信也叫Socket通信, 数据在两个Socket之间通过 数据报包 或者 IO流的形式进行传输. */ //发送端. public class SendDemo { public static void main(String[] args) throws Exception { //1. 创建发送端的Socket对象. DatagramSocket ds = new DatagramSocket(); //2. 定义要发送的数据. String s = "恭喜发财, 红包拿来"; byte[] bys = s.getBytes(); //3. 将要发送的数据封装到 数据报包中(DatagramPacket)中. // 要发送的数据 数据长度 接收端的IP地址 端口号 //使用这个构造方法: DatagramPacket(byte[] buf, int length, InetAddress address, int port) DatagramPacket dp = new DatagramPacket(bys, bys.length, InetAddress.getByName("127.0.0.1"), 12345); //4. 通过Socket对象, 发送数据报包 ds.send(dp); //5. 关闭Socket对象. ds.close(); } }
package com.it.demo04_tcp_quickstart; import java.io.OutputStream; import java.net.Socket; /* 案例: 演示TCP协议之发送数据. 步骤: 1. 创建客户端Socket对象, 指定服务器端的ip, 端口号. 2. 通过 Socket#getOutputStream()方法, 获取输出流, 可以往服务器端写数据. 3. 通过输出流, 给服务器端写数据. 4. 关闭Socket对象. */ //客户端 public class ClientDemo { public static void main(String[] args) throws Exception { //1. 创建客户端Socket对象, 指定服务器端的ip, 端口号. Socket socket = new Socket("192.168.88.5", 10087); //2. 通过 Socket#getOutputStream()方法, 获取输出流, 可以往服务器端写数据. OutputStream os = socket.getOutputStream(); //3. 通过输出流, 给服务器端写数据. os.write("Hello, TCP , 我来了!".getBytes()); //4. 关闭Socket对象. socket.close(); } }
package com.it.demo04_tcp_quickstart; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; /* 案例: 演示TCP协议之接收数据. 步骤: 1. 创建服务器端端Socket对象(ServerSocket), 指定端口号. 2. 通过ServerSocket#accept()方法监听客户端连接, 如果有客户端申请建立连接, 服务器端在审核完数据之后, 回自动创建一个Socket对象, 负责和此客户端的交互. 3. 通过Socket#getInnputStream()获取输入流, 可以读取客户端发过来的数据. 4. 具体接收数据的动作. 5. 打印接收到的数据. 6. 关闭Socket对象, 关闭的是与客户端Socket交互的对象, 而不是ServerSocket. */ //服务器端 public class ServerDemo { public static void main(String[] args) throws Exception { //1. 创建服务器端端Socket对象(ServerSocket), 指定端口号. ServerSocket server = new ServerSocket(10087); //2. 通过ServerSocket#accept()方法监听客户端连接, 如果有客户端申请建立连接, //服务器端在审核完数据之后, 回自动创建一个Socket对象, 负责和此客户端的交互. System.out.println(1); Socket accept = server.accept(); System.out.println(2); //3. 通过Socket#getInnputStream()获取输入流, 可以读取客户端发过来的数据. InputStream is = accept.getInputStream(); //4. 具体接收数据的动作. byte[] bys = new byte[1024]; int len = is.read(bys); String s = new String(bys, 0, len); //5. 打印接收到的数据. System.out.println(s); //6. 关闭Socket对象, 关闭的是与客户端Socket交互的对象, 而不是ServerSocket. accept.close(); //server.close(); 服务器端Socket对象一般不关闭. } }
package com.it.demo05_tcp_exercise; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; /* 案例: 演示TCP协议之发送数据. 步骤: 1. 创建客户端Socket对象, 指定服务器端的ip, 端口号. 2. 通过 Socket#getOutputStream()方法, 获取输出流, 可以往服务器端写数据. 3. 通过输出流, 给服务器端写数据. 4. 关闭Socket对象. */ //客户端 public class ClientDemo { public static void main(String[] args) throws Exception { //1. 创建客户端Socket对象, 指定服务器端的ip, 端口号. Socket socket = new Socket("192.168.88.5", 10087); //2. 通过 Socket#getOutputStream()方法, 获取输出流, 可以往服务器端写数据. OutputStream os = socket.getOutputStream(); //3. 通过输出流, 给服务器端写数据. os.write("Hello, TCP , 我来了!".getBytes()); //4. 获取输出流, 可以读取服务器端写过来的数据. InputStream is = socket.getInputStream(); //5. 具体读取数据的操作. byte[] bys = new byte[1024]; int len = is.read(bys); String s = new String(bys, 0, len); //6. 打印读取到的数据. System.out.println(s); //7. 关闭Socket对象. socket.close(); } } package com.it.demo05_tcp_exercise; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; /* 案例: 演示TCP协议之接收数据. 步骤: 1. 创建服务器端端Socket对象(ServerSocket), 指定端口号. 2. 通过ServerSocket#accept()方法监听客户端连接, 如果有客户端申请建立连接, 服务器端在审核完数据之后, 回自动创建一个Socket对象, 负责和此客户端的交互. 3. 通过Socket#getInnputStream()获取输入流, 可以读取客户端发过来的数据. 4. 具体接收数据的动作. 5. 打印接收到的数据. 6. 关闭Socket对象, 关闭的是与客户端Socket交互的对象, 而不是ServerSocket. */ //服务器端 public class ServerDemo { public static void main(String[] args) throws Exception { //1. 创建服务器端端Socket对象(ServerSocket), 指定端口号. ServerSocket server = new ServerSocket(10087); //2. 通过ServerSocket#accept()方法监听客户端连接, 如果有客户端申请建立连接, //服务器端在审核完数据之后, 回自动创建一个Socket对象, 负责和此客户端的交互. System.out.println(1); Socket accept = server.accept(); System.out.println(2); //3. 通过Socket#getInnputStream()获取输入流, 可以读取客户端发过来的数据. InputStream is = accept.getInputStream(); //4. 具体接收数据的动作. byte[] bys = new byte[1024]; int len = is.read(bys); String s = new String(bys, 0, len); //5. 打印接收到的数据. System.out.println(s); //6. 获取输出流, 可以往客户端写数据. OutputStream os = accept.getOutputStream(); //7. 给客户端写的具体的数据(回执信息) os.write("数据已收到!".getBytes()); //8. 关闭Socket对象, 关闭的是与客户端Socket交互的对象, 而不是ServerSocket. accept.close(); //server.close(); 服务器端Socket对象一般不关闭. } }
package com.it.demo06_tcp_exercise_upload; import java.io.*; import java.net.Socket; /* 案例: 客户端给服务器端上传文件. 思路: 1. 创建客户端的Socket对象, 指定服务器端的ip, 端口号. 2. 获取字符缓冲输入流对象, 管理数据源文件. 3. 通过Socket#getOutputStream()获取输出流, 可以往服务器端写数据. 4. 具体的IO流操作, 读写数据. 5. 关流, 释放资源. */ //客户端 public class ClientDemo { public static void main(String[] args) throws Exception{ //1. 创建客户端的Socket对象, 指定服务器端的ip, 端口号. Socket socket = new Socket("127.0.0.1", 10010); //2. 获取字符缓冲输入流对象, 管理数据源文件. BufferedReader br = new BufferedReader(new FileReader("D:\\绕口令.txt")); //3. 通过Socket#getOutputStream()获取输出流, 可以往服务器端写数据. //分解版 /*OutputStream os = socket.getOutputStream(); //转换流: 字节流 -> 字符流 OutputStreamWriter osw = new OutputStreamWriter(os); //字符缓冲流: 普通的字符流 -> 高效的字符流 BufferedWriter bw = new BufferedWriter(osw);*/ //合并版 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); //4. 具体的IO流操作, 读写数据. String line; while((line = br.readLine()) != null) { //把读取到的数据写给服务器端 bw.write(line); bw.newLine(); bw.flush(); //刷新出 缓冲区中的数据. } //5. 关流, 释放资源. br.close(); socket.close(); } } package com.it.demo06_tcp_exercise_upload; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /* 案例: 客户端给服务器端上传文件 思路: 1. 创建服务器端Socket对象, 指定端口号. 2. 监听连接. 3. 创建字符缓冲输出流, 关联目的地文件. 4. 通过Socket#getInputStream(), 获取输入流, 读取客户端写过来的数据. 5. 具体的IO流操作, 读写数据. 6. 关流, 释放资源. */ //服务器端 public class ServerDemo { public static void main(String[] args) throws Exception{ // 1. 创建服务器端Socket对象, 指定端口号. ServerSocket server = new ServerSocket(10010); // 2. 监听连接. Socket accept = server.accept(); // 3. 创建字符缓冲输出流, 关联目的地文件. BufferedWriter bw = new BufferedWriter(new FileWriter("day13_socket/data/copy1.txt")); // 4. 通过Socket#getInputStream(), 获取输入流, 读取客户端写过来的数据. BufferedReader br = new BufferedReader(new InputStreamReader(accept.getInputStream())); // 5. 具体的IO流操作, 读写数据. String line; while((line = br.readLine()) != null) { //把读取到的数据写给服务器端 bw.write(line); bw.newLine(); bw.flush(); //刷新出 缓冲区中的数据. } // 6. 关流, 释放资源. bw.close(); accept.close(); } }
package com.it.demo07_tcp_exercise_upload_message; import java.io.*; import java.net.Socket; /* 案例: 客户端给服务器端上传文件. 思路: 1. 创建客户端的Socket对象, 指定服务器端的ip, 端口号. 2. 获取字符缓冲输入流对象, 管理数据源文件. 3. 通过Socket#getOutputStream()获取输出流, 可以往服务器端写数据. 4. 具体的IO流操作, 读写数据. 5. 关流, 释放资源. */ //客户端 public class ClientDemo { public static void main(String[] args) throws Exception{ //1. 创建客户端的Socket对象, 指定服务器端的ip, 端口号. Socket socket = new Socket("127.0.0.1", 10010); //2. 获取字符缓冲输入流对象, 管理数据源文件. BufferedReader br = new BufferedReader(new FileReader("D:\\绕口令.txt")); //3. 通过Socket#getOutputStream()获取输出流, 可以往服务器端写数据. //分解版 /*OutputStream os = socket.getOutputStream(); //转换流: 字节流 -> 字符流 OutputStreamWriter osw = new OutputStreamWriter(os); //字符缓冲流: 普通的字符流 -> 高效的字符流 BufferedWriter bw = new BufferedWriter(osw);*/ //合并版 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); //4. 具体的IO流操作, 读写数据. System.out.println("client: 1"); String line; while((line = br.readLine()) != null) { //把读取到的数据写给服务器端 bw.write(line); bw.newLine(); bw.flush(); //刷新出 缓冲区中的数据. } System.out.println("client: 2"); //5. 核心操作, 客户端上传文件完毕后, 需要给服务器端一个结束标记, 意思是说: 我传完了, 你该干嘛干嘛. socket.shutdownOutput(); //给服务器端一个结束标记. //6. 获取输入流, 读取服务器端写过来的回执信息. BufferedReader br2 = new BufferedReader(new InputStreamReader(socket.getInputStream())); //7. 具体接收数据的操作 System.out.println("client: 3"); String result = br2.readLine(); System.out.println("client: 4"); //8. 打印接收到的数据. System.out.println(result); //9. 关流, 释放资源. br.close(); socket.close(); } } package com.it.demo07_tcp_exercise_upload_message; import java.io.*; import java.net.ServerSocket; import java.net.Socket; /* 案例: 客户端给服务器端上传文件 思路: 1. 创建服务器端Socket对象, 指定端口号. 2. 监听连接. 3. 创建字符缓冲输出流, 关联目的地文件. 4. 通过Socket#getInputStream(), 获取输入流, 读取客户端写过来的数据. 5. 具体的IO流操作, 读写数据. 6. 关流, 释放资源. */ //服务器端 public class ServerDemo { public static void main(String[] args) throws Exception { // 1. 创建服务器端Socket对象, 指定端口号. ServerSocket server = new ServerSocket(10010); // 2. 监听连接. System.out.println("server: 1"); Socket accept = server.accept(); System.out.println("server: 2"); // 3. 创建字符缓冲输出流, 关联目的地文件. BufferedWriter bw = new BufferedWriter(new FileWriter("day13_socket/data/copy1.txt")); // 4. 通过Socket#getInputStream(), 获取输入流, 读取客户端写过来的数据. BufferedReader br = new BufferedReader(new InputStreamReader(accept.getInputStream())); // 5. 具体的IO流操作, 读写数据. System.out.println("server: 3"); String line; while ((line = br.readLine()) != null) { //把读取到的数据写给服务器端 bw.write(line); bw.newLine(); bw.flush(); //刷新出 缓冲区中的数据. } System.out.println("server: 4"); //6. 获取输出流, 给客户端写回执信息. BufferedWriter bw2 = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream())); //7. 给客户端写回执信息的具体操作. bw2.write("文件上传成功"); bw2.flush(); //8.. 关流, 释放资源. bw.close(); accept.close(); } }
package com.it.demo08_tcp_upload_thread; import java.io.*; import java.net.Socket; /* 案例: 客户端给服务器端上传文件. 思路: 1. 创建客户端的Socket对象, 指定服务器端的ip, 端口号. 2. 获取字符缓冲输入流对象, 管理数据源文件. 3. 通过Socket#getOutputStream()获取输出流, 可以往服务器端写数据. 4. 具体的IO流操作, 读写数据. 5. 关流, 释放资源. */ //客户端 public class ClientDemo { public static void main(String[] args) throws Exception{ //1. 创建客户端的Socket对象, 指定服务器端的ip, 端口号. Socket socket = new Socket("127.0.0.1", 10010); //2. 获取字符缓冲输入流对象, 管理数据源文件. BufferedReader br = new BufferedReader(new FileReader("D:\\代码打字练习词库.txt")); //3. 通过Socket#getOutputStream()获取输出流, 可以往服务器端写数据. BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); //4. 具体的IO流操作, 读写数据. String line; while((line = br.readLine()) != null) { //把读取到的数据写给服务器端 bw.write(line); bw.newLine(); bw.flush(); //刷新出 缓冲区中的数据. } //5. 核心操作, 客户端上传文件完毕后, 需要给服务器端一个结束标记, 意思是说: 我传完了, 你该干嘛干嘛. socket.shutdownOutput(); //给服务器端一个结束标记. //6. 获取输入流, 读取服务器端写过来的回执信息. BufferedReader br2 = new BufferedReader(new InputStreamReader(socket.getInputStream())); //7. 具体接收数据的操作 String result = br2.readLine(); //8. 打印接收到的数据. System.out.println(result); //9. 关流, 释放资源. br.close(); socket.close(); } } package com.it.demo08_tcp_upload_thread; import java.io.*; import java.net.ServerSocket; import java.net.Socket; /* 案例: 客户端给服务器端上传文件 思路: 1. 创建服务器端Socket对象, 指定端口号. 2. 监听连接. 3. 创建字符缓冲输出流, 关联目的地文件. 4. 通过Socket#getInputStream(), 获取输入流, 读取客户端写过来的数据. 5. 具体的IO流操作, 读写数据. 6. 关流, 释放资源. */ //服务器端 public class ServerDemo { public static void main(String[] args) throws Exception { // 1. 创建服务器端Socket对象, 指定端口号. ServerSocket server = new ServerSocket(10010); //服务器端要不断的监听客户端的连接. while(true) { // 2. 监听连接. Socket accept = server.accept(); //3. 如果有, 就创建一个线程, 负责和此客户端的交互. //new Thread(Runnable接口的子类对象).start(); new Thread(new ServerThread(accept)).start(); } } } package com.it.demo08_tcp_upload_thread; import java.io.*; import java.net.Socket; //自定义的线程资源类, 表示具体的接收文件, 并给出回执信息的动作. //每一个客户端的Socket对象, 都对应一个服务器端线程(即: ServerThread) public class ServerThread implements Runnable{ //定义变量, 表示和客户单Socket通信的 Socket对象. private Socket accept; public ServerThread(Socket accept) { this.accept = accept; } //具体的接收文件, 并给出回执信息的动作. @Override public void run() { try { //解决: 文件重名问题. int count = 1; File file = new File("day13_socket/data/copy("+ count +").txt"); //copy(1).txt while (file.exists()) { //走这里, 说明文件存在 count++; file = new File("day13_socket/data/copy("+ count +").txt"); //copy(2).txt, copy(3).txt } // 3. 创建字符缓冲输出流, 关联目的地文件. BufferedWriter bw = new BufferedWriter(new FileWriter(file)); // 4. 通过Socket#getInputStream(), 获取输入流, 读取客户端写过来的数据. BufferedReader br = new BufferedReader(new InputStreamReader(accept.getInputStream())); // 5. 具体的IO流操作, 读写数据. String line; while ((line = br.readLine()) != null) { //把读取到的数据写给服务器端 bw.write(line); bw.newLine(); bw.flush(); //刷新出 缓冲区中的数据. } //6. 获取输出流, 给客户端写回执信息. BufferedWriter bw2 = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream())); //7. 给客户端写回执信息的具体操作. bw2.write("文件上传成功"); bw2.flush(); //8.. 关流, 释放资源. bw.close(); accept.close(); } catch (Exception e) { e.printStackTrace(); } } }
 
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号