网络编程

概述

首先理解TCP和UDP的区别

TCP:打电话:--连接--接了--通话--

UDP:发短信:--发送了就完事--接收--

计算机网络

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

网络编程的目的:

  • 无线电台--传播交流信息

  • 数据交换--通信

 

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

1、如何准确的定位网络上的一台主机,198.168.1.1。通过计算机的端口定位到这个计算机的某个资源。

2、找到这个主机,如何传输数据呢?

 

通过硬件用于传输数据

JavaWeb:网页编程 B/S,全称为Browser/Server结构,是指浏览器和服务器结构。

网络编程:TCP/IP C/S,全程为Client/Server结构,是指客户端和服务器结构。

 

如果实现网络通信?

通信双方地址:

  • IP

  • 端口号

规则:就是网络通信的协议

TCP/IP参考模型

 

小结:网络编程中的两个主要问题?

  • 如何准确定位到网络上的一台或多台主机?(用ping + 网址)

  • 找到主机后如何进行通信?

网络编程中的要素

  • IP和端口号 IP

  • 网络通信写协议 UDP,TCP

万物皆对象

 

IP地址

API文档的方法:InetAddress

  • 用来定义一台计算机的标识之一

  • 本机IP:127.0.0.1 ; localhost

 

IP地址的分类

IPV4/IPV6

IPV4:127.0.0.1,4个字节组成。0~255,大约42亿;30亿在北美,4亿在亚洲,于2011年用尽了。

IPV6:128位,8个无符号整数!据说可以把地球的每粒沙子都标有地址

fe80::b442:9d87:5428:8ee8%11

 

公网(互联网)-私网(局域网)

 ABCD类地址

192.168.x.x,专门用于组织内部使用

域名:记忆IP

例如:www.JD.com

//测试IP
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);

            //常用的方法
            //返回此对象InetAddress的原始地址
            System.out.println(inetAddress2.getAddress());
            //获取此IP地址的限定域名--获取规范的名字
            System.out.println(inetAddress2.getCanonicalHostName());
            //返回文本显示中的IP地址字符串
            System.out.println(inetAddress2.getHostAddress());
            //获取此IP地址的主机名。
            System.out.println(inetAddress2.getHostName());


            //UnknownHostException表示
            // 这个问题的出现是由于你的IP地址名称找不到对应的ip地址,
            // 就如同你在本地启动程序时默认为“localhost”。
        }catch (UnknownHostException e){
            e.printStackTrace();
        }
    }
}

 

端口

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

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

被规定0-65535

  • TCP,UDP:65535*2,意思是,tcp 80和udp 80端口号不冲突,在单个协议下,端口号可以冲突

端口分类

公有端口0-1023

  • HTTP:80

  • HTTPS:443

  • FTP:21

  • Telent:23

程序注册端口:1023-49151,分配用户或者程序

  • Tomcat:8080

  • MySQL:3306

  • Oracle:1521

动态、私有:49152-65535

netstat -ano #查看所有端口

netstat -ano|findstr "5900"#查看指定的端口

tasklist|findstr"8998" #查看端口的进程

 

通信协议

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

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

为了能够简化和统一

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

重点:

TCP:用户传输协议

UDP:用户数据报协议

出名的协议:

 

TCP 、UDP的对比

  • TCP:打电话

  • 连接、稳定

  • 三次握手、四次挥手(面试重点)

三次握手:https://www.cnblogs.com/bj-mr-li/p/11106390.html

四次挥手:https://blog.csdn.net/brook_/article/details/81090081

  • 客户端、服务端

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

UDP:发短信

  • 不连接、不稳定

  • 客户端、服务端:没有明确的界限

  • 只管发送,不确定对方是否收到

  • 例如DDOS:洪水攻击!

 

TCP实现聊天

理解Tcp上传文件中

客户端与服务端的交互流程

客户端:

  1. 创建一个socket连接

  2. 创建一个输出流

  3. 读取文件

  4. 写出文件

  5. 通知服务器,已经结束

  6. 确认服务器接收完毕,才能断开连接

  7. 关闭资源

public class TcpClinentDemo02 {
    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("life.png");


        //4、写出文件
        byte[] buffer = new byte[1024];
        int len;
        if ((len=fis.read(buffer))!=-1){
            os.write(buffer,0,len);
        }

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

        //确定服务器接收完毕,才能断开连接
        InputStream inputStream = socket.getInputStream();
        //String byte[]
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        byte[] buffer2 = new byte[1024];
        int len2;
        if ((len2=inputStream.read(buffer2))!=-1){
                baos.write(buffer2,0,len2);
        }
        System.out.println(baos.toString());

