Java之网络编程详解

网络编程

概述

  • 地球村概念 :也译为世界村(global village),对地球的一种比喻说法现代科技的迅速发展,缩小了地球上的时空距离,国际交往日益频繁便利,因而整个地球就如同是茫茫宇宙中的一个小村落。
  • 计算机网络:计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统网络管理软件网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
  • 网络编程的目的:传播交流信息 数据交换 通信
  • 想要达到这个效果需要什么:
    1. 如何准确的定位网络上的一台主机 :IP地址、端口 、定位资源
    2. 找到了这个主机,如何传输数据呢?
  • javaweb:网页编程 B/S
  • 网络编程 : TCP/IP C/S

网络通信的要素

  • 如何实现网络的通信

    • IP
    • 端口号
  • 规则:网络通信的协议

    • TCP/IP 参考模型
      在这里插入图片描述
  • 小结:

    1. 网络编程中有两个主要的问题:
      • 如何准确的定位到网络上的一台或多台主机
      • 找到主机后如何进行通信
    2. 网络编程中的要素
      • IP 和 端口号 IP
      • 网络通信协议 TCP
    3. java 万物皆对象

IP 地址

  • IP 地址类:inetAddress

    • 唯一定位一台网络上的计算机
    • 127.0.0.1 本机 localhost
    • IP 地址的分类
      • IP 地址分类 : 公网(互联网)/私网(局域网)
      • 196.168.xx.xx : 专门给组织机构使用
      • ABCD类地址
      • IPV4/IPV6
        • IPV4: 127.0.0.1 , 4个字节组成 ,0~255
        • IPV6:128位,8个无符号整数
  • 域名:记忆IP问题

  • //测试IP
    public class TestInetAddress {
        public static void main(String[] args) {
            try {
    //            查询本机地址
                InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");
                System.out.println(inetAddress1);
                InetAddress inetAddress3 = InetAddress.getByName("localhost");
                System.out.println(inetAddress3);
                InetAddress inetAddress4 = InetAddress.getLocalHost();
                System.out.println(inetAddress4);
    //          查询网站ip地址
                InetAddress inetAddress2 = InetAddress.getByName("www.baidu.com");
                System.out.println(inetAddress2);
    
    //            常用方法
                System.out.println(inetAddress2.getAddress());
                System.out.println(inetAddress2.getCanonicalHostName());//规范的名字
                System.out.println(inetAddress2.getHostAddress());//IP
                System.out.println(inetAddress2.getHostName());//域名 , 或者自己电脑的名字
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
        }
    }
    

端口

  • 端口表示计算机上一个程序的进程

    • 不同的进程有不同的端口号!
    • 被端口0~65536
    • TCP/UDP 65536*2 单个协议下,端口号不能冲突
  • 端口分类

    • 公有端口0~1023
      • HTTP:80
      • HTTPS:443
      • FTP:21
      • SSH:22
      • Telent:23
    • 程序注册端口:1024~49151, 分配用户或者程序
      • Tomcat:8080
      • MySQL:3306
      • Oracle:1521
    • 动态、私有:49152~65535
      • netstat -ano : 查看所有端口
      • netstat -ano |findstr “xxx” 查看指定端口
      • tasklist|findstr “12412” 查看指定宽口的进程
  • import java.net.InetSocketAddress;
    
    public class TestInetSocketAddress {
        public static void main(String[] args) {
            InetSocketAddress inetSocketAddress =   new InetSocketAddress("127.0.0.1",8080);
            System.out.println(inetSocketAddress);
            InetSocketAddress inetSocketAddress2 =   new InetSocketAddress("localhost",8080);
            System.out.println(inetSocketAddress2);
    
            System.out.println(inetSocketAddress.getAddress());
            System.out.println(inetSocketAddress.getHostName());
            System.out.println(inetSocketAddress.getPort());
        }
    }
    

通信协议

协议:约定 就好比我们说的普通话

网络通信协议:速率,传输码率,代码结构,传输控制

TCP/IP协议簇(实际上是一组协议):

  • TCP : 用户传输协议
  • UDP : 用户数据报协议
  • IP : 网络互联协议

TCP UDP 对比:

  • TCP : 打电话
    • 连接,稳定
    • 三次握手,四次挥手
    • 分为客户端 和 服务端
    • 传输完成后释放连接 ,效率低
  • UDP : 发短信
    • 不建立连接,不稳定
    • 客户端和服务端没有明确的界限
    • 不管有没有准备好,都可以发给你
    • DDOS : 洪水攻击!

TCP 实现聊天

客户端:

  1. 连接服务器Socket
  2. 发送消息
  • //客户端
    public class TcpClientDemo01 {
        public static void main(String[] args) {
            Socket socket = null;
            OutputStream os = null;
            try {
                //要知道服务器的地址
                InetAddress  serverIP = InetAddress.getByName("127.0.0.1");
                //端口号
                 int port = 9999;
                 // 创建一个 socket 连接
                socket = new Socket(serverIP,port);
                //发送消息 IO 流
                os = socket.getOutputStream();
                os.write("你好,欢迎学习java".getBytes());
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                if (os != null){
                    try {
                        os.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (socket != null){
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
    
            }
        }
    }
    

服务器:

  1. 建立服务的端口ServerSocket
  2. 等待用户连接 accept
  3. 接收用户的消息
  • //服务端
    public class TcpServerDemo01 {
        public static void main(String[] args) {
            ServerSocket serverSocket = null;
            Socket socket = null;
            InputStream is = null;
            ByteArrayOutputStream baos = null;
            try {
                //我得有一个地址
                serverSocket = new ServerSocket(9999);
                while (true){
                    // 等待客户端连接
                    socket = serverSocket.accept();
                    // 读取客户端的消息
                    is = socket.getInputStream();
    
                    // 管道流
                    baos = new ByteArrayOutputStream();
                    byte[] buffer = new byte[1024];
                    int len;
                    while ((len = is.read(buffer))!=-1){
                        baos.write(buffer,0,len);
                    }
                    System.out.println(baos.toString());
                }
                } catch (IOException e) {
                e.printStackTrace();
            }finally {
                //关闭流
                if (baos!=null){
                    try {
                        baos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (is!=null){
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (socket!=null) {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (serverSocket!=null) {
                    try {
                        serverSocket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
      /*
                            byte[] buffer = new byte[1024];
                int len;
                while ((len = is.read(buffer))!=-1){
                    String msg = new String(buffer, 0, len);
                    System.out.println(msg);
                }
                 */
    

TCP 实现文件上传

服务器端:

public class TcpServerDemo02 {
    public static void main(String[] args) throws Exception{
//        创建服务
        ServerSocket serverSocket = new ServerSocket(9000);
//        监听客户的连接
        Socket socket = serverSocket.accept();// 阻塞式监听,会一直等待
//        获取输入流
        InputStream is = socket.getInputStream();
//        文件输出
        FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));
        byte[] buffer = new byte[1024];
        int len;
        while ((len = is.read(buffer))!=-1){
            fos.write(buffer,0,len);
        }

//        通知客户端我接受完毕了
        OutputStream os = socket.getOutputStream();
        os.write("我接受完毕了,你可以断开了".getBytes());


        //关闭资源
        fos.close();
        is.close();
        socket.close();
        serverSocket.close();
    }
}

客户端:

public class TcpClientDemo02 {
    public static void main(String[] args)throws Exception {
//        创建一个Socket 连接
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
//        创建一个输出流
        OutputStream os = socket.getOutputStream();
//        读取文件
        FileInputStream fis = new FileInputStream(new File("下载.jpg"));
//        写出文件
        byte[] buffer = new byte[1024];
        int len;
        while ((len = fis.read(buffer))!=-1){
            os.write(buffer,0,len);
        }
//        通知服务器,我已经结束了
        socket.shutdownOutput();//我已经传输完了


//        确定服务器接收完毕,才能够断开连接
        InputStream is = socket.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        byte[]  buffer2 = new byte[1024];
        int len2;
        while ((len2=is.read(buffer2))!=-1){
            baos.write(buffer2,0,len2);
        }
        System.out.println(baos.toString());

//        关闭资源
        baos.close();
        is.close();
        fis.close();
        os.close();
        socket.close();
    }
}

初始Tomcat

服务端:

  • 自定义 S
  • Tomcat 服务器 S

客户端:

  • 自定义 C
  • 浏览器 B

UDP 消息发送

  • 发送端:

  • //不需要链接服务器
    public class UdpClientDemo01 {
        public static void main(String[] args) throws Exception{
    //        建立一个Socket
            DatagramSocket socket = new DatagramSocket();
    //        建立包
            String msg = "你好啊服务器!";
    //        发送给谁
            InetAddress localhost = InetAddress.getByName("localhost");
            int port = 9090;
    //        数据,数据的长度起始,要发送给谁 ,IP地址 , 端口
            DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);
    //        发送包
            socket.send(packet);
    
    //        关闭流
            socket.close();
        }
    }
    
  • 接收端:

  • // 还是要等待客户端的连接
    public class UdpServerDemo01 {
        public static void main(String[] args) throws Exception{
    //        开放端口
            DatagramSocket socket = new DatagramSocket(9090);
    //        接受数据包
            byte[] buffer = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);//接受
            socket.receive(packet);// 阻塞接受
    
            System.out.println(packet.getAddress().getHostAddress());
            System.out.println(new String(packet.getData(),0,packet.getLength()));
    
    //        关闭连接
            socket.close();
        }
    }
    

UDP聊天实现

  • 循环发送方

  • public class UdpSenderDemo01 {
        public static void main(String[] args) throws Exception{
            DatagramSocket socket = new DatagramSocket(8888);
    
    //       准备数据: 控制台读取  System.in
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            while (true){
                String data = reader.readLine();
                byte[] datas = data.getBytes();
                DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",6666));
    
                socket.send(packet);
                if (data.equals("bye")){
                    break;
                }
            }
            socket.close();
        }
    }
    
  • 循环接受方

  • public class UdpReceiveDemo01 {
        public static void main(String[] args) throws Exception{
            DatagramSocket socket = new DatagramSocket(6666);
            while (true){
                //        准备接受包裹
                byte[] container = new byte[1024];
                DatagramPacket packet = new DatagramPacket(container,0,container.length);
                socket.receive(packet);//阻塞式接受包裹
    //            断开链接
                byte[] data = packet.getData();
                String receiveData = new String(data, 0, data.length);
                System.out.println(receiveData);
    
                if (receiveData.equals("bye")){
                    break;
                }
            }
            socket.close();
        }
    }
    

UDP 多线程实现在线咨询

  • 学生咨询:

  • public class TalkSend implements Runnable{
        DatagramSocket socket = null;
        BufferedReader reader = null;
    
    
        private int fromPort;
        private String toIP;
        private int toPort;
    
        public TalkSend(int fromPort, String toIP, int toPort) {
            this.fromPort = fromPort;
            this.toIP = toIP;
            this.toPort = toPort;
    
            try {
                socket = new DatagramSocket(fromPort);
                reader = new BufferedReader(new InputStreamReader(System.in));
            } catch (SocketException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void run() {
    
    //       准备数据: 控制台读取  System.in
            while (true){
    //            String data = null;
                try {
                    String data = reader.readLine();
                    byte[] datas = data.getBytes();
                    DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress(this.toIP,this.toPort));
                    socket.send(packet);
                    if (data.equals("bye")){
                        break;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            socket.close();
        }
    }
    
  • public class TalkStudent {
        public static void main(String[] args) {
    //        开启两个线程
            new Thread(new TalkSend(7777,"localhost",9999)).start();
            new Thread(new TalkReceive(8888,"老师")).start();
        }
    }
    
  • 老师回答:

  • public class TalkReceive implements Runnable{
        DatagramSocket socket = null;
        private int port;
        private String magFrom;
    
        public TalkReceive(int port,String magFrom) {
            this.port = port;
            this.magFrom = magFrom;
            try {
                socket = new DatagramSocket(port);
            } catch (SocketException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void run() {
            while (true){
                try {
                    //准备接受包裹
                    byte[] container = new byte[1024];
                    DatagramPacket packet = new DatagramPacket(container,0,container.length);
                    socket.receive(packet);//阻塞式接受包裹
    //            断开链接
                    byte[] data = packet.getData();
                    String receiveData = new String(data, 0, data.length);
                    System.out.println(magFrom+" :"+receiveData);
                    if (receiveData.equals("bye")){
                        break;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            socket.close();
        }
    }
    
  • public class TalkTeacher {
        public static void main(String[] args) {
            new Thread(new TalkSend(5555,"localhost",8888)).start();
            new Thread(new TalkReceive(9999,"学生")).start();
        }
    }
    

URL下载网络资源

  • 统一资源定位符:定位资源的,定位互联网上的某一个资源

  • DNS域名解析: 就是把域名解析一个IP地址

  • 协议: // IP地址 :端口 /项目名/资源

  • public class URLDown {
        public static void main(String[] args)throws Exception {
    //        下载地址
    //        URL url = new URL("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2Ftp09%2F210611094Q512b-0-lp.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1643212210&t=06966e22fa9ff7890e75fbfe09ae8d0a");
            URL url = new URL("https://m10.music.126.net/20211228002550/1e889b24fa7b2494a4695c6d024dad83/yyaac/0708/0652/0508/0b9b6827b718aa223af92bd52aa2424f.m4a");
    //       链接到这个资源 HTTP
            HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
    
            InputStream is = urlConnection.getInputStream();
    
            FileOutputStream fos = new FileOutputStream("xxx.m4a");
    
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer))!=-1){
                fos.write(buffer,0,len);//写出这个数据
            }
            fos.close();
            is.close();
            urlConnection.disconnect();//断开链接
        }
    }
    
  • 可以下载网上的图片和歌

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值