• java - 网络编程TCP/IP


    概述

    TCP:类似于打电话这种,接通后双方开始通话。
    UDP:类似于发短信这种,一方发送一方接收。

    计算机网络

    计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。

    网络编程的目的

    传播交流信息,数据交换,通信。

    网络编程中方的主要问题

    • 如何准确定位到网络上的一台或多台主机
    • 找到主机之后如何通信

    网络通信的要素

    • IP和端口号
    • 网络通信协议

    TCP/IP参考模型

    在这里插入图片描述

    IP

    IP地址:InetAddress

    • 唯一定位一台网络上的计算机
    • 127.0.0.1:本机localhost
    • IP地址的分类:ipv4 / ipv6、公网/私网

    获取ip

    package com.zls.demo01;
    
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    public class TestInetAddress {
        public static void main(String[] args) {
            try {
                //查询本机地址
                InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");
                System.out.println(inetAddress1);
                InetAddress inetAddress2 = InetAddress.getByName("localhost");
                System.out.println(inetAddress2);
                InetAddress inetAddress3 = InetAddress.getLocalHost();
                System.out.println(inetAddress3);
    
                //查询网站ip地址
                InetAddress inetAddress4 = InetAddress.getByName("www.baidu.com");
                System.out.println(inetAddress4);
    
                //常用方法
                System.out.println(inetAddress4.getAddress());
                System.out.println(inetAddress4.getCanonicalHostName()); //规范的名称
                System.out.println(inetAddress4.getHostAddress()); //ip
                System.out.println(inetAddress4.getHostName()); //域名
    
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    在这里插入图片描述

    端口

    概念

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

    • 不同的进程 有不同的端口号,用于区分软件
    • 单个协议下端口号不能冲突
    • 端口号分类:
      • 公有端口: 0 ~ 1023。
        HTTP:80;HTTPS:443;FTP:21;Telent:23;
      • 私有端口: 1024 ~ 49151。分配给用户或者程序员
        Tomcat:8080;MySQL:3306;Oracle:1521;
      • 动态端口: 49152 ~ 65535

    关于端口的指令

    netstat -ano #查看所有端口
    netstat -ano|findstr "5900" #查看指定端口
    tasklist|findstr "8696" #查看指定端口的进程
    Ctrl + Shift + Esc #打开任务管理器的快捷键
    
    • 1
    • 2
    • 3
    • 4

    获取端口

    package com.zls.demo01;
    
    import java.net.InetSocketAddress;
    
    public class TestInetSocketAddress {
        public static void main(String[] args) {
            InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1", 8080);
            System.out.println(socketAddress);
            System.out.println(socketAddress.getPort());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    通信协议

    实现消息传递

    模拟服务端

    1. 建立服务器的端口 ServerSocket
    2. 等待用户的链接
    3. 接收用户的消息
    package com.zls.demo02;
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    //服务端
    public class TcpServerDemo01 {
        public static void main(String[] args) {
            ServerSocket serverSocket = null;
            Socket socket = null;
            InputStream is = null;
            ByteArrayOutputStream baos = null;
    
            try {
                //1.需要一个地址
                serverSocket = new ServerSocket(9999);
                //2.等待客户端链接
                socket = serverSocket.accept();
                //3.读取客户端的消息
                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();
                    }
                }
    
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    模拟客户端

    1. 连接服务器Socket
    2. 发送消息
    package com.zls.demo02;
    
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.InetAddress;
    import java.net.Socket;
    
    //客户端
    public class TcpClientDemo01 {
        public static void main(String[] args) {
            Socket socket = null;
            OutputStream os = null;
            try {
                //1.需要知道服务器的地址、端口号
                InetAddress serverIP = InetAddress.getByName("127.0.0.1");
                int port = 9999;
                //2.创建一个Socket链接
                socket = new Socket(serverIP,port);
                //3.发送消息 IO源
                os = socket.getOutputStream();
                os.write("你好世界".getBytes());
    
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                if (socket != null){
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (os != null){
                    try {
                        os.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    结果

    在运行服务器端后在运行客户端,服务器端就能接收到客户端发来的消息
    在这里插入图片描述

    实现文件上传

    模拟服务端

    1. 建立服务器的端口 ServerSocket
    2. 等待用户的链接
    3. 接收用户的消息
    package com.zls.demo02;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TcpServerDemo02 {
        public static void main(String[] args) throws Exception {
            //1.创建服务(端口)
            ServerSocket serverSocket = new ServerSocket(9000);
            //2.监听客户端链接
            Socket socket = serverSocket.accept();//阻塞式监听,会一直等待客户端链接
            //3.获取输入流
            InputStream is = socket.getInputStream();
    
            //4.文件输出
            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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    模拟客户端

    1. 连接服务器Socket
    2. 发送消息
    package com.zls.demo02;
    
    import java.io.*;
    import java.net.InetAddress;
    import java.net.Socket;
    
    public class TcpClientDemo02 {
        public static void main(String[] args) throws Exception {
            //1.创建一个Socket链接
            Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
            //2.创建一个输出流
            OutputStream os = socket.getOutputStream();
    
            //3.文件流 读取文件
            FileInputStream fis = new FileInputStream(new File("tx.jpg"));
            //4.写出文件
            byte[] buffer = new byte[1024];
            int len;
            while ((len = fis.read(buffer)) != -1){
                os.write(buffer,0,len);
            }
    
            //通知服务器传输完毕
            socket.shutdownOutput();//已经传输完毕了
    
            //确定服务器接收完毕,再断开链接
            InputStream inputStream = socket.getInputStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer2 = new byte[1024];
            int len2;
            while ((len2 = inputStream.read(buffer2)) != -1){
                baos.write(buffer2,0,len2);
            }
    
            System.out.println(baos.toString());
    
    
            //5.关闭资源
            fis.close();
            os.close();
            socket.close();
            baos.close();
            inputStream.close();
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    结果

    在这里插入图片描述

    UDP

    发送消息

    模拟服务端

    (流程在代码注释中)

    package com.zls.demo03;
    
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    
    //要等待客户端的链接
    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(new String(packet.getData(),0, packet.getLength()));
    
            //关闭链接
            socket.close();
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    模拟客户端

    (流程在代码注释中)

    package com.zls.demo03;
    
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    
    //不需要链接服务器
    public class UdpClientDemo01 {
        public static void main(String[] args) throws Exception {
            //1.建立一个Socket
            DatagramSocket socket = new DatagramSocket();
            //2.建个包
            String msg = "你好呀,服务器";
    
            //发送给谁
            InetAddress localhost = InetAddress.getByName("localhost");
            int port = 9090;
            //数据,数据长度起始,发送给谁
            DatagramPacket packet = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,localhost,port);
            //3.发送包
            socket.send(packet);
            //4.关闭流
            socket.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    结果

    在这里插入图片描述

    实现聊天(连续发送)

    模拟接收端

    package com.zls.demo03;
    
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    
    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, packet.getLength());
    
                System.out.println(receiveData);
    
                //断开链接
                if (receiveData.equals("bye"))
                    break;
            }
    
            socket.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    模拟发送端

    package com.zls.demo03;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetSocketAddress;
    
    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();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    结果

    成功发送:
    在这里插入图片描述
    成功接收:
    在这里插入图片描述

    实现在线咨询(双发都可以发送和接收)

    要通过线程实现

    发送类

    package com.zls.demo03;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetSocketAddress;
    import java.net.SocketException;
    
    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() {
            while (true){
                String data = null;
                try {
                    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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    接收类

    package com.zls.demo03;
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.SocketException;
    
    public class TalkReceive implements Runnable{
    
        DatagramSocket socket = null;
    
        private int port;
        private String msgFrom;
    
        public TalkReceive(int port, String msgFrom) {
            this.port = port;
            this.msgFrom = msgFrom;
            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, packet.getLength());
    
                    System.out.println(msgFrom + ":" + receiveData);
    
                    //断开链接
                    if (receiveData.equals("bye"))
                        break;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
            socket.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    开启线程

    注意端口的对应关系
    在这里插入图片描述

    结果

    学生视角:
    在这里插入图片描述
    老师视角:
    在这里插入图片描述

    URL

    统一资源定位器:定位互联网上的某一个资源。

    实现在网站上下载资源:
    (该网址是提前打开tomcat放置的一个文件)

    package com.zls.demo04;
    
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    public class URLDemo01 {
        public static void main(String[] args) throws Exception {
            //1.下载地址
            URL url = new URL("http://localhost/zls/secretFile.txt");
    
            //2.链接到这个资源 HTTP
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
    
            InputStream inputStream = urlConnection.getInputStream();
            FileOutputStream fos = new FileOutputStream("secretFile.txt");
    
            byte[] buffer = new byte[1024];
            int len;
            while((len = inputStream.read(buffer)) != -1){
                fos.write(buffer,0,len); //这出这个数据
            }
    
            fos.close();;
            inputStream.close();
            urlConnection.disconnect();
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    在这里插入图片描述

  • 相关阅读:
    【ASM】字节码操作 工具类与常用类 TraceClassVisitor 介绍
    妙手ERP功能更新丨TikTok采集箱显示并可设置货源价格、美客多新增定价模板和尺码表、订单设置新增规范使用库存等
    如何找回这个辅助窗口
    2023年中国鸡蛋市场供需现状、市场规模及产品价格走势分析[图]
    计算机网络
    扬帆牧哲:shopee台湾站点卖什么?
    vue3工程引用vue2模块文件时所做的修改
    Linux网络编程---Socket编程
    黑群辉+腾讯云+frp内网穿透
    java-web:Servlet、cookie、session
  • 原文地址:https://blog.csdn.net/m0_50754064/article/details/124910727