Java学习笔记(九)网络编程

发布时间 2023-03-24 23:11:32作者: 雪化凛然

网络编程

概述

ppwFqR1.md.png

计算机网络:

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

网络编程的目的:

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

想要达到这个效果需要什么:

  1. 如何准确的定位网络上的一台主机: 192.168.xx.xx:端口,定位到这台计算机上的某个资源
  2. 找到了这个主机,如何传输数据:

javaweb:B/S

网络编程:C/S

网络通信的要素

如何实现网络的通信?

  • ip
  • 端口号
  • 192.168.16.124:5900

规则

ppwnZ1H.md.png

小结:

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

IP

ip地址:InetAdress

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

  • 127.0.0.1 : 本机Ip localhost

  • ip地址的分类

    • ip地址的分类
      • IPV4 127.0.0.1 四个字节组成 0-255,42亿,30亿在北美,已用尽
      • IPV6 128位,8个无符号整数
    • 公网(互联网) - 私网(局域网)
      • ABCD类地址
      • 192.168.xx.xx,专门给组织内部使用的
  • 域名

    • IP:www.vip.com
    package com.tyrant.lesson01;
    
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    public class InetAddressDemo01 {
        public static void main(String[] args) {
            try {
                //查询网站地址
                InetAddress inetAddress01 = InetAddress.getByName("www.baidu.com");
                System.out.println(inetAddress01);
    
                //查询本机IP
                InetAddress inetAddress02 = InetAddress.getLocalHost();
                System.out.println(inetAddress02);
    
                //常用方法
                System.out.println(inetAddress01.getAddress());//返回地址的字节数组
                System.out.println(inetAddress01.getHostAddress());//返回ip
                System.out.println(inetAddress01.getCanonicalHostName());//规范的名字    IP
                System.out.println(inetAddress01.getHostName());//返回域名
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
        }
    }
    

端口

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

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

  • 被规定0~65535

  • TCP和UDP都有65536个端口,TCP能和UDP端口号能相同,但同一协议下不能使用同一端口

  • 端口分类:

    • 共有端口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" # 
    
    package com.tyrant.lesson01;
    
    import java.net.InetSocketAddress;
    
    public class inetSocketAddressDemo01 {
        public static void main(String[] args) {
            InetSocketAddress localhost = new InetSocketAddress("localhost", 8080);
            System.out.println(localhost);
            System.out.println(localhost.getAddress());
            System.out.println(localhost.getHostName());
            System.out.println(localhost.getPort());//端口
        }
    }
    

    pp0giJP.md.png

通信协议

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

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

问题:非常复杂

大事化小:分层的概念

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

重要:

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

出名的协议:

  • TCP
  • IP:网络互连协议

TCP UDP对比

TCP:打电话

  • 连接,稳定

  • 三次握手,四次挥手

    连接

    • A:你瞅啥?
    • B:瞅你咋地?
    • 干一场!

    断开

    • A:我要走了
    • B:你真的要走了吗
    • B:你真的真的要走了吗
    • A:我真的要走了
  • 客户端、服务端

  • 传输完成就释放连接,效率低

UDP:发短信

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

TCP

客户端

  1. 连接服务器 Socket
  2. 发送消息
package com.tyrant.lesson02;

import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

//客户端
public class TCPClientDemo01 {

    public static void main(String[] args) {

        Socket socket = null;
        OutputStream os = null;

        try {
            //1. 要知道服务器的地址,端口号
            InetAddress ServerIP = InetAddress.getByName("localhost");
            int port = 9999;
            //2. 创建一个socket连接
            socket = new Socket(ServerIP, port);
            //3. 发送消息 IO流
            os = socket.getOutputStream();
            os.write("hello world".getBytes("UTF-8"));

        } 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. 接收用户的消息
package com.tyrant.lesson02;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

//服务端
public class TCPServerDemo01 {

    public static void main(String[] args) {

        ServerSocket serverSocket = null;
        Socket accept = null;
        InputStream is = null;
        ByteArrayOutputStream bos = null;

        try {
            //1. 我要有一个地址
            serverSocket = new ServerSocket(9999);
            //2. 等待客户端连过来
            accept = serverSocket.accept();
            //3.读取消息

            //字节缓冲流
            is = accept.getInputStream();

/*
            byte[] bytes = new byte[1024];
            int len;
            while ((len = is.read(bytes)) != -1){
                String s = new String(bytes, 0, len);
                System.out.println(s);
            }
*/

            //管道的概念,使用另一种流去接收
            bos = new ByteArrayOutputStream();
            byte[] bytes = new byte[1024];
            int len;
            while ((len = is.read(bytes)) != -1){
                bos.write(bytes,0,len);
                bos.flush();
            }
            System.out.println(bos.toString());

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bos != null){
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (is != null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (accept != null){
                try {
                    accept.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (serverSocket != null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

文件上传

客户端

age com.tyrant.lesson02;

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("localhost"), 8080);
        //2. 创建一个输出流
        OutputStream os = socket.getOutputStream();

        //3. 读文件
        FileInputStream fis = new FileInputStream(new File("src\\com\\tyrant\\lesson02\\keqing001.jpg"));
        byte[] bytes = new byte[1024];
        int len ;
        //4. 写文件
        while ((len = fis.read(bytes)) != -1){
            os.write(bytes,0,len);
        }

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

        //确定服务器接收完毕,才能断开连接
        InputStream msg = socket.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len2 ;
        while ((len2 = msg.read(buffer)) != -1){
            baos.write(buffer,0,len2);
        }
        System.out.println(baos.toString());


        //释放资源
        baos.close();
        msg.close();
        fis.close();
        os.close();
        socket.close();
    }
}

服务器

package com.tyrant.lesson02;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class TCPServerDemo02 {

    public static void main(String[] args) throws Exception {
        //1. 创建服务
        ServerSocket serverSocket = new ServerSocket(8080);

        //2. 监听客户端的连接
        Socket accept = serverSocket.accept();//阻断式监听,会一直等待客户端连接

        //3. 获取输入流
        InputStream is = accept.getInputStream();

        //4. 读文件
        FileOutputStream fos = new FileOutputStream(new File("src\\com\\tyrant\\lesson02\\keqing002.jpg"));
        byte[] bytes = new byte[1024];
        int len;
        while((len = is.read(bytes)) != -1){
            fos.write(bytes,0,len);
        }

        //通知客户端我已接受
        OutputStream msg = accept.getOutputStream();
        msg.write("我已接受".getBytes(StandardCharsets.UTF_8));

        //释放资源
        msg.close();
        fos.close();
        is.close();
        accept.close();
        serverSocket.close();
    }
}

Tomcat

服务端

  • 自定义 S
  • Tomcat服务器 S

客户端

  • 自定义 C
  • 浏览器 B

UDP

发送消息

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

发送方

package com.tyrant.lesson03;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;

//不需要连接服务器
public class UDPClientDemo01{
    public static void main(String[] args) throws Exception  {

        //1. 建立一个Scoket
        DatagramSocket scoket = new DatagramSocket();

        //2. 建立一个包
        String msg = "Hello World";

        //发送给谁
        InetAddress localhost = InetAddress.getByName("localhost");
        int port = 8080;

        //数据
        DatagramPacket datagramPacket = new DatagramPacket(msg.getBytes(StandardCharsets.UTF_8),0,msg.getBytes(StandardCharsets.UTF_8).length,localhost,port);

        //3. 发送一个包
        scoket.send(datagramPacket);

        //释放资源
        scoket.close();
    }
}

接收方

package com.tyrant.lesson03;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UDPServerDemo01 {

    //等待客户端的链接
    public static void main(String[] args) throws Exception {
        //开放端口
        DatagramSocket socket = new DatagramSocket(8080);

        //接收数据包
        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();
    }
}

咨询

循环发送

发送方

package com.tyrant.lesson03;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;

public class UDPSenderDemo01 {

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

        //建立一个Socket连接
        DatagramSocket socket = new DatagramSocket(8888);

        //准备数据
        //从控制台接收
        BufferedReader br  = new BufferedReader(new InputStreamReader(System.in));

        while (true){

            String s = br.readLine();
            byte[] data = s.getBytes(StandardCharsets.UTF_8);
            DatagramPacket packet = new DatagramPacket(data,0,data.length,new InetSocketAddress("localhost",6666));

            //发送数据
            socket.send(packet);

            if (s.equals("bye")){
                break;
            }
        }
        //关闭资源
        br.close();
        socket.close();
    }
}

接收方

package com.tyrant.lesson03;

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[] msg = new byte[1024];
            DatagramPacket packet = new DatagramPacket(msg,0,msg.length);
            socket.receive(packet);
            byte[] data = packet.getData();
            String receiveMsg = new String(data, 0, packet.getLength());
            System.out.println(receiveMsg);
            if (receiveMsg.equals("bye")){
                break;
            }

            //发送数据包
            //socket.send(packet);
        }


        //释放资源
        socket.close();
    }
}

对话

发送类

package com.tyrant.chat;

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.nio.charset.StandardCharsets;

public class TalkSend implements Runnable{
    DatagramSocket socket = null;
    BufferedReader br = null;

    //private String fromIP;
    private int fromPort;
    private String toIP;
    private int toPort;

    public TalkSend( int fromPort, String toIP, int toPort) {
        //this.fromIP = fromIP;
        this.fromPort = fromPort;
        this.toIP = toIP;
        this.toPort = toPort;
        try{
            socket = new DatagramSocket(this.fromPort);
            br  = new BufferedReader(new InputStreamReader(System.in));
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void run() {

        //准备数据
        //从控制台接收
        try {

            while (true){

                String s = br.readLine();
                byte[] data = s.getBytes(StandardCharsets.UTF_8);
                DatagramPacket packet = new DatagramPacket(data,0,data.length,new InetSocketAddress(this.toIP,this.toPort));

                //发送数据
                socket.send(packet);

                if (s.equals("bye")){
                    break;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (br != null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null){
                socket.close();
            }
        }
    }
}

接收类

package com.tyrant.chat;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

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(this.port);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        //开放端口

        try {
            while (true){

                //接收数据包
                byte[] msg = new byte[1024];
                DatagramPacket packet = new DatagramPacket(msg,0,msg.length);

                //阻塞式接收
                socket.receive(packet);

                byte[] data = packet.getData();
                String receiveMsg = new String(data, 0, packet.getLength());
                System.out.println(msgFrom + ":" + receiveMsg);

                //断开连接
                if (receiveMsg.equals("bye")){
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //释放资源
            socket.close();
        }
    }
}

测试类

package com.tyrant.chat;

public class Student {
    public static void main(String[] args) {
        //开启两个线程
        new Thread(new TalkSend(8888,"localhost",9999)).start();
        new Thread(new TalkReceive(7777,"老师")).start();
    }
}
package com.tyrant.chat;

public class Teacher {
    public static void main(String[] args) {
        //开启两个线程
        new Thread(new TalkSend(6666,"localhost",7777)).start();
        new Thread(new TalkReceive(9999,"学生")).start();
    }
}

URL

https://www.baidu.com/

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

DNS 域名解析

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

package com.tyrant.lesson04;

import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;

public class URLDemo01 {
    public static void main(String[] args) throws IOException {

        //下载地址
        URL url = new URL("https://i0.hdslb.com/bfs/activity-plat/static/20211216/df3e2ff90b315fca2f8d24a29cb68a47/tFsbCWMDtV.gif");
        System.out.println("协议:" + url.getProtocol());//协议
        System.out.println("主机IP:" + url.getHost());//主机IP
        System.out.println("端口:" + url.getPort());//端口
        System.out.println("文件:" + url.getPath());//文件
        System.out.println("全路径:" + url.getFile());//全路径
        System.out.println("参数:" + url.getQuery());//参数

        //保存到本地
        HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
        InputStream is = urlConnection.getInputStream();
        FileOutputStream fos = new FileOutputStream(new File("xx.gif"));
        byte[] bytes = new byte[1024];
        int len ;
        while ((len = is.read(bytes)) != -1){
            fos.write(bytes,0,len);
        }

        //释放资源
        fos.close();
        is.close();
        urlConnection.disconnect();
    }
}