day26(026-网络编程)

###26.02_网络编程(网络编程三要素之IP概述)

  • IPv6:8组,每组4个16进制数。

  • 1a2b:0000:aaaa:0000:0000:0000:aabb:1f2f

###26.03_网络编程(网络编程三要素之端口号概述)

  • 每个程序在设备上的唯一标识

  • 每个网络程序都需要绑定一个端口号,传输数据的时候除了确定发到哪台机器上,还要明确发到哪个程序。

  • 端口号范围从0-65535

  • 编写网络应用就需要绑定一个端口号,尽量使用1024以上的,1024以下的基本上都被系统程序占用了。

  • 常用端口

    • mysql: 3306

    • oracle: 1521

    • web: 80

    • tomcat: 8080

###26.04_网络编程(网络编程三要素协议)

  • 为计算机网络中进行数据交换而建立的规则、标准或约定的集合。

  • UDP

    • 面向无连接,数据不安全,速度快。不区分客户端与服务端。

  • TCP

  • 面向连接(三次握手),数据安全,速度略低。分为客户端和服务端。

    • 三次握手: 客户端先向服务端发起请求, 服务端响应请求, 传输数据

###26.05_网络编程(Socket通信原理图解)

  • Socket套接字概述:

    • 网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。

    • 通信的两端都有Socket。

    • 网络通信其实就是Socket间的通信。

    • 数据在两个Socket间通过IO流传输。

    • Socket在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己所对应的IP和port。

###26.06_网络编程(UDP传输)(了解)

  • 1.发送Send

    • 创建DatagramSocket, 随机端口号(空参构造new即可)

    • 创建DatagramPacket, 指定数据, 长度, 地址, 端口

    • 使用DatagramSocket发送DatagramPacket

    • 关闭DatagramSocket

  • 2.接收Receive

    • 创建DatagramSocket, 指定端口号

    • 创建DatagramPacket, 指定数组, 长度

    • 使用DatagramSocket接收DatagramPacket

    • 关闭DatagramSocket

    • 从DatagramPacket中获取数据

  • 3.接收方获取ip和端口号
    • String ip = packet.getAddress().getHostAddress();
    • int port = packet.getPort();

打开cmd黑窗口,进入.java编译后字节码的bin目录。

cd C:\Users\kangy\Desktop\demo\day26\bin

先执行启动接收端

java com.heima.socket.Demo1_Receive

然后启动发送端

java com.heima.socket.Demo1_Send

Demo1_Send

package com.heima.socket;

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

public class Demo1_Send {

    /**
     * * 1.发送Send
     * 创建DatagramSocket, 随机端口号
     * 创建DatagramPacket, 指定数据, 长度, 地址, 端口
     * 使用DatagramSocket发送DatagramPacket
     * 关闭DatagramSocket
     * @throws SocketException 
     * @throws UnknownHostException 
     */
    public static void main(String[] args) throws Exception {
        String str = "what are you 弄啥呢?";
        DatagramSocket socket = new DatagramSocket();                //创建Socket相当于创建码头
        DatagramPacket packet =                                     //创建Packet相当于集装箱
                new DatagramPacket(str.getBytes(), str.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666);
        socket.send(packet);                                        //发货,将数据发出去
        socket.close();                                                //关闭码头
    }

}
View Code

Demo1_Receive

package com.heima.socket;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class Demo1_Receive {

    /**
     ** 2.接收Receive
     * 创建DatagramSocket, 指定端口号
     * 创建DatagramPacket, 指定数组, 长度
     * 使用DatagramSocket接收DatagramPacket
     * 关闭DatagramSocket
     * 从DatagramPacket中获取数据
     * @throws SocketException 
     */
    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket(6666);        //创建Socket相当于创建码头
        DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);//创建Packet相当于创建集装箱
        socket.receive(packet);                                    //接货,接收数据
        
        byte[] arr = packet.getData();                            //获取数据
        int len = packet.getLength();                            //获取有效的字节个数
        System.out.println(new String(arr,0,len));
        socket.close();
    }

}
View Code

 

Demo2_Send 

