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

网络编程

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();//断开连接

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值