Java SE进阶(12)网络编程

一、网络编程介绍

1、网络编程:
是在网络通信写一下,在不同计算机上运行的程序可以进行数据传输。如:QQ聊天,A用户发送信息给B用户需要知道哪些条件呢?

  • 网络编程三要素:

    IP地址:设备在网络中的地址,唯一标识符。

    端口:应用程序在设备中的唯一标识。

    协议:数据在网络中传输的规则,常见的协议由UDP协议和TCP协议。

  • 常见命令

    ipconfig:查看本机ip地址。

    ping ip地址:检查网络是否连通。

    特殊IP地址:127.0.0.1本机地址

    2、Inetaddress类

    ​ Inetaddress:此类表示internel(ip)地址。

    常用方法:

    方法名说明
    static InetAddress getByName(String host)确定主机的ip地址
    String getHostName()获取ip地址的主机名
    String getHostAddress()返回文本显示中的ip地址字符串

二、UDP协议

1、协议:网络中,连接和通信的规则称之为网络通信协议

2、UDP协议

  • 用户数据报协议
  • UDP是面向无连接的通信协议
  • 速度快,有大小限制最多发送64k,数据不安全,易丢失数据。

3、关键代码

DatagramSocket socket = new DatagramSocket()	//码头
DatagramPacket socket = new DatagramPacket()	//箱子

形象表示:

在这里插入图片描述

案例展示:

//发送方
public class SendTest1 {
    public static void main(String[] args) throws IOException {
        //建一个码头用于送货
        //提供寄货的箱子
        //东西都装到箱子里
        //码头发货
        //离开码头
        DatagramSocket socket = new DatagramSocket(); //建一个码头用于送货

            byte[] bytes = "要发送的东西".getBytes();
            InetAddress address = InetAddress.getByName("127.0.0.1");
            int port = 10000;
            DatagramPacket packet = new DatagramPacket(bytes,bytes.length,address,port);//提供寄货的箱子//东西都装到箱子里
            
            socket.send(packet);//码头发货

            socket.close();//离开码头
    }
}

//接收方
public class ReciveTest1 {
    public static void main(String[] args) throws IOException {
        //建一个码头(指定地址的码头收东西)
        // 提供一个收东西的箱子(箱子要有一定的空间)
        //接收箱子
        //取出箱子里的东西
        //离开码头
        DatagramSocket socket = new DatagramSocket(10000);//建一个码头(指定地址的码头收东西)
        
            byte[] bytes = new byte[1024];
            DatagramPacket packet = new DatagramPacket(bytes, bytes.length);// 提供一个收东西的箱子(箱子要有一定的空间)
        
            socket.receive(packet);//接收箱子

            byte[] data = packet.getData();//取出箱子里的东西
            System.out.println(new String(data));

            socket.close();//离开码头
    }
}

4、UDP的三种通信方式

  1. 单播:一对一发送接收

    如上一个代码案例就是单播,一个接收一个发送,加一个死循环就可以一直发送和接收。

  2. 组播:一对一组发送接收

    组播ip地址:224.0.0.0239.255.255.255(其中224.0.0.0224.0.0.255位预留的组播地址)

    //发送方
    public class SendTest2 {
        public static void main(String[] args) throws IOException {
            //建一个码头用于送货
            //提供寄货的箱子
            //东西都装到箱子里
            //码头发货
            //离开码头
            DatagramSocket socket = new DatagramSocket();
            
                
                byte[] bytes = "组播地址".getBytes();
                InetAddress address = InetAddress.getByName("224.0.0.1");//发送端唯一区别ip地址
                int port = 10000;
                DatagramPacket packet = new DatagramPacket(bytes,bytes.length,address,port);
                socket.send(packet);
            
                socket.close();
        }
    }
    //接收端
    public class ReciveTest2 {
        public static void main(String[] args) throws IOException {
            //建一个码头(指定地址的码头收东西)
            // 提供一个收东西的箱子(箱子要有一定的空间)
            //取出箱子里的东西
            //离开码头
            MulticastSocket socket = new MulticastSocket(10000);  //组播接收码头
            byte[] bytes = new byte[1024];
                DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
    
                socket.joinGroup(InetAddress.getByName("224.0.0.1"));  //绑定组播地址,表示加入这一组中
                socket.receive(packet);
    
                byte[] data = packet.getData();
                System.out.println(new String(data));
    
                socket.close();
        }
    }
    
    
  3. 广播:一对所有发送接收(区别在于IP地址不同)

    广播ip地址:255.255.255.255广播地址(局域网内所有用户能够接收到信息)

    //发送方
    public class SendTest {
        public static void main(String[] args) throws IOException {
            //建一个码头用于送货
            //提供寄货的箱子
            //东西都装到箱子里
            //码头发货
            //离开码头
            DatagramSocket socket = new DatagramSocket();
            Scanner scanner = new Scanner(System.in);
            while (true){
                String next = scanner.next();
                if ("886".equals(next)){    //输入886即停止退出循环
                    break;
                }
                byte[] bytes = next.getBytes();
                InetAddress address = InetAddress.getByName("127.0.0.1");//255.255.255.255广播地址(局域网内所有用户能够接收到)
                int port = 10000;
                DatagramPacket packet = new DatagramPacket(bytes,bytes.length,address,port);
                socket.send(packet);
            }
                socket.close();
        }
    }
    //接收端
    public class ReciveTest {
        public static void main(String[] args) throws IOException {
            //建一个码头(指定地址的码头收东西)
            // 提供一个收东西的箱子(箱子要有一定的空间)
            //取出箱子里的东西
            //离开码头
            DatagramSocket socket = new DatagramSocket(10000);
            while (true){
                byte[] bytes = new byte[1024];
                DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
                socket.receive(packet);
    
                byte[] data = packet.getData();
                System.out.println(new String(data));
            }
    //        socket.close();
        }
    }
    