package com.heima.socket;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Demo2_Send {

    /**
     * * 1.发送Send
     * 创建DatagramSocket, 随机端口号
     * 创建DatagramPacket, 指定数据, 长度, 地址, 端口
     * 使用DatagramSocket发送DatagramPacket
     * 关闭DatagramSocket
     * @throws SocketException 
     * @throws UnknownHostException 
     */
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);                        //创建键盘录入对象
        DatagramSocket socket = new DatagramSocket();                //创建Socket相当于创建码头
        
        while(true) {
            String line = sc.nextLine();                            //获取键盘录入的字符串
            if("quit".equals(line)||"exit".equals(line)) {
                break;
            }
            DatagramPacket packet =                                 //创建Packet相当于集装箱
                    new DatagramPacket(line.getBytes(), line.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666);
            socket.send(packet);                                    //发货,将数据发出去
        }
        socket.close();                                                //关闭码头
        sc.close();             //关闭Scanner
    }

}
View Code

Demo2_Receive

package com.heima.socket;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class Demo2_Receive {

    /**
     ** 2.接收Receive
     * 创建DatagramSocket, 指定端口号
     * 创建DatagramPacket, 指定数组, 长度
     * 使用DatagramSocket接收DatagramPacket
     * 关闭DatagramSocket
     * 从DatagramPacket中获取数据
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket(6666);        //创建Socket相当于创建码头
        DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);//创建Packet相当于创建集装箱
        
        while(true) {
            socket.receive(packet);                                    //接货,接收数据
            
            byte[] arr = packet.getData();                            //获取数据
            int len = packet.getLength();                            //获取有效的字节个数
            String ip = packet.getAddress().getHostAddress();        //获取ip地址
            int port = packet.getPort();                            //获取端口号
            System.out.println(ip + ":" + port + ":" + new String(arr,0,len));
        }
        
    }

}
View Code

测试命令

java com.heima.socket.Demo2_Receive

java com.heima.socket.Demo2_Send

###26.08_网络编程(UDP传输多线程)

Demo3_MoreThread

package com.heima.socket;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Demo3_MoreThread {

    /**
     * main方法入口
     * @param args
     */
    public static void main(String[] args) {
        new Receive().start();
        
        new Send().start();
    }

}

class Receive extends Thread {
    public void run() {
        try {
            DatagramSocket socket = new DatagramSocket(6666);        //创建Socket相当于创建码头
            DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);//创建Packet相当于创建集装箱
            
            while(true) {
                socket.receive(packet);                                    //接货,接收数据
                
                byte[] arr = packet.getData();                            //获取数据
                int len = packet.getLength();                            //获取有效的字节个数
                String ip = packet.getAddress().getHostAddress();        //获取ip地址
                int port = packet.getPort();                            //获取端口号
                System.out.println(ip + ":" + port + ":" + new String(arr,0,len));
            }
        } catch (IOException e) {
            
            e.printStackTrace();
        }
    }
}

class Send extends Thread {
    public void run() {
        try {
            Scanner sc = new Scanner(System.in);                        //创建键盘录入对象
            DatagramSocket socket = new DatagramSocket();                //创建Socket相当于创建码头
            
            while(true) {
                String line = sc.nextLine();                            //获取键盘录入的字符串
                if("quit".equals(line)||"exit".equals(line)) {
                    break;
                }
                DatagramPacket packet =                                 //创建Packet相当于集装箱
                        new DatagramPacket(line.getBytes(), line.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666);
                socket.send(packet);                                    //发货,将数据发出去
            }
            socket.close();
        }  catch (IOException e) {
            
            e.printStackTrace();
        }        
    }
}
View Code

###26.16_网络编程(TCP协议)(掌握)

  • 1.客户端

    • 创建Socket连接服务端(指定ip地址,端口号)通过ip地址找对应的服务器

    • 调用Socket的getInputStream()和getOutputStream()方法获取和服务端相连的IO流

    • 输入流可以读取服务端输出流写出的数据

    • 输出流可以写出数据到服务端的输入流

  • 2.服务端

    • 创建ServerSocket(需要指定端口号)

    • 调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket

    • 调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流

    • 输入流可以读取客户端输出流写出的数据

    • 输出流可以写出数据到客户端的输入流

 Demo1_Server

