day-14-(网络编程【Socket网络编程】)

1.网络通信协议

1.网络的概述:

协议:
    在网络之间传出数据是需要按照指定的标准来传输,标准中规定数据的格式,大小,传输的方式,传输的速率;
    标准写在文件中形成一个统一的规范-->按照规范开发的代码->协议;
网络:
    应用层:我们开发的程序在这一层;
    传输层:在这一层指定了使用什么格式,对要发送的数据进行分包和发送;
    网络层:在这一层,会对目标IP地址进行校验
    链路层:包含了网卡及其驱动程序
IP地址:互联网协议地址
    格式: 数字.数字.数字.数字   数字在0-255之间;
    通常说的IP地址是指外网的IP地址;
    内网中的IP都是以192开头的。
作用:用来唯一标识互联网中某一台电脑的地址的,通过IP地址就可以找到对应的电脑;

端口号:
    就是一个数字,范围1-65536,这个数字是用来唯一标识一个安装在你的电脑上的软件。

    1024之前的端口是系统保留的端口;1024之后的可以让开发人员来使用。

    常见的端口:
        tomcat:8080
        http:80
        mysql:3306

    作用:用来唯一标识一个安装在你的电脑上的软件。

    要想给对方发送数据,需要指定发送数据和对方的IP与端口;

2.InetAddress 类

是用来封装 网络地址;

网络地址:ip地址,端口号,主机名称;

常用方法:
public class Example01 {
    public static void main(String[] args) throws Exception {
        InetAddress local = InetAddress.getLocalHost();
        InetAddress remote = InetAddress.getByName("www.itcast.cn");
        System.out.println("本机的IP地址:" + local.getHostAddress());
        System.out.println("itcast的IP地址:" + remote.getHostAddress());
        System.out.println("itcast的主机名为:" + remote.getHostName());
    }
}

3.UDP和TCP协议介绍

UDP称为用户数据报协议;
    特点:
        1.发送端只发送数据,不管接收端是否接收数据或者数据接收是否完整;
        2.接收端只管接收数据;
        3.允许发送的数据出现丢失的现象;
    应用场景:
        视频直播;
        广播;

TCP称为传输控制协议;
    特点:
        1.客户端:发送数据;
        2.服务器端:接收数据;
        3.不允许出现数据丢失的情况;
    应用场景:
        上传下载文件;

4.UDP编程

1.发送端程序

步骤:
    1.创建DatagramSocket对象,作为一个发送端,就相当于一个码头;
    2.创建一个DatagramPacket对象,用于封装要发送的数据,就相当于一个集装箱;
    3.调用DatagramSocket 对象的send方法,发送数据报;
    4.关闭DatagramSocket对象,就相当于关闭码头;

示例代码:

    public class Sender{
        public static void main(String[] args)throws Exception{
        //1.创建DatagramSocket对象,作为一个发送端,就相当于一个码头;
            DatagramSocket s=new DatagramSocket();
        //2.创建一个DatagramPacket对象,用于封装要发送的数据,就相当于一个集装箱;
            byte[] data="今晚7点操场西北角小树林不见不散!”.getBytes();
            DatagramPacket dp=new DatagramPacket(data,data.length,InetAddress.getByName("192.168.186.50"),6000);
        //3.调用DatagramSocket对象send方法,发送数据报;
            s.send(dp);
        //4.关闭DatagramSocket对象,就相当于关闭码头;
            s.close();
        }
    }

2.接收端

步骤:
    1.创建DatagramSocket对象,作为一个发送端,相当于一个码头;
    2.创建一个DatagramPacket对象,用于封装接收的数据,就相当于一个集装箱;
    3.调用DatagramSocket对象的receive方法接收数据;
    4.得到接收的数据;
    5.展示数据;
    6.关闭DatagramPacket对象;

