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:UserskangyDesktopdemoday26in

先执行启动接收端

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
部分内容来自于学习编程期间收集于网络的免费分享资源和工作后购买的付费内容。
原文地址:https://www.cnblogs.com/MarlonKang/p/12284821.html