Java学习Day15------网络编程、InetAddress、UDP、TCP

网络编程三要素

(1)IP:设备在网络中的位置
(2)端口号:应用程序在设备中的地址(范围: 0 ~ 65535 之间。其中 0 - 1023 是系统端口号。 1024 以上的端口号才能被我们使用。)
(3)协议:UDP和TCP

IP指令

  ping IP地址(查看该地址网络是否连通)
  ipconfig (查看自己的IP地址)

InetAddress类

(1)常用方法

方法备注
static InetAddress getByName(String host)通过主机名称或者IP地址, 获取到 InetAddress 对象。(既可以传递IP地址,也可以传递主机名)
String getHostName()获取此IP地址的主机名
String getHostAddress()返回文本显示中的IP地址字符串

协议

(1)UDP 协议
  a) 传输速度:快
  b) 传输数据量:小 最大64KB
  c) 安全性:低
(2)TCP 协议
  a) 传输速度:慢
  b) 传输数据量:大 无上限
  c) 安全性:高

UDP协议

(1)UDP的三种通信方式
  a) 单播: 一个发送端 和 一个接收端
  b) 组播: 一个发送端 和 一组(多个)接收端
  c) 广播: 一个发送端 和 一群(所有)接收端
(2)单播实现案例

//发送端
public class SendDemo {
    public static void main(String[] args) throws IOException {
        System.out.println("发送端");
        // (1). 创建对象
        DatagramSocket ds = new DatagramSocket();

        // (2). 打包数据
        String message = "Hello,你好呀.";
        byte[] data = message.getBytes();
        int length = data.length;
        InetAddress address = InetAddress.getByName("127.0.0.1");
        int port = 10086;  //说明:IP和端口指的是 接收端的IP和接收端的端口
        // --------
        DatagramPacket dp = new DatagramPacket(data,length,address,port);

        // (3). 发送数据
        ds.send(dp);

        // (4). 释放资源
        ds.close();
    }
}

//接收端【先运行接收端】
public class ReceiveDemo {
    public static void main(String[] args) throws IOException {
        System.out.println("接收端");
        // (1). 创建对象 ---> 需要传递参数:端口号
        DatagramSocket ds = new DatagramSocket(10086);
        // (2). 准备包裹
        byte[] data = new byte[1024];
        int len = data.length;
        DatagramPacket dp = new DatagramPacket(data,len);

        // (3). 接收数据
        ds.receive(dp);

        // (4). 解析数据
        String message = new String(data,0,dp.getLength());
        System.out.println(message);
        // (5). 释放资源
        ds.close();
    }
}

(3)组播
  a) 发送端
    需要修改发送端的 IP地址: 224.0.1.0到后面的IP
  b) 接收端
    aa) 创建对象 MulticastSocket ms = new MulticastSocket(10086);
    bb) 需要添加组播地址 ms.joinGroup(InetAddress.getByName(“224.0.1.1”));
    cc) 接收组播数据. ms.receive(dp);
    dd) 释放资源. ms.close();
  c) 案例

//发送端: 想一想发快递
public class SendDemo {
    public static void main(String[] args) throws Exception{
        // (1). 创建对象 找到快递点
        DatagramSocket ds = new DatagramSocket();
        // (2). 打包快递 将要发送的内容进行打包处理
        byte[] data = "Hello,几个老哥,不要在sleep".getBytes();
        int length = data.length;
        //IP地址是 接收端的IP地址
        InetAddress address = InetAddress.getByName("224.0.1.1");
        //端口号是 接收端的端口号
        int port = 10086;
        DatagramPacket dp = new DatagramPacket(data,length,address,port);
        // (3). 发送快递
        ds.send(dp);
        // (4). 结单
        ds.close();
    }
}