package com.heima.tcp;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Demo1_Server {

    /**
     * * 2.服务端
    * 创建ServerSocket(需要指定端口号)
    * 调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket
    * 调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流
    * 输入流可以读取客户端输出流写出的数据
    * 输出流可以写出数据到客户端的输入流
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(12345);
        
        Socket socket = server.accept();                        //接受客户端的请求
        InputStream is = socket.getInputStream();            //获取客户端输入流
        OutputStream os = socket.getOutputStream();            //获取客户端的输出流
        
        os.write("百度一下你就知道".getBytes());                    //服务器向客户端写出数据
        
        byte[] arr = new byte[1024];
        int len = is.read(arr);                                //读取客户端发过来的数据
        System.out.println(new String(arr,0,len));           //将数据转换成字符串并打印
        
        socket.close();
    }

}
View Code

 Demo1_Client

package com.heima.tcp;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Demo1_Client {

    /**
     * * 1.客户端
        * 创建Socket连接服务端(指定ip地址,端口号)通过ip地址找对应的服务器
        * 调用Socket的getInputStream()和getOutputStream()方法获取和服务端相连的IO流
        * 输入流可以读取服务端输出流写出的数据
        * 输出流可以写出数据到服务端的输入流
     * @throws IOException 
     * @throws UnknownHostException 
     */
    public static void main(String[] args) throws UnknownHostException, IOException {
        Socket socket = new Socket("127.0.0.1", 12345);
        
        InputStream is = socket.getInputStream();            //获取客户端输入流
        OutputStream os = socket.getOutputStream();            //获取客户端的输出流
        
        byte[] arr = new byte[1024];
        int len = is.read(arr);                                //读取服务器发过来的数据
        System.out.println(new String(arr,0,len));           //将数据转换成字符串并打印
        
        os.write("学习挖掘机哪家强?".getBytes());                    //客户端向服务器写数据
        
        socket.close();
    }

}
View Code

java com.heima.tcp.Demo1_Server

java com.heima.tcp.Demo1_Client

###26.17_网络编程(TCP协议代码优化)

Demo2_Server

package com.heima.tcp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Demo2_Server {

    /**
     * * 2.服务端
    * 创建ServerSocket(需要指定端口号)
    * 调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket
    * 调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流
    * 输入流可以读取客户端输出流写出的数据
    * 输出流可以写出数据到客户端的输入流
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        //demo1();
        ServerSocket server = new ServerSocket(12345);
        
        while(true) {
            final Socket socket = server.accept();                        //接受客户端的请求
            new Thread() {  //匿名内部类
                public void run() {
                    try {
                        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));        //将字节流包装成了字符流
                        PrintStream ps = new PrintStream(socket.getOutputStream());                    //PrintStream中有写出换行的方法
                        
                        ps.println("欢迎咨询黑马程序员");
                        System.out.println(br.readLine());
                        ps.println("不好意思,爆满了");
                        System.out.println(br.readLine());
                        socket.close();
                    } catch (IOException e) {
                        
                        e.printStackTrace();
                    }
                }
            }.start();
        }
    }

    public static void demo1() throws IOException {
        ServerSocket server = new ServerSocket(12345);
        
        Socket socket = server.accept();                        //接受客户端的请求
        
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));        //将字节流包装成了字符流
        PrintStream ps = new PrintStream(socket.getOutputStream());                    //PrintStream中有写出换行的方法
        
        ps.println("欢迎咨询黑马程序员");
        System.out.println(br.readLine());  //BufferedReader.readLine()
        ps.println("不好意思,爆满了");
        System.out.println(br.readLine());
        socket.close();
    }

}
View Code

Demo2_Client

package com.heima.tcp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Demo2_Client {

    /**
     * * 1.客户端
        * 创建Socket连接服务端(指定ip地址,端口号)通过ip地址找对应的服务器
        * 调用Socket的getInputStream()和getOutputStream()方法获取和服务端相连的IO流
        * 输入流可以读取服务端输出流写出的数据
        * 输出流可以写出数据到服务端的输入流
     * @throws IOException 
     * @throws UnknownHostException 
     */
    public static void main(String[] args) throws UnknownHostException, IOException {
        Socket socket = new Socket("127.0.0.1", 12345);
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));        //将字节流包装成了字符流
        PrintStream ps = new PrintStream(socket.getOutputStream());                    //PrintStream中有写出换行的方法
        
        System.out.println(br.readLine());
        ps.println("我想报名黑马程序员");
        System.out.println(br.readLine());
        ps.println("大哭!!!能不能给次机会");
        
        socket.close();
    }

}
View Code

###26.19_网络编程(练习)

  • 客户端向服务器写字符串(键盘录入),服务器(多线程)将字符串反转后写回,客户端再次读取到是反转后的字符串

Test1_Server

package com.heima.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Test1_Server {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(54321);
        System.out.println("服务器启动,绑定54321端口");
        
        while(true) {
            final Socket socket = server.accept();                    //接受客户端的请求
            
            new Thread() {                                            //开启一条线程
                public void run() {
                    try {
                        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));    //获取输入流
                        PrintStream ps = new PrintStream(socket.getOutputStream());//获取输出流
                        
                        String line = br.readLine();                //将客户端写过来的数据读取出来
                        line = new StringBuilder(line).reverse().toString();    //链式编程
                        ps.println(line);                            //反转后写回去
                        
                        socket.close();
                    } catch (IOException e) {                        
                        
                        e.printStackTrace();
                    }
                }
            }.start();
        }
    }

}
View Code

