Java网络编程

write:2022-5-26
学习视频笔记,视频来源:B站——狂神

1. 概念

生活中我们通常会给自己外地或者外国的朋友打电话,发短信或者发邮件,以发送信封的方式为例,要想成功发送信件,必须知道如下信息:
在这里插入图片描述
通过信件可以使你和你的外地或者外国朋友进行联系,想一想,为什么不同地理位置的人能够通过打电话或者发短信等方式进行交流沟通?

(1)计算机网络:将地理位置不同的具有独立功能的多台计算机及其外部设备通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
(2)网络编程的目的:传播交流信息,数据交换,通信;
(3)想要达到目的需要什么:
——如何准确的定位网络上的一台主机,(查看位置:设置—网络和Internet—状态—查看硬件和连接属性)端口,以及定位到计算机上的某个资源;
——找到了这个主机,如何传输数据呢;

区分网页编程和网络编程:
网页编程:用JavaWeb;B/S架构
网络编程:TCP/IP ;C/S架构

2. 网络通信的要素

(1)通信双方的地址:IP,端口号;IP+端口号可以定位到某一台电脑的某个应用;
(2)通信规则:网络通信协议:http,ftp(文件上传协议),smtp,tcp,udp等等
TCP/IP参考模型:
在这里插入图片描述
在网路编程中重点学习:
在这里插入图片描述

现在动手试一试连接百度的IP地址吧:(命令行窗口输入ping+百度域名)
在这里插入图片描述
根据Java“万物皆对象”的思想,那么在java里面肯定有一个类表示IP/端口号,如果没有则自己创建;

3. IP

在java.net包下,有一个表示Internet协议(IP地址)的类:InetAddress 没有构造方法,所以不能new,有静态方法

3.1 IP地址作用

IP地址作用唯一定位一台网络上计算机(类似人的身份证)

3.2 本机IP

127.0.0.1:本机 localhost
ping 127.0.0.1:自己呼叫自己,无网也能够呼叫成功
在这里插入图片描述

3.3 IP地址的分类

两种分类方式:
1)第一种通过IP地址分类:IPv4/IPv6
IPv4:例如127.0.0.1以十进制点隔开(点分十进制记法),4个字节组成,长度0-255,大概42亿个因此能穷尽,2001年就用尽
IPv6:命令行窗口输入ipconfig可查看,例如:fe80::a518:5144:24d4:19c3%7,128位,8个无符号整数表示
2)第一种通过公网(互联网)-私网(局域网)分类
——分为ABCD类地址
在这里插入图片描述
局域网:一般192.168.XX.XX形式,专门给组织内部使用;

3.4 域名

3.5 测试类TestInetAddress

练一练:

//网络编程
//测试IP类:InetAddress
public class TestInetAddress {
    public static void main(String[] args) {
        try {
            //查询本机地址
            InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");
            System.out.println(inetAddress1);
            InetAddress inetAddress3 = InetAddress.getByName("localhost");
            System.out.println(inetAddress3);
            InetAddress inetAddress4 = InetAddress.getLocalHost();
            System.out.println(inetAddress4);

            //查询网站地址
            InetAddress inetAddress2 = InetAddress.getByName("www.baidu.com");
            System.out.println(inetAddress2);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}

运行结果:
在这里插入图片描述
我们再在其中添加一些常用方法:

            //常用方法
            System.out.println(inetAddress2.getAddress());//返回地址
            System.out.println(inetAddress2.getCanonicalHostName());//获得规范名字
            System.out.println(inetAddress2.getHostAddress());//获得IP
            System.out.println(inetAddress2.getHostName());//获得域名,或者自己电脑的名字

运行结果:运行时速度稍缓慢,因为是通过百度的域名去查找的
在这里插入图片描述

4. 端口

端口表示计算机上的一个程序的进程;(按ctrl+shift+esc键查看任务管理器),形象比喻理解:一栋大楼是IP,每一户一个端口;
(1)不同的进程有不同的端口号,用来区分软件, 端口重复会报端口被占用的错误,
(2)端口被规定0~65535
(3)会被分为TCP端口,UDP端口,每一个都有65535个,所以总65535 * 2;如果TCP用了80,UDP也可以用80,因为这两个协议不冲突,因此单个协议下,端口号不能冲突;
(4)端口分类:
公有端口:0~1023;常见:HTTP:80,HTTPS:443,FTP:21,TELENT:23
程序注册端口:1024~49151,分配给用户/程序,常见:Tomcat:8080,Mysql:3306,Oracle:1521
动态端口/私有端口:49152~65535(尽量不用这里面的端口);
(5)常见dos命令:
——netstat -ano 查看所有端口
——netstat -ano | findstr “xxx” 查看指定端口(findstr :过滤)
——tasklist | findstr “xxx” 查看指定端口的进程
(6)测试类TestInetSocketAddress

//套接字
public class TestInetSocketAddress {
    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());
        System.out.println(inetSocketAddress.getPort());
    }
}