//接收端:想一想接收快递[先运行接收端]
public class ReceiveDemo {
    public static void main(String[] args) throws Exception {
        // (1). 创建对象 找到快递点
        MulticastSocket ms = new MulticastSocket(10086);
        //添加到组播地址
        ms.joinGroup(InetAddress.getByName("224.0.1.1"));

        // (2). 准备一个新的包裹 箱子
        byte[] data = new byte[1024];
        DatagramPacket dp = new DatagramPacket(data,data.length);

        // (3). 接收快递
        ms.receive(dp);

        // (4). 打开快递 解析数据
        String message = new String(data,0,dp.getLength());

        String address = dp.getAddress().getHostAddress();
        System.out.println(address+"说:"+message);
        // (5). 结单
        ms.close();
    }
}

(4)广播
  a) 需要修改发送端的 IP 地址: 255.255.255.255
  b) 案例

//发送端: 想一想发快递
public class SendDemo {
    public static void main(String[] args) throws Exception{
        // (1). 创建对象 找到快递点
        DatagramSocket ds = new DatagramSocket();
        // (2). 打包快递 将要发送的内容进行打包处理
        byte[] data = "Hello,几个老哥,不要在sleep".getBytes();
        int length = data.length;
        //IP地址是 接收端的IP地址
        InetAddress address = InetAddress.getByName("255.255.255.255");
        //端口号是 接收端的端口号
        int port = 10086;
        DatagramPacket dp = new DatagramPacket(data,length,address,port);
        // (3). 发送快递
        ds.send(dp);
        // (4). 结单
        ds.close();
    }
}

//接收端:想一想接收快递[先运行接收端]
public class ReceiveDemo {
    public static void main(String[] args) throws Exception {
        // (1). 创建对象 找到快递点
        DatagramSocket ds = new DatagramSocket(10086);
        // (2). 准备一个新的包裹 箱子
        byte[] data = new byte[1024];
        DatagramPacket dp = new DatagramPacket(data,data.length);
        // (3). 接收快递
        ds.receive(dp);
        // (4). 打开快递 解析数据
        String message = new String(data,0,dp.getLength());
        String address = dp.getAddress().getHostAddress();
        System.out.println(address+"说:"+message);
        // (5). 结单
        ds.close();
    }
}

TCP协议

(1)案例演示原理

//词霸客户端
public class CiBaClient {
    public static void main(String[] args) throws IOException {
        String word = "hello";
        // (1). 准备发送数据给服务端 --》输出  IP和端口 都是服务端的
        Socket clientSocket = new Socket("127.0.0.1",6666);
        OutputStream os = clientSocket.getOutputStream();
        os.write(word.getBytes());

        // (2). 准备接收到服务端回复的数据--》输入
        InputStream is = clientSocket.getInputStream();
        byte[] array = new byte[1024];
        int len = is.read(array);
        String message = new String(array,0,len);
        System.out.println(message);
        clientSocket.close();  //释放资源
    }
}

//词霸 服务端 【先运行服务端】
public class CiBaServer {
    public static void main(String[] args) throws IOException {
        System.out.println("你好,黑马词霸服务器开启了...");
        // --------
        ServerSocket serverSocket = new ServerSocket(6666);
        Socket clientSocket = serverSocket.accept();  //客户端的Socket
        // (1). 接收来自于客户端的数据 --》输入流
        InputStream is = clientSocket.getInputStream();
        byte[] array = new byte[1024];
        int len = is.read(array);
        String word = new String(array,0,len);


        // (2). 单词的查找
        HashMap<String,String> map = new HashMap<>();
        map.put("hello","你好呀");
        map.put("world","世界");
        map.put("java","牛逼的语言");
        String value = map.get(word);
        value = (value == null)?"请充值VIP":value;


        // (3). 返回结果--》输出流
        OutputStream os = clientSocket.getOutputStream();
        os.write(value.getBytes());
        clientSocket.close();  //释放资源
    }
}

  案例原理图
在这里插入图片描述
(2)词霸案例(单线程和多线程)
  a) 单线程

