java零基础 高阶函数 状态模式 caching cmd uwp mui Notify.js 百度seo关键词优化 bootstrap管理模板 pmp培训视频 list获取最后一个元素 js鼠标离开事件 matlab读取dat文件 css选择器有几种 oracle重命名表名 matlab不等于 oracle查看所有数据库 python开发环境 python正则替换 java中正则表达式 java中new javaabstract java遍历set java常用数据结构 linux硬盘 心理学与生活txt 凯立德地图免费下载 atq js数组删除指定元素 字幕制作软件哪个好 python输入数字 51脚本 iphone滚动截屏 彻底删除mysql 1660ti 矩阵分析与应用 xflow 视频编辑专家下载 脚本列表
当前位置: 首页 > 学习教程  > 编程语言

Day17,18 网络编程:通信协议(TCP,UDP),IP,端口

2020/9/19 16:17:46 文章标签: 测试文章如有侵权请发送至邮箱809451989@qq.com投诉后文章立即删除

网络编程

1.1、概述

地球村:

对地球的一种比喻说法。现代科技的迅速发展,缩小了地球上的时空距离,国际交往日益频繁便利,因而整个地球就如同是茫茫宇宙中的一个小村落。

计算机网络:

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

网络编程的目的:

无线电台…传播交流信息,数据交换。通信。

想要达到的效果需要什么:

  1. 如何准确的定位网络上的一台电脑 192.168.16.124:端口,定位到这个计算机上的某个资源。
  2. 找到这个主机,如何传输数据呢?

javaweb:网页编程 BS

网络编程:TCP/IP CS

1.2、网络通信的要素

如何实现网络通信?

需要知道通信双方地址:

  • ip 192.168.1.1
  • 端口号
  • 192.168.16.24:5900

规则:网络通信协议

TCP/IP 参考模型

在这里插入图片描述

小结:

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

1.3、IP

ip地址:InetAddress

  • 唯一定位一台计算机

  • 127.0.01:本机localhost

  • ip地址分类

    • ipv4/ipv6地址分类

      • IPV4 127.0.0.1 ,4个字节组成,1个字节8位。0-255,42亿~;30亿都在北美,亚洲4亿,2011年就用尽了。
      • IPV6 fe80::e574:5dfc:4204:8875%11,16个字节,128位。8个无符号整数。
      2001:0bb2:aaa:0015:0000:0000:1aaa:1312
      每个数字都是16进制,一个十六进制数可以写成4个二进制数(就是占4位)。共32个数字*4位=128
      
    • 公网(互联网)-私网(局域网)

      • ABCD类地址

      • 192.168.xx.xx ,专门给组织内部使用的。

  • 域名:记忆IP问题!

    • IP:www.vip.com 万网
import java.net.UnknownHostException;

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

}

1.4、端口

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

  • 不同进程有不同的端口号!用来区分软件!

  • 端口被规定范围:0~65535

  • TCP,UDP:这两个都有65535这么多端口,即65535*2。tcp:80,udp:80.单个协议下,端口号不能冲突。

  • 端口分类

    • 公有端口0-1023

      • HTTP默认端口:80
      • HHTPS默认端口:443
      • FTP:21
      • Telent:23
    • 程序注册端口:1024~49151,非陪用户或者程序

      • Tomcat:8080
      • MySQL:3306
      • Oracle:1521
    • 动态、私有:49152-65535

      netstat -ano 命令:可以查看本机开放的全部端口。
      
      • LISTENING时表示处于侦听状态,就是说该端口是开放的,等待连接,但还没有被连接。就像
        你房子的门已经敞开的,但还没有人进来。
      • ESTABLISHED的意思是建立连接。表示两台机器正在通信。
      • CLOSE_WAIT 对方主动关闭连接或者网络 异常导致连接中断。
      • TIME_WAIT 我方主动调用close()断开连接,收到对方确认后状态变为TIME_WAIT。
      netstat -ano|findstr "5900":查看5900端口详情。
      tasklist|findsr "8696" :查看指定端口的进程。(或者电脑任务管理器里面的PID栏查看)
      
      public class TestInetSocktaddress {
          public static void main(String[] args) {
              InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 8080);
              InetSocketAddress inetSocketAddress2 = new InetSocketAddress("localhost", 8080);
              System.out.println(inetSocketAddress);
              System.out.println(inetSocketAddress2);
              System.out.println(inetSocketAddress.getAddress());
              System.out.println(inetSocketAddress.getHostName());//hosts文件可以配置映射地址
              System.out.println(inetSocketAddress.getPort());//端口
          }
      }
      

