Featured image of post java网络编程

java网络编程

本文阅读量

网络编程

是什么

可以让设备中的程序与网络中其他设备中的程序进行数据交互(实现网络通信)

基本的通信架构

基本的通信架构有2种形式:CS架构(Client客户端/Server服务端)、BS架构(Browser浏览器/Server服务端)

网络通信三要素

IP地址

设备在网络中的地址,是唯一标识

IP(Internet Proeocol):全称”互联网协议地址“,是分配给上网设备的唯一标志

IP地址有两种形式:IPv4,IPv6

IPv4

32bit (4字节) 为了更好识别,使用点分十进制表示法,可以更好的展示IPv4地址

IPv6

共128位,号称可以为地球每一粒沙子编号

IPv6分为8段表示,每段每4位编码成一个十六进制位表示,数之间用冒号(:)分开

为了更好识别IPv6,使用冒分十六进制表示法,可以更好的展示IPv6地址

如何通过域名访问网站

  1. 浏览器会访问本地dns服务器,dns服务器记录着你要访问域名的真实IP

    如果本地dns服务器没有查询到,就会到网络运营商dns服务器获取,并缓存

  2. 获取到要访问域名的真实ip后,浏览器就会访问对应网站的服务器,获取数据后在浏览器上进行展示

公网IP,内网IP

公网IP:是可以连接互联网的IP地址,

内网IP:也叫局域网iP,只能组织机构内部使用

案例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// 1、获取本机IP地址对象
InetAddress ip = InetAddress.getLocalHost();
System.out.println(ip.getHostAddress());
System.out.println(ip.getHostName());


// 2、指定获取对方主机的IP地址对象
InetAddress ip2 = InetAddress.getByName("www.baidu.com");
System.out.println(ip.getHostAddress());
System.out.println(ip.getHostName());

// 3、判断本机与该主机是否能够联通:ping
System.out.println(ip2.isReachable(5000)); // 5s 

端口号

标记正在计算机设备上运行的应用程序的,被规定为一个16位的二进制,范围是0~65535

分类

周知端口:0~1023,被预先定义的知名应用占用(如:HTTP占用80,FTP占用21)

注册端口:1024~49151,分配给用户进程或某些应用程序

动态端口:49152~65535,之所以称为动态端口,是因为它,一般不固定分配某些进程,而是动态分配

注意:

我们自己开发的程序一般选择使用注册端口,且一个设备中不能出现两个程序的端口号一样,否则出错

协议

网络上通信的设备,事先规定的连接规则,以及传输数据的规则被称为网络通信协议

为了让全球所有的上网设备都能够互联,开放式网络互联标准组织,制定了OSI网络参考模型(全球网络互联标准)

网络参考模型

我们一般在4层架构中的应用层进行开发,

我们说的协议就是在4层架构中的传输层,主要有2个:UDP与TCP

UDP通信

UDP协议

用户数据报协议(User Datagram Protocol)

特点

无连接、不可靠通信

事先不建立连接,数据按照包发,一包数据包含:自己的IP、程序端口、目的地IP、程序端口和数据(限制在64KB内)等

发送方不管对方是否在线,数据在中间丢失也不管,如果接收方收到数据也不返回确认,故不可靠

一发一收案例

客户端

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package cn.snailsir.stu;

import java.net.*;

public class Client {
    public static void main(String[] args) throws Exception {
        // 1、创建发送对象(抛韭菜的人)
        DatagramSocket socket = new DatagramSocket();

        // 2、创建一个数据包对象,负责封装要发送的数据
        byte[] buffer = "今晚一起啤酒、龙虾、小烧烤,约吗?".getBytes();
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getLocalHost(), 8888);// 盒子

        //3 、把这一包数据发出去(抛出去韭菜)
        socket.send(packet);

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

        System.out.println("客户端已经发送完毕!");

    }
}

服务端

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package cn.snailsir.stu;

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

public class Server {
    public static void main(String[] args) throws Exception {
        System.out.println("===服务端启动成功==");

        // 1、创建接收端对象,注册端口
        DatagramSocket socket = new DatagramSocket(8888);

        // 2、创建一个数据包对象(韭菜盘子)
        byte[] buffer = new byte[1024 * 64];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

        // 3、接收数据(接收韭菜)
        socket.receive(packet); // 暂停等待


        // 4、把数据输出
        int len = packet.getLength();
        String msg = new String(buffer,0,len);
        System.out.println(msg);

        // 获取发送端的ip和端口
        InetAddress ip = packet.getAddress();
        System.out.println("对方ip:" + ip.getHostAddress());
        System.out.println("对方端口:" + packet.getPort());

        // 5、释放资源
        socket.close();

    }
}

多发多收案例

客户端

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Client {
    public static void main(String[] args) throws Exception {
        // 1、创建发送对象(抛韭菜的人)
        DatagramSocket socket = new DatagramSocket();

        // 2、创建一个数据包对象,负责封装要发送的数据
        Scanner sc = new Scanner(System.in);

        while (true) {
            System.out.println("请说:");
            String msg = sc.nextLine();
            if(msg.equals("exit")){
                System.out.println("退出成功");
                // 4、释放资源
                socket.close();
            }
            byte[] buffer = msg.getBytes();
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getLocalHost(), 8888);// 盒子

            //3 、把这一包数据发出去(抛出去韭菜)
            socket.send(packet);
        }



//        System.out.println("客户端已经发送完毕!");

    }
}

服务端

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class Server {
    public static void main(String[] args) throws Exception {
        System.out.println("===服务端启动成功==");

        // 1、创建接收端对象,注册端口
        DatagramSocket socket = new DatagramSocket(8888);

        // 2、创建一个数据包对象(韭菜盘子)
        byte[] buffer = new byte[1024 * 64];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

        // 3、接收数据(接收韭菜)
        while (true) {
            socket.receive(packet); // 暂停等待

            // 4、把数据输出
            int len = packet.getLength();
            String msg = new String(buffer,0,len);
            System.out.println("收到"+msg);

            // 获取发送端的ip和端口
            InetAddress ip = packet.getAddress();
            System.out.println("对方ip:" + ip.getHostAddress());
            System.out.println("对方端口:" + packet.getPort());
        }
    }
}

TCP通信

Tcp协议

传输控制协议(Transmission Control Protocol)

特点

面向连接、可靠通信

TCP的最终目的:要保证在不可靠的信道上实现可靠的传输

TCP主要有三个步骤实现可靠传输:三次握手建立连接,传输数据进行确认,四次挥手断开连接

三次握手原理

可靠连接:确定通信双方,收费消息都是正常无问题的!(全双工)

  1. 客户端 -> 发送连接请求
  2. 服务端 -> 确认收到请求,返回一个响应
  3. 客户端 -> 确认服务端信息,建立连接

为什么要三次握手建立连接?

第一次握手,服务端确定了客户端能发送消息

第二次握手,客户端确定了服务端能接收与发送消息

第三次握手,服务端确定了客户端能接收消息

ack确认机制

传输数据会进行确认,以保证数据传输的可靠性

四次挥手

目的:确保双方数据的收发都已经完成

  1. 客户端 -> 发送断开连接请求
  2. 服务端 -> 收到断开请求,返回一个响应:稍等
  3. 服务端,处理完未处理的数据后 -> 返回一个响应:确认断开
  4. 客户端 -> 发出正式确认断开连接
使用 Hugo 构建
主题 StackJimmy 设计