Java网络编程

目录

一、定义

二、三要素

1.IP

(1)IPv4

(2)IPv6

(3)细节

(4)常用cmd命令

(5)InetAddress 类

2.端口号

3.协议

(1)UDP协议

Ⅰ. 发送数据

Ⅱ. 接收数据

Ⅲ. 通信方式

① 单播:一对一

② 组播:一对多(一次一组) 

③ 广播:一对 all 

(2)TCP协议

Ⅰ. 过程

Ⅱ. 三次握手

Ⅲ. 四次挥手 


一、定义

网络编程:在网络通信协议下,不同计算机上运行的程序,进行的数据传输

                (计算机跟计算机之间通过网络进行数据传输)

常见的软件架构:CS 和 BS

 BS架构的优缺点:

① 不需要开发客户端,只需要 页面 + 服务端

② 用户不需要下载,打开浏览器就可以直接使用

③ 如果应用过大,用户体验受到影响(图片等资源依靠网络传输,往往分辨率不会太高)

CS架构的优缺点:

① 需要开发客户端,也需要开发服务端

② 用户需要下载和更新的时候太麻烦

③ 画面可以做的非常精美,用户体验好(图片等资源都是存储在本地文件中的,不依靠网络)

二、三要素

注意:这里的设备并不只包含计算机,手机、平板、手表都具有上网的功能。

1.IP

全称:Internet protocol,是互联网协议地址,也称 IP 地址,是分配给上网设备的数字标签。

作用:上网设备在网络中的地址,是唯一的标识。

(1)IPv4

全称:Internet protocol version 4,互联网通信协议第四版

采用 32 位地址长度,分成 4 组,使用点分十进制表示法。

注意:IPv4 是目前的主流方案,但最多只有 2^32 个 ip, 目前已经用完。

(2)IPv6

全称:Internet protocol version 6,互联网通信协议第六版。

采用 128 位地址长度,分成 8 组,使用冒分十六进制表示法。

注意:IPv6 是为了解决 IPv4 不够用而出现的,最多有 2^128 个 ip, 可以让地球上的每一粒沙子都有对应的 ip。

(3)细节

Question1:目前主流的是IPv4,但 Ipv4 分配的 ip 已经不够用了,是怎么解决这个问题的呢?

IPv4 的地址分类形式:公网网址(万维网使用)和 私有地址(局域网使用)

私有地址:专门为组织机构内部使用,以此节省 ip。

主要的私有IP地址范围有:

  • 10.0.0.0 - 10.255.255.255
  • 172.16.0.0 - 172.31.255.255
  • 192.168.0.0 - 192.168.255.255

比如:网吧中的所有电脑,都共享同一个 公网 IP,再由路由器给每一台电脑分配局域网 IP,从而达到节省 ip 的目的。


特殊 IP 地址:127.0.0.1,也就是 localhost:回送地址,也称本地回环地址,本地 IP,永远只会寻早当前所在本机。

Question2:假设我现在电脑的 IP地址是198.162.1.100,那么这个 IP 和127.0.0.1是一样的吗?

答案是不一样的。 

电脑的 ip 地址是192.168.1.100,如果现在也往 192.168.1.100 发送数据。

电脑先发送数据到路由器, 路由器再找到电脑当前的 ip,这样才能实现数据的发送

但上面说过,电脑的局域网 ip 地址是靠路由器分配的。

在不同的地方,不同的路由器所分配的 ip 地址也有可能是不同的。

所以,如果换了一个地方上网,或者下次启动电脑,那么局域网的 ip 就有可能不是 198.162.1.100,而是其他 ip。

 但如果电脑往 127.0.0.1 发送数据,此时是不经过路由器的。

数据在经过网卡时,网卡发现是往 127.0.0.1 发送,此时这个数据就会直接发给自己。

不论在哪个地方上网,永远都是这样,因为 127.0.0.1永远表示本机。

建议:自己练习的时候,就写 127.0.0.1,不要写 ip 地址

(4)常用cmd命令

ipconfig:查看本机地址

ping:检查网络是否联通

(5)InetAddress 类

该类就表示电脑 ip 地址的对象, 但 ip 地址分为 IPv4 和 IPv6 两种。

在获取 InetAddress 的时,底层会判断当前系统使用的是 IPv4 还是 IPv6,然后返回其子类 Inet4Address 或 Inet6Address 的对象。