运行结果:
在这里插入图片描述
(7)端口映射
端口映射问题,为什么你能发消息到我的电脑上?关键:找对端口

5. 通信协议

(1)协议:就是约定,就好比中国现在规格说的是普通话;
(2)网络通信协议:通信中的专业术语:速率,传输码率,代码传输结构,传输控制等等,不学计算机网络不用全部掌握;掌握通信核心要点:分层概念,
(3)TCP/IP协议簇:实际上是一组协议,
比较重要的两个协议:TCP/UDP,都位于传输层;
——TCP:用户传输协议
——UDP:用户数据报协议
比较出名的协议:
——TCP:用户传输协议
——IP:网络互连协议

TCP/IP模型理解:
在这里插入图片描述
(4)TCP UDP对比
TCP:想象成打电话
—连接,稳定
—三次握手,四次挥手
—客户端,服务端
—传输完成,释放连接,效率低
UDP:想象成发短信
—不连接,不稳定
—客户端,服务端:没有明确的界限(可以是服务端发给服务端)
—不管有没有准备好,都可以发给你
(5)三次握手,四次挥手
三次握手
形象说明:A想与B交流
A:你瞅啥?
B:瞅你咋地?
A:干一场!
A向B请求连接,B有了回应,A再次回应:最少需要三次,保证连接稳定!
在这里插入图片描述
四次挥手
形象说明:A想与B分开
A:我要断开了
B:我知道你要断开了
B:你真的断开了吗?
A:我真的要断开了
在这里插入图片描述

5.1 TCP

5.1.1 TCP聊天

需要通信双方,所以需要写两个类:
—客户端:
1.连接服务器Socket
2.发送消息
—服务器:
1.建立服务端口SeverSocket
2.等待用户的连接accept
3.接收用户的消息

写一个例子:
服务器端:

//服务端
public class TcpServerDemo1 {
    public static void main(String[] args){
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream is = null;
        ByteArrayOutputStream  baos = null;
        try {
            //1.我得有一个地址
            serverSocket = new ServerSocket(9999);
            //2.等待客户端连接过来
            socket = serverSocket.accept();
            //3.读取客户端的消息
            is =  socket.getInputStream();
            //管道流
            baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while((len = is.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 ((baos!=null)){
                try {
                    is.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 TcpClientDemo1 {
    public static void main(String[] args) {
        Socket socket = null;
        OutputStream os = null;
        try {
            //1.要知道服务器端的地址,端口号
            InetAddress serverIP = InetAddress.getByName("127.0.0.1");
            int port = 9999;
            //2.创建一个socket连接
            socket = new Socket(serverIP,port);
            //3.发送消息  IO流
            os = socket.getOutputStream();
            os.write("你好".getBytes());
        } 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();
                }
            }

        }
    }

}

运行结果:
在这里插入图片描述

5.1.2 TCP文件上传

思想:读取文件变成流再传出去;

写一个例子:在项目根目录下放一个图片
服务器端:

public class TcpServerDemo2 {
    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(new File("receive.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.关闭资源
        fos.close();
        is.close();
        socket.close();
        serverSocket.close();
    }
}


客户端:

public class TcpClientDemo2 {
    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(new File("paopao.jpg"));
        //4.写出文件
        byte[] buffer = new byte[1024];
        int len;
        while((len = fis.read(buffer))!=-1){
            os.write(buffer,0,len);
        }
        //通知服务器,我已经结束了
        socket.shutdownOutput();//我已经传输完了

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

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

运行结果:根目录下生成了receive.jpg
在这里插入图片描述
在这里插入图片描述

5.2 UDP

发短信:不用连接,但需要知道对方的地址!
设计两个类:
1)DatagramPacket类:构造方法:public DatagramPacket(byte[] buf, int offset, int length)
2)DatagramSocket类:构造方法:public DatagramSocket() throws SocketException

5.2.1 UDP消息发送

写一个例子:
客户端:

//不需要连接服务器
public class UdpClinetDemo1 {
    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);
        //2.接收数据(包)
        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();
    }
}

运行结果:
在这里插入图片描述
UdpServerDemo1不算服务器端,因为只要客户端写了端口号就也算服务器端,客户端和服务端没有明确的界限,写一个聊天接收与发送的例子,就是你与其他人一个发送一个接收,具体如下

5.2.2 UDP聊天实现

先是一个发送方,一个接收方
发送者:

public class UdpSenderDemo1 {
    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket(8888);

        //控制数据:控制台读取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("localhost",6666));
            socket.send(packet);

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

接受者:

public class UdpReceiveDemo1 {
    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, new InetSocketAddress("localhost", 6666));
            socket.receive(packet);//阻塞式接收包裹;
            //读数据
            byte[] data = packet.getData();
            String receiverData = new String(data, 0, data.length);

            System.out.println(receiverData);
            //断开连接
            if (receiverData.equals("bye")){
                break;
            }
        }
        socket.close();
    }
}

