网络编程


狂神说学习笔记

概述

网络通信的要素

通信双方的地址:ip+端口号

规则:网络通信的协议

TCP/IP参考模型

image-20210513113515843

小结:

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

IP

IP地址:InetAddress

  • 唯一定位一台网络计算机

  • ip地址的分类

    • ipv4/ipv6

      • IPV4 127.0.0.1,四个字节组成,0-255 ,42亿,30亿都在北美,亚洲4亿,2011年用尽。
      • IPV6 128位,8个无符号整数!例如2141:0bb1:acde:6454:12aa:887c:67ac:dddd
    • 公网(互联网)-私网(局域网)

      • ABCD类地址
      • 192.168.XXX.XXX,专门给组织内部使用的
  • 域名:记忆IP问题

public class TestInetAddress {
    public static void main(String[] args) throws UnknownHostException {

        //查询本机地址
        InetAddress address1=InetAddress.getByName("127.0.0.1");
        System.out.println(address1);
        InetAddress address2=InetAddress.getByName("localhost");
        System.out.println(address2);
        InetAddress address3 = InetAddress.getLocalHost();
        System.out.println(address3);

        //查询网站IP地址
        InetAddress address4= InetAddress.getByName("www.baidu.com");
        System.out.println(address4);

        //常用方法
        System.out.println(address3.getCanonicalHostName());//规范的名字
        System.out.println(address3.getHostAddress());//ip
        System.out.println(address3.getHostName());//域名,自己电脑的名字
    }
}

端口

​ 计算机上一个程序的进程

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

  • 被规定0-65535

  • TCP UDP:65535*2 tcp:80则udp也可以是80,单个协议下,端口号不能冲突

  • 端口分类

    • 公有端口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 "1221" #查看指定端口的进程
      Ctrl+Shift+Esc  #打开任务管理器
      
      public class TestInetSocketAddress {
          public static void main(String[] args) {
              InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 8080);
              InetSocketAddress inetSocketAddress1 = new InetSocketAddress("localhost", 8080);
              System.out.println(inetSocketAddress);
              System.out.println(inetSocketAddress1);
      
              System.out.println(inetSocketAddress.getAddress());
              System.out.println(inetSocketAddress.getHostName());
              System.out.println(inetSocketAddress.getPort());
          }
      }
      

通信协议

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

非常的复杂,网络分层策略

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

重要:

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

出名的协议:

  • TCP
  • IP:网络互联协议

TCP与UDP对比

TCP打电话

  • 连接,稳定

  • 客户端、服务端

  • 三次握手四次挥手

    最少需要三次保证稳定连接!
    A:你瞅啥?
    B:瞅你咋地?
    A:干一场!
    
    A:我要走了!
    B:你真的要走了么?
    B:你真的真的要走了么?
    A:我真的真的要走了!
    
  • 传输完成,释放连接,效率低

UDP发短信

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

TCP

客户端

  1. 连接服务器Socket

  2. 发送消息