public class Demo {
    public static void main(String[] args) throws UnknownHostException {
        //1.获取InetAddress对象(IP对象,也就是电脑的对象)
        InetAddress address = InetAddress.getByName("DESKTOP-278NGMM");
        System.out.println(address);

        //2.获取主机名
        String name = address.getHostName();
        System.out.println(name);

        //3.获取ip地址
        String ip = address.getHostAddress();
        System.out.println(ip);
    }
}

 运行结果:

2.端口号

端口号:应用程序在设备中唯一的标识。

由两个字节的整数表示,取值范围:0 ~ 65535。

其中 0 ~ 1023 之间的端口号用于一些知名的网络服务或者应用,我们自己只能使用1024以上的。

注意:一个端口号只能被一个应用程序使用。

3.协议

协议:在计算机网络中,连接和通信的规则被称为网络通信协议

OSI参考模型:世界互联协议标准,全球通信规范,但模型过于理想化,未能在Internet上进行推广

TCP/IP参考模型(或TCP/IP协议):事实上的国际标准。

(1)UDP协议

 用户数据报协议(User Datagram Protocol):面向无连接的通信协议。

作用:速度快,有大小限制,一次最多发送 64k,数据不安全,易丢失数据(不可靠)

面向无连接:不管通信双方网络是否畅通,都直接发送,收不到就算了。

应用场景:在线视频,语音通话,网络会议

Ⅰ. 发送数据

public class SendMessage {
    public static void main(String[] args) throws IOException {
        //1.创建DatagramSocket对象(快递公司)
        DatagramSocket ds = new DatagramSocket();

        //2.打包数据
        String str = "你好!";
        //转换成字节数组
        byte[] bytes = str.getBytes();
        //获取目的地的ip地址对象
        InetAddress address = InetAddress.getByName("127.0.0.1");
        //端口号
        int port = 10086;

        //参数:发送的数据,数据的长度,目的地的ip地址对象,目的端口号
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address,port);

        //3.发送数据
        ds.send(dp);

        //4.释放资源
        ds.close();
    }
}

细节:

① DatagramSocket 需要绑定端口,然后通过这个端口往外发送数据。

如果是空参的构造函数,底层会在所有可用的端口中随机一个使用。

如果是有参的构造函数,参数就是指定的端口号。

② udp协议是面向无连接的,不论是否连接成功,都会发送数据,所以运行结果不会有任何提示。

Ⅱ. 接收数据

public class ReceiveMessage {
    public static void main(String[] args) throws IOException {
        //1.创建DatagramSocket对象(快递公司)
        DatagramSocket ds = new DatagramSocket(10086);

        //2.接收数据包
        byte[] bytes = new byte[1024];
        //参数:接收数据的数组,采用数组多大的空间去接收
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
        ds.receive(dp);

        //3.解析数据包
        byte[] data = dp.getData();//发送的数据
        int len = dp.getLength();//发送数据的字节长度
        InetAddress address = dp.getAddress();//发送方的ip地址
        int port = dp.getPort();//发送方通过哪个端口发送的

        System.out.println("接收到的数据为:" + new String(data, 0, len));
        System.out.println("该数据是从" + address + "的端口号为" + port + "所发出的");

        //4.释放资源
        ds.close();
    }
}

细节:

①  在接收的时候,DatagramSocket 对象一定要绑定端口号,而且端口号一定要和发送方发送到端口保持一致

② recevie 方法是阻塞的,程序在执行到这一步时,会一直等待,直到接收到发送方发送的消息。

运行结果:

Ⅲ. 通信方式
① 单播:一对一

上面写的代码就是单播,这里不再介绍。 

② 组播:一对多(一次一组) 

组播地址:224.0.0.0 ~ 239.255.255.255(其中 224.0.0.0 ~ 224.0.0.255 为预留的组播地址)

//发送方
public class SendMessage {
    public static void main(String[] args) throws IOException {
        //1.创建MulticastSocket对象(快递公司)
        MulticastSocket ms = new MulticastSocket();

        //2.打包数据
        String str = "你好!";
        //转换成字节数组
        byte[] bytes = str.getBytes();
        //获取目的地的组播地址
        InetAddress address = InetAddress.getByName("224.0.0.2");
        //端口号
        int port = 10086;

        //参数:发送的数据,数据的长度,目的地的ip地址对象,目的端口号
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address,port);

        //3.发送数据
        ms.send(dp);

        //4.释放资源
        ms.close();
    }
}

细节:

① 创建的是 MulticastSocket 对象,而不是 DatagramSocket 对象。

指定发送数据的目的地(接收方)的 ip 地址要是组播地址。