运行结果:
在这里插入图片描述
在这里插入图片描述

5.2.2 UDP多线程在线咨询

再是两个人都可以是发送方和接收方,写一个学生与老师通信的例子:

package com.example.lrl.UDP3;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

public class TalkSend implements Runnable {

    DatagramSocket socket = null;
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

    private String toIp,fromIP;
    private int toPort,fromPort;

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

        try{
            DatagramSocket socket = new DatagramSocket(fromPort);
        } catch (Exception e){
            e.printStackTrace();
        }

    }

    @Override
    public void run() {

        //循环发送
        while (true){
            try {
                String data = reader.readLine();
                byte[] datas = data.getBytes();
                DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress(this.toIp,this.toPort));
                socket.send(packet);

                if (data.equals("bye")){
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        socket.close();
    }
}

package com.example.lrl.UDP3;

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

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 {
                //准备接收包裹
                byte[] container = new byte[1024];
                DatagramPacket packet = new DatagramPacket(container, 0, container.length, new InetSocketAddress("localhost", 6666));
                socket.receive(packet);//阻塞式接收包裹;
                //读数据
                byte[] data = packet.getData();
                String receiverData = new String(data, 0, data.length);

                System.out.println(msgFrom+":"+receiverData);
                //断开连接
                if (receiverData.equals("bye")){
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        socket.close();
    }
}

package com.example.lrl.UDP3;

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

package com.example.lrl.UDP3;

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

同时运行TalkStudent.java和TalkTeacher.java,老师与学生就可以进行通信!

6. Tomcat

  1. Tomcat简介

  2. 先来看看B/S和C/S,
    服务器端:
    ——自定义 S
    ——Tomcat服务器(别人用java语言写好的服务器,java后台开发推荐使用!) S
    客户端:
    ——自定义 C
    ——浏览器 B

7. URL

本机文件定位地址也是URL,https://www.baidu.com/也是URL(统一资源定位符);

URL(统一资源定位符):定位互联网上的某一个资源;
组成:一般的格式:协议:// ip地址:端口 / 项目名 / 资源
——1. 协议:// https或者https等
——2. 域名:www.baidu.com DNS域名解析:把www.baidu.com解析成xxx.xx…xxx(IP地址);
——3. 端口

写一个例子,认识URL:
在这里插入图片描述
如果需要下载资源文件:
在Tomcat目录下添加文件:
在这里插入图片描述
访问:
在这里插入图片描述
访问成功,不过存在乱码问题;
现在我们把这个 http://localhost:8080/lrl/SecutiyFile.txt 目录下的资源下载,
代码:

//资源下载
public class UrlDown {
    public static void main(String[] args) throws Exception {
        //1.下载地址
        URL url = new URL("http://localhost:8080/lrl/SecutiyFile.txt");
        //2.连接到这个资源
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

        InputStream inputStream = urlConnection.getInputStream();
        FileOutputStream fos = new FileOutputStream("SecutiyFile.txt");

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

        fos.close();
        inputStream.close();
        urlConnection.disconnect();//断开连接

    }

}

点击运行按钮,可以明显的看到下载完成的SecutiyFile.txt:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值