        //5、关闭资源
        os.close();
        fis.close();
        socket.close();
    }
}

服务端:

  1. 创建服务

  2. 监听客户端的连接

  3. 获取输入流

  4. 文件输出

  5. 关闭资源

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("out.png");
        byte[] buffer = new byte[1024];
        int len;
        if ((len=is.read(buffer))!=-1){
            fos.write(buffer,0,len);
        }

        //通知客户端我接收完毕了
        OutputStream os = socket.getOutputStream();
        os.write("已经接收完毕".getBytes());

        //5、关闭资源
        socket.close();
        is.close();
        fos.close();
        serverSocket.close();
    }
}

 

初识Tomcat

学会安装tomcat

安装官网:https://tomcat.apache.org/download-80.cgi

如何修改tomcat启动后的乱码

Tomcat闪退

 

Udp消息发送

理解Udp发送消息后

客户端和服务端的流程


Udp就好比发短信,不用连接,但是需要对方的地址

理解DatagramSocket和DatagramPacket的两者区别

DatagramSocket就好比一个海上运输的轮、DatagramPacket就好比码头

客户端:

结合源码的描述

public DatagramPacket(byte buf[], int offset, int length,
                      InetAddress address, int port) {
    setData(buf, offset, length);
    setAddress(address);
    setPort(port);
}
  1. 创建DatagramSocket的端口号;

  2. 创建DatagramPacket需要的数据、长度、地址、端口;

  3. 使用DatagramSocket发送socket.send();

  4. 关闭流socket.close();

  5. 异常处理throws Exception

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

        //建议一个连接通道Socket
        DatagramSocket socket = new DatagramSocket();

        //包的内容
        String msg = "apple";
        //地址
        InetAddress inetAddress = InetAddress.getByName("localhost");
        //端口:接收方的端口,发送方可写可不写
        int port = 9998;

        //建立包
        DatagramPacket datagramPacket = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,inetAddress,9998);

        //发送包
        socket.send(datagramPacket);

        //关闭流
        socket.close();
    }
}

服务端:

建立一个DatagramSocket的端口

创建DatagramPacket,接收所需要的数据、长度

使用DatagramSocket的阻塞接收receive用来接收Packet

关闭DatagramSocket

阻塞接收:

  receive()方法会使调用线程阻塞。

  Java使用DatagramSocket,DatagramSocket本身只是码头,不维护状态,不能产生IO流,它的唯一作用就是接收和发送数据报,Java使用DatagramPacket来代表数据报,DatagramSocket接收和发送的数据都是通过DatagramPacket对象完成的。

  在接收数据前,通常需要生成一个DatagramPacket对象,给出数据字节数组及其长度。然后调用DatagramSocket的receive()方法等待数据报的到来,该方法会一直阻塞调用该方法的线程,直到收到一个数据报为止。

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

        //开放端口
        DatagramSocket datagramSocket = new DatagramSocket(9998);

        //使用数组接收包的内容
        byte[] bytes = new byte[1024];

        //接收包
        DatagramPacket datagramPacket = new DatagramPacket(bytes,0,bytes.length);

        //阻塞接收:指的就是
        datagramSocket.receive(datagramPacket);
        System.out.println(datagramPacket.getAddress().getHostAddress());
        System.out.println(new String(datagramPacket.getData(),0,datagramPacket.getLength()));

        //关闭流
        datagramSocket.close();
    }
}

Udp实现聊天

理解Udp实现聊天的工作流程

继而探讨如何实现双向聊天的功能

实现聊天的两个关键点

  1. 使用while循环不断发送信息

  2. 使用BufferedReader可以输入信息

public class UdpSenderDemo01 {
    public static void main(String[] args) throws Exception {
        DatagramSocket datagramSocket = new DatagramSocket(1111);

        //准备数据
        //这是一个固定写法
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        while (true){
            String msg = reader.readLine();
            byte[] bytes = msg.getBytes();

            DatagramPacket datagramPacket = new DatagramPacket(bytes,0,bytes.length,new InetSocketAddress("localhost",2222));

            datagramSocket.send(datagramPacket);

            if (msg.equals("bye")){
                break;
            }
        }
        datagramSocket.close();

    }
}

服务端:

public class UdpReceiveDemo01 {
    public static void main(String[] args) throws Exception{
        DatagramSocket datagramSocket = new DatagramSocket(2222);

        while (true){
            //准备接收包裹
            byte[] bytes = new byte[1024];
            DatagramPacket datagramPacket = new DatagramPacket(bytes,0,bytes.length);
            //阻塞接收包裹
            datagramSocket.receive(datagramPacket);

            //断开连接,实现聊天关键字,例如发送端发bye就断开
            byte[] data = datagramPacket.getData();
            String recevieData = new String(data,0,data.length);
            System.out.println(recevieData);
            if (recevieData.equals("bye")){
                break;
            }

        }
        datagramSocket.close();

    }
}

 