//词霸 客户端 引入外部词库
public class CiBaClientDemo {
    public static void main(String[] args) throws Exception{
        while(true){
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入需要翻译的单词:(886则退出)");
            String word = sc.nextLine();
            //如果是 886 则退出循环
            if ("886".equals(word)){
                break;
            }
            // (1). 创建 客户端 clientSocket 的对象
            Socket clientSocket = new Socket("127.0.0.1",10086);
            // (2). 需要发送数据给 服务端
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
            bw.write(word);
            bw.newLine();  //因为 br 需要读取到换行符才会结束,需要给他一个换行符
            bw.flush();  //因为 bw 写数据是写入到缓冲区,需要通过刷新它才能够写过去!
            // (3). 接收来自于服务端 翻译的数据
            BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            String message = br.readLine();
            System.out.println(message);
            // (4). 释放资源
            clientSocket.close();
        }
    }
}

//词霸 服务端 引入外部词库
//服务端: 将Map集合转换成为 Properties 写法
public class CiBaServerDemo {
    public static void main(String[] args) throws IOException {
        String path = "JavaSEDay17\\dir\\ciba.properties";
        Properties pp = new Properties();
        //看你的编码方式是什么类型? 如果编码方式是 UTF-8 则不需要转换,如果是 GBK 则建议采用转换流,解决中文乱码
        pp.load(new InputStreamReader(new FileInputStream(path),"GBK"));
        // --------
        // (1). 创建服务器的 ServerSocket 的对象
        ServerSocket serverSocket = new ServerSocket(10086);
        while(true){
            // (2). 获取到 客户端的 clientSocket 的对象
            Socket clientSocket = serverSocket.accept();
            // (3). 接收来自于客户端的数据
            BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            String word = br.readLine();  //因为只是写了一行数据,读数据只需要读取一行
            // (4). 处理数据逻辑(翻译 java --> 中文)
            String message = "不好意思啊,你还不是SSVIP,请充值";
            //通过 Map 集合,查找单词数据
            String value = pp.getProperty(word);
            //如果值为 null,不好意思啊... 如果不为null 得到结果就是 value值
            message = (value == null) ? message : value;
            // (5). 准备写回结果数据 给客户端
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
            bw.write(message);
            bw.newLine();
            bw.flush();
            // (6). 释放资源
            clientSocket.close();
        }
    }
}

  b) 多线程

// 线程类,用于处理多线程
public class MyThread implements Runnable {
    private Socket clientSocket;
    private HashMap<String, String> map;

    public MyThread(Socket clientSocket, HashMap<String, String> map) {
        this.clientSocket = clientSocket;
        this.map = map;
    }