//接收方
public class ReceiveMessage {
    public static void main(String[] args) throws IOException {
        //1.创建MulticastSocket对象(快递公司)
        MulticastSocket ms = new MulticastSocket(10086);
        
        //2.将当前本机,添加到 组播地址为224.0.0.2的这一组中
        InetAddress address=InetAddress.getByName("224.0.0.2");
        ms.joinGroup(address);

        //3.接收数据包
        byte[] bytes = new byte[1024];
        //参数:接收数据的数组,采用数组多大的空间去接收
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
        ms.receive(dp);

        //4.解析数据包
        byte[] data = dp.getData();//发送的数据
        int len = dp.getLength();//发送数据的字节长度
        InetAddress ip = dp.getAddress();//发送方的ip地址
        int port = dp.getPort();//发送方通过哪个端口发送的

        System.out.println("接收到的数据为:" + new String(data, 0, len));
        System.out.println("该数据是从" + ip + "的端口号为" + port + "所发出的");

        //5.释放资源
        ms.close();
    }
}

细节:接收方接收数据前要多一步:将本机加入到发送方指定的组播地址中。 

读者可创建多个接收方的测试类,发送方发送数据后,这多个接收方只要在该组播地址内,均可接收到数据。 

③ 广播:一对 all 

 广播地址:255.255.255.255

//发送方
public class SendMessage {
    public static void main(String[] args) throws IOException {
        //1.创建DatagramSocket对象(快递公司)
        DatagramSocket ds = new DatagramSocket();

        //2.打包数据
        String str = "你好!";
        //转换成字节数组
        byte[] bytes = str.getBytes();
        //将目的地的ip地址设为广播地址
        InetAddress address = InetAddress.getByName("255.255.255.255");
        //端口号
        int port = 10086;

        //参数:发送的数据,数据的长度,目的地的ip地址对象,目的端口号
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address,port);

        //3.发送数据
        ds.send(dp);

        //4.释放资源
        ds.close();
    }
}

细节:

① 发送方代码和单播的代码几乎完全一致,唯一的变动就是:将目的地的ip地址设为广播地址

② 接收方的代码和单播一样。发送方一旦这样更改后,那么局域网中的所有设备都会收到此消息 

(2)TCP协议

传输控制协议(Transmission Control Protocol):面向连接的通信协议。

作用:速度慢,没有大小限制,数据安全(可靠)

面向连接:发送数据前,会先检查通信双方网络是否畅通,确保连接成功,才会发送数据。

应用场景:下载软件,文字聊天,发送邮件

Ⅰ. 过程

TCP通信是一种可靠的网络协议,它会在通信的两端各建立一个 Socket 对象

通信之前要保证连接已经建立,然后通过 Socket 产生 IO 流来进行网络通信

//客户端(发送方)
public class Client {
    public static void main(String[] args) throws IOException {
        //1.创建Socket对象(参数:服务端ip,服务端的端口号)
        Socket socket = new Socket("127.0.0.1", 10000);

        //2.从连接通道中获取输出流,写数据
        OutputStream os = socket.getOutputStream();
        os.write("你好!".getBytes());

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

 细节:

① 创建Socket对象时,会同时连接服务器,如果连接不上,代码会报错。

     所以,启动程序时,先启动服务端,再启动客户端,否则连接不上。

② 建立连接时,会依靠三次握手协议保证连接建立。

③ 释放资源时,不需要单独释放输出流,因为当调用Socket.close()方法时,它会自动关闭所有关联流。

④ 释放资源时,会依靠四次挥手协议断开连接,以确保连接通道中的数据已经处理完毕。

//服务端(接收方)
public class Server {
    public static void main(String[] args) throws IOException {
        //1.创建ServerSocket对象
        ServerSocket ss = new ServerSocket(8080);

        //2.监听客户端的连接
        Socket socket = ss.accept();

        //3.从连接通道中获取输入流,读取数据
        InputStream is = socket.getInputStream();
        //将字节流变成字符转换流-->可以读取中文
        InputStreamReader isr = new InputStreamReader(is);
        int b;
        while ((b = isr.read()) != -1) {
            System.out.print((char) b);
        }

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

细节:

① 创建 ServerSocket 对象时,指定的端口号要和客户端(发送方)发送到的端口保持一致,否则也会连接不上。

② accpet 方法也是阻塞的,程序在执行到这一步时,会一直等待,直到连接到客户端,然后返回一个 Socket 对象。

③ 释放资源时,不需要单独释放输入流,因为当调用Socket.close()方法时,它会自动关闭所有关联流。

Ⅱ. 三次握手

Ⅲ. 四次挥手 

  • 21
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值