在这里插入图片描述

1.5、通信协议

协议:约定,就好比我们现在说的是普通话。

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

**问题:**非常的复杂

大事化小:分层!

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

重要:

  • TCP:用户传输协议。
  • UDP:用户数据报协议。

出名的协议:

  • TCP:用户传输协议。
  • IP:网络互联协议。

TCP和UDP对比:

TCP:打电话

  • 连接,稳定
  • 三次握手,四次挥手。
最少需要三次,保证稳定连接!
A:你瞅啥?
B:瞅你咋地?
A:干一场!

四次挥手:
A:我要走了
B:你真的要走了吗?
B:你真的真的要走了吗?
A:我真的要走了!

在这里插入图片描述
在这里插入图片描述

  • 客户端,服务端
  • 传输完成,释放连接,效率低

UDP:发短信

  • 不连接,不稳定。
  • 客户端、服务端:没有明确的界限。
  • 不管有没有准备好,都可以发给你。
  • 导弹攻击
  • DDOS:洪水攻击!(饱和攻击)

1.6、TCP

客户端

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

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (outputStream!=null){
                try {
                    outputStream.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 inputStream = null;
        ByteArrayOutputStream baos = null;
        try {
            //1.我得有一个地址
            serverSocket = new ServerSocket(9999);
            while (true){
                //2.等待客户端连接过来
                socket = serverSocket.accept();
                //3.读取客户端的消息
                inputStream = socket.getInputStream();
                //管道流
                baos = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len;
                while ((len = inputStream.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 (inputStream != null) {
                try {
                    inputStream.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();
                }
            }
        }
    }
}

文件上传

//服务端
public class TcpServerDemo02 {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream inputStream = null;
        FileOutputStream baos = null;
        OutputStream outputStream = null;
        try {
            //1.创建服务
            serverSocket = new ServerSocket(9000);

            //2.监听客户端连接//阻塞式监听,会一直等待客户端连接
            socket = serverSocket.accept();
            //3.读取客户端的消息//获取输入流
            inputStream = socket.getInputStream();
            //4.文件输出,利用管道流
            baos = new FileOutputStream(new File("jyw123.jpg"));
            byte[] buffer = new byte[1024];
            int len;
            //每次读取一个字节
            while ((len = inputStream.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }

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


        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (baos != null) {
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.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();
                }
            }


        }
    }
}
//客户端
public class TcpClientDemo02 {
    public static void main(String[] args) {
        //1。创建一个Socket连接
        Socket socket = null;
        try {
            socket = new Socket(InetAddress.getByName("127.0.0.1"),9000);
            //2.创建一个输出流
            OutputStream outputStream = socket.getOutputStream();
            //3.文件流
            FileInputStream fileInputStream = new FileInputStream(new File("F:\\worksapce\\wlbc-study\\src\\123.jpg"));
            //4.写出文件
            byte[] buffer = new byte[1024];
            int len;
            // read (byte[] b) 方法, 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。以整数形式返回实际读取的字节数。
            while ((len=fileInputStream.read(buffer))!=-1){
                outputStream.write(buffer,0,len);
            }

            //通知服务器,我已经结束了
            socket.shutdownOutput();//我已经传输完了

            //确定服务器接收完毕,才能断开连接
            InputStream inputStream = socket.getInputStream();
            //String byte[]
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer2 = new byte[2014];
            int len2;
            while ((len2=inputStream.read(buffer2))!=-1){
                baos.write(buffer2,0,len2);
            }
            System.out.println(baos.toString());
            //5.关闭资源
            baos.close();
            fileInputStream.close();
            outputStream.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Tomcat

服务端

  • 自定义S
  • Tomcat服务器S

客户端

  • 自定义 C
  • 浏览器 B

1.7、UDP

发短信:不用连接,需要知道对方的地址!

发送消息:

public class UdpClientDemo1 {
    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();
    }
}

接收消息

//还是要等待客户端的连接!
public class UdpServerDemo1 {
    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();

    }
}

循环发送消息

public class UdpSendDemo01 {
    public static void main(String[] args) throws Exception {

        DatagramSocket socket = new DatagramSocket(8888);

        //准备数据:读取控制台Ststem.in
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            String data = reader.readLine();
            byte[] dates = data.getBytes();
            DatagramPacket packet = new DatagramPacket(dates, 0, dates.length, new InetSocketAddress("localhost", 6666));
            System.out.println(dates.length);//bye:3
            System.out.println(packet.getLength());//bye:3

            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) {
            //准备接收包裹,放到container里面
            byte[] container = new byte[1024];
            System.out.println(container.length);//1024
            DatagramPacket packet = new DatagramPacket(container, 0, container.length);
            System.out.println(packet.getLength());//1024
            socket.receive(packet);//阻塞式接收包裹。上面是1024,下面是3,说明receive方法将他改变了
            System.out.println(packet.getLength());//3

            //断开连接byte
            byte[] data = packet.getData();//1024
            //String receiveData = new String(data, 0, data.length);//1024
            String receiveData = new String(data, 0, packet.getLength());
            //我不需要固定数组container那么长(1024),我只需要packet里面数据长度(3),这样写后面的equals判断不需要写trim()

            System.out.println(packet.getLength());//收到的是长度是3
            System.out.println(data.length);//1024
            System.out.println(receiveData.length());//3
            System.out.println(receiveData);
            if (receiveData.trim().equals("bye")) {
                break;
            }
        }
        socket.close();
    }
}

在线咨询:两个人都可以发送方,也都可以是接收方!

多线程互相聊天

发送类工具

//发送线程
public class TalkSend implements Runnable{
    DatagramSocket socket =null;
    BufferedReader reader =null;
    private String toIp;
    private int fromPort;
    private int toPort;

    public TalkSend(int fromPort,String toIp,  int toPort) {
        this.toIp = toIp;
        this.fromPort = fromPort;
        this.toPort = toPort;

        try {
            socket =new DatagramSocket(fromPort);
            reader = new BufferedReader(new InputStreamReader(System.in));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true) {
            try {
                String data = reader.readLine();
                DatagramPacket packet = new DatagramPacket(data.getBytes(), 0, data.getBytes().length, new InetSocketAddress(this.toIp, this.toPort));
                socket.send(packet);
                if (data.equals("bye")) {
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        socket.close();
    }
}

接受类工具

//接收线程
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 {
                //准备接收包裹,放到container里面
                byte[] container = new byte[1024];
                DatagramPacket packet = new DatagramPacket(container, 0, container.length);
                socket.receive(packet);//阻塞式接收包裹。上面是1024,下面是3,说明receive方法将他改变了
                //断开连接byte
                String receiveData = new String(packet.getData(), 0, packet.getLength());
                System.out.println(msgFrom+":"+receiveData);
                if (receiveData.trim().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 TalkTeacher {
    public static void main(String[] args) {
        //开启两个线程
        new Thread(new TalkSend(5555,"localhost",8888)).start();
        new Thread(new TalkReceive(9999,"学生")).start();
    }
}

1.8、URL

https://www.baidu.com/

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

DNS域名解析:将https://www.baidu.com/解析成xxx.x…x…x

本质是把域名解析成ip

基本上5部分组成:
协议://IP地址:端口/项目名/对应资源
public class URLDown {
    public static void main(String[] args) throws Exception {
        //1.下载地址
        URL url = new URL("https://m10.music.126.net/20200919161055/7963703b1af08b9d00a2e6ce2ba6c981/yyaac/obj/wonDkMOGw6XDiTHCmMOi/3918591949/c8a1/cba7/c6ea/5a3677569928db9f736580e5a2107f55.m4a");
        HttpsURLConnection httpURLConnection=(HttpsURLConnection)url.openConnection();

        InputStream inputStream = httpURLConnection.getInputStream();

        FileOutputStream fileOutputStream = new FileOutputStream("f.m4a");

        byte[] bytes = new byte[1024];
        int len;
        if ((len=inputStream.read(bytes))!=-1){
            fileOutputStream.write(bytes,0,len);//写出这个数据
        }

        fileOutputStream.close();
        inputStream.close();
        httpURLConnection.disconnect();//断开连接

    }
}

本文链接: http://www.dtmao.cc/news_show_200396.shtml

附件下载

上一篇:jstat 使用

下一篇:Spark Driver Program剖析

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?