Udp多线程在线咨询

理解使用多线程实现聊天的工作流程

发送端:

//原有基础上添加线程
public class TalkSend  implements Runnable{

    //提高DatagramSocket、BufferedReader的作用域
    DatagramSocket datagramSocket = null;
    BufferedReader bufferedReader = null;

    //发送端需要端口,地址,对方端口
    private int fromport;
    private String IP;
    private int toPort;

    public TalkSend(int fromport, String IP, int toPort) {
        this.fromport = fromport;
        this.IP = IP;
        this.toPort = toPort;

        try {
            datagramSocket = new DatagramSocket(fromport);
            bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            while (true){
                String msg = bufferedReader.readLine();
                byte[] bytes = msg.getBytes();
                DatagramPacket datagramPacket = new DatagramPacket(bytes,0,bytes.length,new InetSocketAddress(this.IP,this.toPort));
                datagramSocket.send(datagramPacket);
                if (msg.equals("bye")){
                    break;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        datagramSocket.close();
    }
}

接收端

public class TalkReceive implements Runnable{

    DatagramSocket datagramSocket = null;

    //接收端只需要端口、msgfrom作为备注提示是那方发送的信息
    private int fromport;
    private String msgfrom;

    public TalkReceive(int fromport, String msgfrom) {
        this.fromport = fromport;
        this.msgfrom = msgfrom;

        try {
            datagramSocket = new DatagramSocket(fromport);
        }catch (IOException e){
            e.printStackTrace();
        }

    }

    @Override
    public void run() {
        try {
            while (true){
                //准备接收包裹
                byte[] bytes = new byte[1024];
                DatagramPacket datagramPacket = new DatagramPacket(bytes,0,bytes.length);
                //阻塞接收包裹
                datagramSocket.receive(datagramPacket);

                //断开连接,实现聊天关键字,例如发送端发bye就断开
                byte[] data = datagramPacket.getData();
                String recevieData = new String(data,0,data.length);
                System.out.println(msgfrom+":"+recevieData);
                if (recevieData.equals("bye")){
                    break;
                }

            }
        }catch (IOException e){
            e.printStackTrace();
        }
        datagramSocket.close();
    }
}

老师

public class TalkTeacher {
    public static void main(String[] args) {
        new Thread(new TalkSend(3333,"localhost",4444)).start();
        new Thread(new TalkReceive(2222,"学生")).start();
    }
}

学生

public class TalkStudent {
    public static void main(String[] args) {
        new Thread(new TalkSend(1111,"localhost",2222)).start();
        new Thread(new TalkReceive(4444,"老师")).start();
    }
}

URL下载网络资源

理解如果通过url下载网络上的资源

Url例如:https://www.baidu.com/

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

DNS域名解析:www.baidu.com本质上还是解析为 xxx.xxx.x.x,域名只是为了方便记忆

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

public class UrlDown {
    public static void main(String[] args) throws Exception{
        //1、下载地址
        URL url = new URL("https://p1.music.126.net/ukMMQAeIixCM22VfN6IF_w==/109951166427062169.jpg");

        //2、连接到这个Ip
        // 此处的urlConnection对象实际上是根据URL的 请求协议(此处是http)生成的URLConnection类 
        // 的子类HttpURLConnection,故此处最好将其转化为HttpURLConnection类型的对象,以便用到 
        // HttpURLConnection更多的API.如下: 
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

        InputStream inputStream = urlConnection.getInputStream();

        FileOutputStream fos = new FileOutputStream("SY.jpg");

        byte[] bytes = new byte[999999999];
        int len;
        if ((len=inputStream.read(bytes))!=-1){
            fos.write(bytes,0,bytes.length);
        }

        inputStream.close();
        fos.close();
        urlConnection.disconnect();
    }
}
public class URLDemo01 {
    public static void main(String[] args) throws MalformedURLException {
        URL url = new URL("https://www.baidu.com/");
        //协议
        System.out.println(url.getProtocol());
        //主机IP
        System.out.println(url.getHost());
        //端口
        System.out.println(url.getPort());
        //文件
        System.out.println(url.getPath());
        //全路径
        System.out.println(url.getFile());
        //参数
        System.out.println(url.getQuery());
    }
}
posted @ 2022-08-22 23:53  里牧之  阅读(33)  评论(0)    收藏  举报