Test1_Client

package com.heima.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Test1_Client {

    /**
     * 客户端向服务器写字符串(键盘录入),服务器(多线程)将字符串反转后写回,客户端再次读取到是反转后的字符串
     * @throws IOException 
     * @throws UnknownHostException 
     */
    public static void main(String[] args) throws UnknownHostException, IOException {
        Scanner sc = new Scanner(System.in);                //创建键盘录入对象
        Socket socket = new Socket("127.0.0.1", 54321);        //创建客户端,指定ip地址和端口号
        
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));    //获取输入流
        PrintStream ps = new PrintStream(socket.getOutputStream());//获取输出流
        
        ps.println(sc.nextLine());                            //将字符串写到服务器去
        System.out.println(br.readLine());                     //将反转后的结果读出来
        
        socket.close();
    }

}
View Code

 

###26.20_网络编程(练习)

  • 客户端向服务器上传文件

 Test2_UpdateServer

package com.heima.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Test2_UpdateServer {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        //3,建立多线程的服务器
        ServerSocket server = new ServerSocket(12345);
        System.out.println("服务器启动,绑定12345端口号");
        
        //4.读取文件名
        while(true) {
            final Socket socket = server.accept();                    //接受请求
            new Thread() {
                public void run() {
                    try {
                        InputStream is = socket.getInputStream();
                        BufferedReader br = new BufferedReader(new InputStreamReader(is));
                        PrintStream ps = new PrintStream(socket.getOutputStream());
                        String fileName = br.readLine();
                        
                        //5.判断文件是否存在, 将结果发回客户端
                        File dir = new File("update");
                        dir.mkdir();                                //创建文件夹
                        File file = new File(dir,fileName);            //封装成File对象
                        
                        if(file.exists()) {                            //如果服务器已经存在这个文件
                            ps.println("存在");                        //将存在写给客户端
                            socket.close();                            //关闭socket
                            return;
                        }else {
                            ps.println("不存在");
                        }
                        
                        //8.定义FileOutputStream, 从网络读取数据, 存储到本地
                        FileOutputStream fos = new FileOutputStream(file);
                        byte[] arr = new byte[8192];
                        int len;
                        
                        while((len = is.read(arr)) != -1) {
                            fos.write(arr, 0, len);
                        }
                        
                        fos.close();
                        socket.close();
                    } catch (IOException e) {
                        
                        e.printStackTrace();
                    }
                }
            }.start();
        }
        
        
        
    }
}
View Code

Test2_UpdateClient

package com.heima.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Test2_UpdateClient {

    /**
     * @param args
     * @throws IOException 
     * @throws UnknownHostException 
     */
    public static void main(String[] args) throws UnknownHostException, IOException {
        // 1.提示输入要上传的文件路径, 验证路径是否存在以及是否是文件夹
        File file = getFile();
        // 2.发送文件名到服务端
        Socket socket = new Socket("127.0.0.1", 12345);
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        PrintStream ps = new PrintStream(socket.getOutputStream());
        ps.println(file.getName());
        // 6.接收结果, 如果存在给予提示, 程序直接退出
        String result = br.readLine();                        //读取存在后不存在的结果
        if("存在".equals(result)) {
            System.out.println("您上传的文件已经存在,请不要重复上传");
            socket.close();
            return;
        }
        // 7.如果不存在, 定义FileInputStream读取文件, 写出到网络
        FileInputStream fis = new FileInputStream(file);
        byte[] arr = new byte[8192];
        int len;
        
        while((len = fis.read(arr)) != -1) {
            ps.write(arr, 0, len);
        }
        
        fis.close();
        socket.close();
    }

    private static File getFile() {
        Scanner sc = new Scanner(System.in);                //创建键盘录入对象
        System.out.println("请输入一个文件路径:");
        
        while(true) {
            String line = sc.nextLine();
            File file = new File(line);
            
            if(!file.exists()) {
                System.out.println("您录入的文件路径不存在,请重新录入:");
            }else if(file.isDirectory()) {
                System.out.println("您录入的是文件夹路径,请输入一个文件路径:");
            }else {
                return file;
            }
        }
    }
}
View Code

 

posted @ 2020-02-08 20:11  Marlon康  阅读(181)  评论(0编辑  收藏  举报