示例代码:

    public class Receiver{
        public static void main(String[] args)throws Exception{
        //1.创建DatagramSocket对象,作为一个发送端,相当于一个码头;
            DatagramSocket s=new DatagramSocket(6000);
        //2.创建一个DatagramPacket对象,用于封装接收的数据,就相当于一个集装箱;
            byte[] buf=new byte[1024];
            DatagramPacket dp=new DatagramPacket(buf,1024);
        //3.调用DatagramSocket对象的receive方法接收数据;
            s.receive(dp);
        //4.得到接收的数据;
            byte[] data=dp.getDate();
        //5.展示数据;
            System.out.println(new String(data);
        //6.关闭DatagramPacket对象;
            s.close();
        }
    }

5.TCP协议编程

1.客户端程序

步骤:
    // 1.创建一个Socket对象,作为客户端;
    // 2.通过Socket对象得到输出流,用于把要发送的数据写到服务器端;
    // 3.使用输出流写数据(发送数据);
    // 4.告诉服务器端发送已经完成;
    // 5.展示数据;
    // 6.关闭流,关闭Socket;

示例代码:

    public class Client {

        public static void main(String[] args) throws Exception {
        // 1.创建一个Socket对象,作为客户端;
            Socket s = new Socket("192.168.186.50", 6000);

        // 2.通过Socket对象得到输出流,用于把要发送的数据写到服务器端;
            OutputStream out = s.getOutputStream();

        // 3.使用输出流写数据(发送数据);
            out.write("今晚7点操作西北角小树林不见散!".getBytes());

        // 4.告诉服务器端发送已经完成;
            s.shutdownOutput();

        //----接收服务器端发送的数据--------------------
            InputStream in = s.getInputStream();
                int len = -1;
                byte[] bArray = new byte[1024];
            while((len=in.read(bArray)) != -1){
                // 5.展示数据;
                System.out.println(new String(bArray,0,len));
            }

                in.close();
        // 6.关闭流,关闭Socket;
                 s.close();
        }

    }

2.服务器端程序

步骤:

    // 1.创建一个ServerSocket对象,作为服务器端;
    // 2.调用ServerSocket对象的accept方法,接收数据,返回的是Socket对象,它对应了客户端对象
    // 3.通过Socket对象得到一个输入流(客户端发送数据使用的那个输出流);
    // 4.通过输入流得到客户端发送的数据;
    // 5.展示数据;
    // 6.关闭流,socket和ServerSocket对象;

示例代码:
    public class Server {

        public static void main(String[] args) throws Exception {
        // 1.创建一个ServerSocket对象,作为服务器端;
            ServerSocket ss = new ServerSocket(6000);

        // 2.调用ServerSocket对象的accept方法,接收数据,返回的是Socket对象,它对应了客户端对象
            Socket s = ss.accept();

        // 3.通过Socket对象得到一个输入流(客户端发送数据使用的那个输出流);
            InputStream in = s.getInputStream();

        // 4.通过输入流得到客户端发送的数据;
                int len = -1;
            byte[] bArray = new byte[1024];
            while((len=in.read(bArray)) != -1){
                // 5.展示数据;
                System.out.println(new String(bArray,0,len));
            }

        // 6.关闭流,socket和ServerSocket对象;
                   //in.close();

        //------以上代码完成了接收的功能-------------------

        //------下面要给客户端返回一个数据----------------------------
            OutputStream out = s.getOutputStream();
            out.write("好的,我一定等你!".getBytes());
                out.close();

                s.close();
                ss.close();
        }

    }   

6.文件上传案例

把客户端中的一个文件的数据读取出来,通过网络发送给服务器端,服务器端接收数据,并将其写到目标文件中;

与上面TCP协议编程i相比,区别在于:

1.客户端发送的数据 是从 文件中读取的;
2.服务器端把接收到的数据写到 一个目标文件中;

示例代码:

1.客户端程序

    public class Client{
        public static void main(String[] args)throws Excpention{
        // 1.创建一个Socket对象,作为客户端;
            Socket s = new Socket("192.168.186.50", 6000);

        // 2.通过Socket对象得到输出流,用于把要发送的数据写到服务器端;
            OutputStream out = s.getOutputStream();

        // 3.创建一个输入流对象,用于从文件中读取数据
            FileInputStream fis = new FileInputStream("E:\\2.jpg");
            int n = -1;
            byte[] b = new byte[1024];
            while((n=fis.read(b)) != -1){

        // 3.使用输出流写数据(发送数据);
            out.write(b,0,n);
            }

        // 4.告诉服务器端发送已经完成;
            s.shutdownOutput();
    //----接收服务器端发送的数据--------------------
            InputStream in = s.getInputStream();
            int len = -1;
            byte[] bArray = new byte[1024];
            while((len=in.read(bArray)) != -1){
        // 5.展示数据;
            System.out.println(new String(bArray,0,len));
            }
            in.close();
        // 6.关闭流,关闭Socket;
             s.close();
    }
}


2.服务器端程序

    public class Server {
        public static void main(String[] args) throws Exception {
        // 1.创建一个ServerSocket对象,作为服务器端;
            ServerSocket ss = new ServerSocket(6000);

        // 2.调用ServerSocket对象的accept方法,接收数据,返回的是Socket对象,它对应了客户端对象
            Socket s = ss.accept();
        // 3.通过Socket对象得到一个输入流(客户端发送数据使用的那个输出流);
            InputStream in = s.getInputStream();

        // 创建一个输出流对象,用于把读到的数据写到目标文件中
            FileOutputStream fos = new FileOutputStream("E:\\"+System.currentTimeMillis()+".jpg");

        // 4.通过输入流得到客户端发送的数据;
            int len = -1;
            byte[] bArray = new byte[1024];
            while((len=in.read(bArray)) != -1){
        // 5.展示数据;
            fos.write(bArray,0,len);
            }
            fos.close();

        // 6.关闭流,socket和ServerSocket对象;
             //in.close();

    //------以上代码完成了接收的功能-------------------

    //------下面要给客户端返回一个数据----------------------------
        OutputStream out = s.getOutputStream();
        out.write("文件上传成功!".getBytes());
        out.close();

        s.close();
        ss.close();
    }
}

7.文件上传-多线程版本

1.只是修改了服务器端代码:

(1)把接收和处理客户端发送的数据代码放到一个while死循环中,让服务器端一直处于等待客户端上传的状态.
(2)把接收数据和写数据到木目标文件的代码使用一个子线程来处理,异步的处理多个客户端上传文件,避免阻塞;

代码如下:

public class Server {

    public static void main(String[] args) throws Exception {
    // 1.创建一个ServerSocket对象,作为服务器端;
    ServerSocket ss = new ServerSocket(6000);

    while(true){
    // 2.调用ServerSocket对象的accept方法,接收数据,返回的是Socket对象,它对应了客户端对象
        final Socket s = ss.accept();
        new Thread(){
            public void run() {
                try {
    // 3.通过Socket对象得到一个输入流(客户端发送数据使用的那个输出流);
                InputStream in = s.getInputStream();

    // 创建一个输出流对象,用于把读到的数据写到目标文件中
        FileOutputStream fos = new FileOutputStream("E:\\"+System.currentTimeMillis()+".jpg");

    // 4.通过输入流得到客户端发送的数据;
        int len = -1;
        byte[] bArray = new byte[1024];
        while((len=in.read(bArray)) != -1){
    // 5.展示数据;
            fos.write(bArray,0,len);
                                }
            fos.close();

    // 6.关闭流,socket和ServerSocket对象;
                //in.close();

    //------以上代码完成了接收的功能-------------------

    //------下面要给客户端返回一个数据----------------------------
        OutputStream out = s.getOutputStream();
        out.write("文件上传成功!".getBytes());
                out.close();

                s.close();
            } catch (Exception e) {
                e.printStackTrace();
                    }
                };
            }.start();
        }
        //ss.close();
    }
}

你可能感兴趣的:(day-14-(网络编程【Socket网络编程】))