三、TCP协议

1、UDP协议

  • 传输控制协议

  • TCP是面向连接的通信协议

  • 速度慢,无有大小限制,数据不安全。

  • image-20200907233511029

在这里插入图片描述

image-20200907233826919

//发送端
public class SendTest {
    public static void main(String[] args) throws IOException {
        //创建码头
        Socket socket = new Socket("127.0.0.1",1000);
        //获取流读写数据
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("hello".getBytes());
        //释放资源
        socket.close();
    }
}
//接收方
public class ReceiveTest {
    public static void main(String[] args) throws IOException {
        //创建接收方码头
        ServerSocket socket = new ServerSocket(1000);
        //建立通道
        Socket accept = socket.accept();
        //读写出数据
        InputStream inputStream = accept.getInputStream();
        int b;

        while ((b=inputStream.read())!= -1){
            System.out.println((char) b);
        }
        //释放资源
        socket.close();
    }
}

2、三次握手

image-20200907234154330

3、四次握手

image-20200907234340954

案例优化

需求:1、从本地获取一份文件由客户端发送到服务端,服务端回应给客户端接收到了文件,并将文件添加到服务端保存在本地(图片为例)
2、多个客户端请求能够获取服务端文件(UUID保存图片名唯一,多线程用户模拟多个客户端需求,线程池节约系统资源)

//接收方 负责接收发送方文件并保存到本地,给发送方一个收到反馈
public class ReceiveTest003 {
    public static void main(String[] args) throws IOException {

        ServerSocket socket = new ServerSocket(10000);  //建立服务端码头

        ThreadPoolExecutor pool = new ThreadPoolExecutor(   //创建线程池
                2,  //核心线程数
                4, //最大线程数
                60,//空闲线程最大存活时间
                TimeUnit.SECONDS, //空闲时间单位
                new ArrayBlockingQueue(5),//阻塞个数
                Executors.defaultThreadFactory(),//线程工厂
                new ThreadPoolExecutor.AbortPolicy()//拒绝任务策略
        );

        while (true) {

            Socket accept = socket.accept();//建立连接通道

            ThreadTest threadTest = new ThreadTest(accept);//创建线程对象
            Thread t1 = new Thread(threadTest);
//            t1.start();
            pool.submit(t1);//提交线程到线程池

        }

//        socket.close();

    }
}

//线程任务类
class ThreadTest implements Runnable { 
    private Socket accept;

    public ThreadTest(Socket accept) {
        this.accept = accept;
    }

    BufferedOutputStream bos = null;

    @Override
    public void run() {

        try {
            InputStream is = accept.getInputStream();   //获取输入流
            bos = new BufferedOutputStream(new FileOutputStream("D:\\IDEAworkspace\\basic_Code\\copy\\" + UUID.randomUUID().toString() + ".jpg"));//创建字节输出流用于保存文件位置(UUID提供不唯一的标识符做名称)

            int b;
            while ((b = is.read()) != -1) { //读取文件
                bos.write(b);               //写入文件
            }
            OutputStream os = accept.getOutputStream(); //获取输出流用于给发送端发送一个反馈
            os.write("接收到了".getBytes());

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                accept.shutdownInput();	//关流
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                accept.shutdownOutput();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值