public class TcpClientDemo01 {
    public static void main(String[] args) {

        InetAddress inetAddress=null;
        Socket socket =null;
        OutputStream outputStream=null;
        try {
            //1.要知道服务器的地址
            inetAddress = InetAddress.getByName("127.0.0.1");
            //2.创建一个socket连接
            socket = new Socket(inetAddress, 7777);
            //3.发送消息IO流
            outputStream = socket.getOutputStream();
            outputStream.write("hello".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 byteArrayOutputStream=null;
        try {
            //1.我得有一个地址
            serverSocket = new ServerSocket(7777);
            while (true){
                //2.等待客户端连接进来
                socket = serverSocket.accept();
                //3.读取客户端消息
                inputStream = socket.getInputStream();
                //管道流
                byteArrayOutputStream = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len;
                while ((len=inputStream.read(buffer))!=-1){
                    byteArrayOutputStream.write(buffer,0,len);
                }
                System.out.println(byteArrayOutputStream.toString());
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(byteArrayOutputStream!=null){
                try {
                    byteArrayOutputStream.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) throws IOException {

        //1 创建一个socket连接
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9999);
        //2 创建一个输出流
        OutputStream os = socket.getOutputStream();
        //3 读取文件
        FileInputStream fis = new FileInputStream(new File("a.jpg"));
        //4 写出文件
        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());

        //5 关闭资源
        baos.close();
        is.close();

        fis.close();
        os.close();
        socket.close();
    }
}
//文件传输服务端
public class TcpServerDemo02 {
    public static void main(String[] args) throws IOException {
        //1 创建服务
        ServerSocket serverSocket = new ServerSocket(9999);
        //2 监听客户端的连接
        Socket socket = serverSocket.accept();//阻塞式的监听,会一直等到客户端输入
        //3 获取输入流
        InputStream is = socket.getInputStream();
        //4 文件输出
        FileOutputStream fos = new FileOutputStream(new File("b.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());

        //5 关闭资源
        os.close();

        fos.close();
        is.close();
        socket.close();
        serverSocket.close();
    }
}

UDP

发送消息

发送端

public class UdpClientDemo01 {
    public static void main(String[] args) throws Exception {
        //1 建立一个Socket
        DatagramSocket socket = new DatagramSocket();
        //2 建立包
        byte[] msg="hello".getBytes();
        //数据信息,数据的起始位置,要发送给谁
        DatagramPacket packet = new DatagramPacket(msg,0,msg.length,InetAddress.getByName("127.0.0.1"),8888);
        //3 发送包
        socket.send(packet);
        //4 关闭流
        socket.close();
    }
}

接收端

public class UdpServerDemo01 {
    public static void main(String[] args) throws Exception {
        //1 开放端口
        DatagramSocket socket = new DatagramSocket(8888);
        //2 接收数据包
        byte[] buffer = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
        socket.receive(packet);//阻塞接收
        System.out.println(new String(packet.getData()));
        //3 关闭连接
        socket.close();
    }
}

咨询

循环发送消息

public class UdpSenderDemo01 {
    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket(7777);
        //准备数据 控制台读取 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("127.0.0.1", 6666));

            socket.send(packet);
            if("bye".equals(data))
                break;
        }
        socket.close();
    }
}

循环接收消息

public class UdpReceiverDemo01 {
    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); //阻塞式接收
            String data=new String(packet.getData());
            System.out.println(data);
            if("bye".equals(data))
                break;
        }
        socket.close();
    }
}

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

多线程的方式实现

//聊天发送消息的的线程

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.toIp=toIp;
        this.toPort=toPort;
        try {
            socket = new DatagramSocket(fromPort);
        } catch (SocketException e) {
            e.printStackTrace();
        }
        reader = new BufferedReader(new InputStreamReader(System.in));
    }

    @Override
    public void run() {
        try {
            while (true){
                String data = reader.readLine();
                byte[] datas = data.getBytes();
                DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress(toIp, toPort));

                socket.send(packet);
                if("bye".equals(data))
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        socket.close();
    }
}
//聊天接收消息的的线程
public class TalkReceive implements Runnable {
    DatagramSocket socket =null;

    private int fromPort;
    private String name;

    public TalkReceive(int fromPort ,String name) {
        this.name=name;
        try {
            socket = new DatagramSocket(fromPort);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void run() {
        try {
            while (true){
                //准备接收包裹
                byte[] container = new byte[1024];
                DatagramPacket packet = new DatagramPacket(container, 0, container.length);
                socket.receive(packet); //阻塞式接收
                String data=new String(packet.getData());
                System.out.println(name+data);
                if("bye".equals(data))
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        socket.close();
    }
}
//老师端开启发送及接收多线程
public class TalkTeacher {
    public static void main(String[] args) {
        new Thread(new TalkSend(6666,"127.0.0.1",5555)).start();
        new Thread(new TalkReceive(8888,"学生说:")).start();
    }
}
//学生端开启发送及接收多线程
public class TalkStudent {
    public static void main(String[] args) {
        new Thread(new TalkSend(7777,"127.0.0.1",8888)).start();
        new Thread(new TalkReceive(5555,"老师说:")).start();
    }
}

URL

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

https://www.baidu.com/

DNS域名解析:www.baidu.com xxx.xxx.xxx.xxx

协议://IP地址:端口/项目名称/资源
//获取URL的消息
public class UrlDemo01 {
    public static void main(String[] args) throws MalformedURLException {
        URL url = new URL("http://localhost:8080/test/index.jsp?a=1&b=2");

        System.out.println(url.getProtocol());//协议
        System.out.println(url.getHost());//主机IP
        System.out.println(url.getPort());//多看
        System.out.println(url.getPath());//文件
        System.out.println(url.getFile());//全路径
        System.out.println(url.getQuery());//参数

    }
}
//URL资源下载
public class UrlDown {
    public static void main(String[] args) throws IOException {
        //1 下载地址
        URL url = new URL("https://m801.music.126.net/20210514153629/5666a8e91c37c46f024a9e60514f0ea7/jdyyaac/obj/w5rDlsOJwrLDjj7CmsOj/7937683494/31e2/2771/3eef/e1a6f0f79db893a61118d620b204384f.m4a");
        //2 连接到这个资源
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        InputStream inputStream = connection.getInputStream();
        FileOutputStream fileOutputStream = new FileOutputStream("4384f.m4a");
        byte[] buffer = new byte[1024];
        int len;
        while ((len=inputStream.read(buffer))!=-1){
            fileOutputStream.write(buffer,0,len);
        }

        fileOutputStream.close();
        inputStream.close();
        connection.disconnect();
    }
}
posted @ 2021-05-14 15:18  地球小星星  阅读(157)  评论(0)    收藏  举报