    @Override
    public void run() {
        try {
            // 获取客户端发送的数据
            InputStream is = clientSocket.getInputStream();

            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String word = br.readLine();

            // 获取翻译
            String value = map.get(word);
            value = value == null ? "请充值会员" : value;

            // 将数据返回给客户端
            // 获取输出流
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
            bw.write(value);
            bw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (clientSocket != null) {
                try {
                    clientSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

// 客户端
public class Client {
    public static void main(String[] args) throws IOException {
        while (true) {
            Scanner sc = new Scanner(System.in);
            // 创建客户端socket对象
            Socket client = new Socket("127.0.0.1",10086);
            // 准备数据
            System.out.print("输入单词:");
            String word = sc.nextLine();
            // 获取输出流传输数据
            OutputStream clientOutputStream = client.getOutputStream();
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientOutputStream));
            bw.write(word);
            bw.newLine();
            bw.flush();


            // 获取服务器回传的数据
            BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
            String s = br.readLine();
            System.out.println("翻译:"+s);
            if ("886".equals(word)){
                break;
            }
            client.close();
        }

    }
}

// 服务器端
public class Server {
    private static HashMap<String, String> map = new HashMap<>();
    // 加载配置文件的字典数据
    static {
        BufferedReader br = null;
        try {
            // 加载字典文件
            br = new BufferedReader(new FileReader("day15/homeworkdir/dictionary.txt"));
            String line;
            while ((line = br.readLine()) != null) {
                // 将读取的内容转换为map
                String[] split = line.split("=");
                map.put(split[0], split[1]);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) throws IOException {
        System.out.println("词霸已上线.......");
        ServerSocket ss = new ServerSocket(10086);
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                3,
                5,
                60,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(5),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
        while (true) {
            Socket clientSocket = ss.accept();
            MyThread myThread = new MyThread(clientSocket, map);
            pool.submit(myThread);
            clientSocket.close();
        }
    }
}

(3)文件上传(单线程和多线程)
  a) 单线程

//文件上传的客户端:
public class UpLoadClientDemo {
    
    public static void main(String[] args) throws Exception {
        String path = "JavaSEDay17\\dir\\meizi.png";
        Socket clientSocket = new Socket("127.0.0.1", 10086);
        // --------
        // (1). 本地流 输入到程序当中, 网络流 输出到 服务器
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path));
        BufferedOutputStream bos = new BufferedOutputStream(clientSocket.getOutputStream());
        byte[] data = new byte[1024];
        int len;
        while ((len = bis.read(data)) != -1) {
            bos.write(data, 0, len);
            bos.flush();
        }
        //===============
        //需要写一个结束标记
        clientSocket.shutdownOutput();
        //===============
        // (4). 获取到服务器的数据
        BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        String message = br.readLine();
        System.out.println(message);
        clientSocket.close();
    }
}

//文件上传的服务端:
public class UpLoadServerDemo {
    public static void main(String[] args) throws IOException {
        System.out.println("服务器启动了...");
        String path = "JavaSEDay17\\dir\\mz001.png";
        ServerSocket serverSocket = new ServerSocket(10086);
        Socket clientSocket = serverSocket.accept();
        // (2). 网络流 接收来自于客户端的数据,写出到本地
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path));
        BufferedInputStream bis = new BufferedInputStream(clientSocket.getInputStream());
        byte[] data = new byte[1024];
        int len;
        while ((len = bis.read(data)) != -1) {
            bos.write(data, 0, len);
            bos.flush();
        }
        // (3). 写回结果给客户端
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
        bw.write("文件上传成功!");
        bw.newLine();
        bw.flush();
        clientSocket.close();
    }
}

  b) 多线程

//文件上传的客户端:
public class UpLoadClientDemo {
    
    public static void main(String[] args) throws Exception {
        String path = "JavaSEDay17\\dir\\meizi.png";
        Socket clientSocket = new Socket("127.0.0.1", 10086);
        // --------
        // (1). 本地流 输入到程序当中, 网络流 输出到 服务器
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path));
        BufferedOutputStream bos = new BufferedOutputStream(clientSocket.getOutputStream());
        byte[] data = new byte[1024];
        int len;
        while ((len = bis.read(data)) != -1) {
            bos.write(data, 0, len);
            bos.flush();
        }
        //===============
        //需要写一个结束标记
        clientSocket.shutdownOutput();
        //===============
        // (4). 获取到服务器的数据
        BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        String message = br.readLine();
        System.out.println(message);
        clientSocket.close();
    }
}

//文件上传的服务端:
//1. 文件的名称需要随机出现。UUID.randomUUID().toString();
//2. 服务器需要处于长期开启状态。 添加死循环操作
//  ------> 针对于第二步而言:
//  ----------> A. 在 accept() 方法的下面,进行抽取
//  ----------> B. 添加死循环操作 while(true){ ... }
public class UpLoadServerDemo {
    public static void main(String[] args) throws IOException {
        System.out.println("服务器启动了...");
        ServerSocket serverSocket = new ServerSocket(10086);
        while (true) {
            Socket clientSocket = serverSocket.accept();
            upload(clientSocket);
        }
    }
    //抽取成为一个方法
    public static void upload(Socket clientSocket) throws IOException {
        //随机生成一个字符串序列.作为文件的名称
        String name = UUID.randomUUID().toString();
        String path = "JavaSEDay17\\dir\\" + name + ".png";
        // (2). 网络流 接收来自于客户端的数据,写出到本地
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path));
        BufferedInputStream bis = new BufferedInputStream(clientSocket.getInputStream());
        byte[] data = new byte[1024];
        int len;
        while ((len = bis.read(data)) != -1) {
            bos.write(data, 0, len);
            bos.flush();
        }
        // (3). 写回结果给客户端
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
        bw.write("文件上传成功!");
        bw.newLine();
        bw.flush();
        clientSocket.close();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值