Java网络编程

Java网络编程

  • [1. 常见的软件架构](#1. 常见的软件架构)
    • [1.1 CS结构](#1.1 CS结构)
    • [1.2 BS架构](#1.2 BS架构)
  • [2. 网络编程三要素](#2. 网络编程三要素)
  • 3.InetAddress使用
  • [4. 端口号](#4. 端口号)
  • [5. 协议](#5. 协议)
    • [5.1 UDP协议](#5.1 UDP协议)
    • [5.1.1 代码演示](#5.1.1 代码演示)
    • [5.2 UDP的三种通信方式](#5.2 UDP的三种通信方式)
      • [5.2.1 单播](#5.2.1 单播)
      • [5.2.2 组播](#5.2.2 组播)
      • [5.2.3 广播](#5.2.3 广播)
    • [5.3 TCP通信](#5.3 TCP通信)
      • [5.3.1 TCP的基本特性](#5.3.1 TCP的基本特性)
      • [5.3.2 TCP的工作原理](#5.3.2 TCP的工作原理)
        • [5.3.2.1 三次握手(建立连接)](#5.3.2.1 三次握手(建立连接))
        • [5.3.2.2 数据传输](#5.3.2.2 数据传输)
        • [5.3.2.3 四次挥手(断开连接)](#5.3.2.3 四次挥手(断开连接))
      • [5.3.2 TCP报文结构](#5.3.2 TCP报文结构)
      • [5.3.3 TCP应用场景](#5.3.3 TCP应用场景)
      • [5.3.4 代码演示](#5.3.4 代码演示)

1. 常见的软件架构

1.1 CS结构

常见的CS结构的软件有QQ、微信、Steam等

1.2 BS架构

2. 网络编程三要素

3.InetAddress使用

InetAddress 是 Java 中用于表示 IP 地址的类,位于 java.net 包中。它可以表示一个 IP 地址(IPv4 或 IPv6),并提供用于解析主机名的静态方法。以下是 InetAddress 类的详细介绍及其常用方法:

InetAddress 类的基本概念

  • IP 地址: InetAddress 对象可以表示一个互联网协议 (IP) 地址。
  • 主机名解析: 它提供了将主机名解析为 IP 地址的方法,以及将 IP 地址解析为主机名的方法。
  • 静态工厂方法: 用于获取 InetAddress 实例。
java 复制代码
import java.net.InetAddress;
import java.net.UnknownHostException;

public class InetAddressStudy {
    public static void main(String[] args) throws UnknownHostException {
        // 获取本地主机地址
        InetAddress localHost = InetAddress.getLocalHost();
        System.out.println("Local host: " + localHost.getHostName() + " (" + localHost.getHostAddress() + ")");

        // 根据主机名获取 InetAddress 对象
        InetAddress address = InetAddress.getByName("www.baidu.com");
        System.out.println("Host: " + address.getHostName() + ", IP Address: " + address.getHostAddress());

        // 根据主机名获取所有关联的 InetAddress 对象
        InetAddress[] addresses = InetAddress.getAllByName("www.baidu.com");
        for (InetAddress addr : addresses) {
            System.out.println("Host: " + addr.getHostName() + ", IP Address: " + addr.getHostAddress());
        }

        // 获取本地回环地址
        InetAddress loopbackAddress = InetAddress.getLoopbackAddress();
        System.out.println("Loopback Address: " + loopbackAddress.getHostAddress());

        // 判断地址是否为多播地址
        boolean isMulticast = address.isMulticastAddress();
        System.out.println("Is multicast address: " + isMulticast);
    }
}

结果:
Local host: fanzhendembp-2 (192.168.1.4)
Host: www.baidu.com, IP Address: 39.156.66.14
Host: www.baidu.com, IP Address: 39.156.66.14
Host: www.baidu.com, IP Address: 39.156.66.18
Host: www.baidu.com, IP Address: 2409:8c00:6c21:104f:0:ff:b03f:3ae
Host: www.baidu.com, IP Address: 2409:8c00:6c21:1051:0:ff:b0af:279a
Loopback Address: 127.0.0.1
Is multicast address: false

4. 端口号

端口(Port)是计算机网络中的一个重要概念,用于标识传输层协议(如 TCP 或 UDP)所使用的通信端点。端口号是一个 16 位的数字,范围从 0 到 65535,每个端口号代表一个特定的网络服务或应用程序。以下是关于端口的详细介绍:

端口的基本概念

  1. 端口号: 端口号是一个整数,用于标识网络上的特定服务或应用程序。每个网络连接通过 IP 地址和端口号的组合来唯一标识。
  2. 传输层协议: 端口号与传输层协议(如 TCP 或 UDP)结合使用,用于区分不同类型的网络通信。
  3. 知名端口(Well-Known Ports): 范围为 0-1023,用于常见的网络服务和协议,例如 HTTP(80 端口)、HTTPS(443 端口)、FTP(21 端口)等。
  4. 注册端口(Registered Ports): 范围为 1024-49151,分配给特定的服务和应用程序。
  5. 动态端口(Dynamic/Private Ports): 范围为 49152-65535,通常用于客户端临时连接。

端口的分类

  1. TCP 端口: 用于基于连接的通信,例如 HTTP、HTTPS、FTP、SMTP 等。
  2. UDP 端口: 用于无连接的通信,例如 DNS、DHCP、SNMP 等。

端口的作用
端口用于在同一台计算机上区分多个网络服务。例如,一台服务器可以同时运行 Web 服务(HTTP,80 端口)和邮件服务(SMTP,25 端口),客户端可以通过不同的端口号连接到相应的服务。

端口的工作原理

当一个程序需要通过网络进行通信时,它会绑定到一个特定的端口号并监听来自其他计算机的连接请求。以下是一个简单的例子:

  1. 服务器端: 服务器程序在特定的端口上监听连接请求。例如,Web 服务器通常监听 80 端口上的 HTTP 请求。
  2. 客户端: 客户端程序通过指定服务器的 IP 地址和端口号来建立连接。例如,Web 浏览器通过访问特定的 URL(如 http://example.com)来连接到服务器的 80 端口。
  3. 数据传输: 一旦连接建立,数据就可以在客户端和服务器之间传输。服务器通过端口号来识别并处理不同的请求。

5. 协议

5.1 UDP协议

UDP(用户数据报协议,User Datagram Protocol)是一种面向无连接的传输层协议,属于TCP/IP协议族中的一个重要组成部分。UDP提供了一种简单但不可靠的服务,主要用于对速度和效率要求高,而对数据传输的准确性和可靠性要求相对较低的应用场景。

主要特点

  1. 无连接:
    UDP不需要建立连接就可以发送数据报。每个数据报都是独立的,没有任何关系,这样可以减少开销和延迟。

  2. 不可靠传输:
    UDP没有提供保证数据包到达的机制,也没有重传机制。数据包可能会丢失、重复或乱序。

  3. 快速:
    由于不需要连接建立和维护过程,UDP传输速度较快,适用于实时应用。

  4. 简单的首部:
    UDP报文头部很简单,只有8个字节,包括源端口、目的端口、长度和校验和。

  5. 数据报格式:
    每个UDP数据报包括一个UDP首部和一个数据部分。

应用场景

  1. 实时应用:

    如视频会议、网络电话、在线游戏等,这些应用对时延和速度要求高,对数据可靠性要求相对较低。

  2. 简单请求-响应协议:

    如DNS(域名系统)查询,由于查询数据包小且丢失后可以重新发送,因此使用UDP协议效率更高。

  3. 广播和组播:

    UDP支持广播和组播,适用于向多个接收者发送相同数据的场景,如IPTV等。

优缺点
优点:

  • 速度快,开销小,适合对延迟敏感的应用。
  • 实现简单,资源消耗少。

缺点:

  • 不保证数据的可靠传输,可能会丢包、乱序或重复。
  • 没有流量控制和拥塞控制机制。

5.1.1 代码演示

java 复制代码
import java.io.IOException;
import java.net.*;

public class SendMessageDemo {
    public static void main(String[] args) throws IOException {
        //发送数据


        //1.创建DatagramSocket对象(快递公司)
        //细节:
        //绑定端口,以后我们就是通过这个端口往外发送
        //空参:所有可用的端口中随机一个进行使用
        //有参:指定端口号进行绑定
        DatagramSocket ds = new DatagramSocket();

        //2.打包数据
        String str = "你好威啊!!!";
        byte[] bytes = str.getBytes();
        InetAddress address = InetAddress.getByName("127.0.0.1");
        int port = 10086;

        DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);

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

        //4.释放资源
        ds.close();
    }
}
java 复制代码
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class ReceiveMessageDemo {
    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);

        //该方法是阻塞的
        //程序执行到这一步的时候,会在这里死等
        //等发送端发送消息
        System.out.println(11111);
        ds.receive(dp);
        System.out.println(2222);

        //3.解析数据包
        byte[] data = dp.getData();
        int len = dp.getLength();
        InetAddress address = dp.getAddress();
        int port = dp.getPort();

        System.out.println("接收到数据" + new String(data,0,len));
        System.out.println("该数据是从" + address + "这台电脑中的" + port + "这个端口发出的");

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

5.2 UDP的三种通信方式

单播、组播、广播

5.2.1 单播

5.2.2 组播

组播地址:224.0.0.0 ~ 239.255.255.255

其中 224.0.0.0. ~ 224.0.0.255 为预留的组播地址

java 复制代码
组播发送端代码

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

public class SendMessageDemo {
    public static void main(String[] args) throws IOException {
         /*
            组播发送端代码
        */

        //创建MulticastSocket对象
        MulticastSocket ms = new MulticastSocket() ;

        // 创建DatagramPacket对象
        String s = "你好,你好!" ;
        byte[] bytes = s.getBytes();
        InetAddress address = InetAddress.getByName("224.0.0.1");
        int port = 10000;

        DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, address, port) ;

        // 调用MulticastSocket发送数据方法发送数据
        ms.send(datagramPacket);

        // 释放资源
        ms.close();
    }
}
java 复制代码
接收端1

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

public class ReceiveMessageDemo1 {
    public static void main(String[] args) throws IOException {
        /*
            组播接收端代码
        */

        //1. 创建MulticastSocket对象
        MulticastSocket ms = new MulticastSocket(10000);

        //2. 将将当前本机,添加到224.0.0.1的这一组当中
        InetAddress address = InetAddress.getByName("224.0.0.1");
        ms.joinGroup(address);

        //3. 创建DatagramPacket数据包对象
        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);

        //4. 接收数据
        ms.receive(dp);

        //5. 解析数据
        byte[] data = dp.getData();
        int len = dp.getLength();
        String ip = dp.getAddress().getHostAddress();
        String name = dp.getAddress().getHostName();

        System.out.println("ip为:" + ip + ",主机名为:" + name + "的人,发送了数据:" + new String(data,0,len));

        //6. 释放资源
        ms.close();
    }
}
java 复制代码
接收端2

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

public class ReceiveMessageDemo2 {
    public static void main(String[] args) throws IOException {
        /*
            组播接收端代码
        */

        //1. 创建MulticastSocket对象
        MulticastSocket ms = new MulticastSocket(10000);

        //2. 将将当前本机,添加到224.0.0.1的这一组当中
        InetAddress address = InetAddress.getByName("224.0.0.1");
        ms.joinGroup(address);

        //3. 创建DatagramPacket数据包对象
        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);

        //4. 接收数据
        ms.receive(dp);

        //5. 解析数据
        byte[] data = dp.getData();
        int len = dp.getLength();
        String ip = dp.getAddress().getHostAddress();
        String name = dp.getAddress().getHostName();

        System.out.println("ip为:" + ip + ",主机名为:" + name + "的人,发送了数据:" + new String(data,0,len));

        //6. 释放资源
        ms.close();
    }
}
java 复制代码
接收端3

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

public class ReceiveMessageDemo3 {
    public static void main(String[] args) throws IOException {
        /*
            组播接收端代码
        */

        //1. 创建MulticastSocket对象
        MulticastSocket ms = new MulticastSocket(10000);

        //2. 将将当前本机,添加到224.0.0.1的这一组当中
        InetAddress address = InetAddress.getByName("224.0.0.1");
        ms.joinGroup(address);

        //3. 创建DatagramPacket数据包对象
        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);

        //4. 接收数据
        ms.receive(dp);

        //5. 解析数据
        byte[] data = dp.getData();
        int len = dp.getLength();
        String ip = dp.getAddress().getHostAddress();
        String name = dp.getAddress().getHostName();

        System.out.println("ip为:" + ip + ",主机名为:" + name + "的人,发送了数据:" + new String(data,0,len));

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

5.2.3 广播

广播地址255.255.255.255

只需要修改为255.255.255.255

5.3 TCP通信

TCP(传输控制协议,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的通信协议,它是Internet协议栈中的核心协议之一。TCP提供了可靠的数据传输、流量控制和拥塞控制等功能,广泛用于网络应用,如HTTP、FTP、SMTP等。

5.3.1 TCP的基本特性

  • 面向连接:在数据传输开始之前,通信双方必须建立一个连接(通过三次握手)。
  • 可靠传输:通过序列号、确认机制、重传机制等保证数据的完整性和正确性。
  • 流量控制:防止发送方发送数据过快,导致接收方来不及处理。
  • 拥塞控制:防止网络拥塞,保证网络资源的有效利用。TCP采用多种算法来进行拥塞控制,如慢启动(Slow Start)、拥塞避免(Congestion Avoidance)、快重传(Fast Retransmit)和快恢复(Fast Recovery)。

5.3.2 TCP的工作原理

5.3.2.1 三次握手(建立连接)

TCP连接的建立需要三次握手过程:

  1. 第一次握手:客户端向服务器发送一个SYN(synchronize)包,请求建立连接。
  2. 第二次握手:服务器收到SYN包后,向客户端发送一个SYN-ACK包,表示同意连接。
  3. 第三次握手:客户端收到SYN-ACK包后,向服务器发送一个ACK(acknowledge)包,连接建立完成。
5.3.2.2 数据传输
  • 数据分片:数据被分割成若干个TCP报文段,每个报文段都有一个序列号。
  • 序列号和确认号:接收方会返回确认号(ACK)来确认收到的数据。发送方如果在一定时间内没有收到ACK,会重传该报文段。
  • 窗口机制:TCP使用滑动窗口机制来进行流量控制。发送窗口大小由接收方的接收窗口和网络状况决定。
  • 超时重传:如果发送方在超时时间内未收到ACK,将重新发送该报文段。
5.3.2.3 四次挥手(断开连接)

TCP连接的断开需要四次挥手过程:

  1. 第一次挥手:主动关闭方发送一个FIN(finish)包,表示没有数据要发送了。
  2. 第二次挥手:被动关闭方收到FIN包后,发送一个ACK包,确认关闭请求。
  3. 第三次挥手:被动关闭方发送一个FIN包,表示同意关闭连接。
  4. 第四次挥手:主动关闭方收到FIN包后,发送一个ACK包,连接关闭完成。

5.3.2 TCP报文结构

TCP报文段的结构主要包括以下字段:

  • 源端口和目标端口:标识发送方和接收方的应用程序端口。
  • 序列号:标识报文段在整个字节流中的位置。
  • 确认号:表示接收到的数据的下一个字节序号。
  • 头部长度:TCP头部的长度。
  • 控制标志:包括SYN、ACK、FIN、RST等。
  • 窗口大小:接收方当前的接收窗口大小。
  • 校验和:用于检验报文段的完整性。
  • 紧急指针:指示紧急数据的位置(如果有)。
  • 选项:可选字段,如最大报文段长度(MSS)等。

5.3.3 TCP应用场景

TCP广泛用于需要可靠传输的网络应用,如:

  • 网页浏览:HTTP/HTTPS协议基于TCP。
  • 文件传输:FTP协议基于TCP。
  • 电子邮件:SMTP、IMAP、POP3协议基于TCP。

5.3.4 代码演示

java 复制代码
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws IOException {
        //TCP协议,发送数据

        //1.创建Socket对象
        //细节:在创建对象的同时会连接服务端
        //      如果连接不上,代码会报错
        Socket socket = new Socket("127.0.0.1",10000);

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

        //3.释放资源
        os.close();
        socket.close();
    }
}
java 复制代码
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        //TCP协议,接收数据

        //1.创建对象ServerSocker
        ServerSocket ss = new ServerSocket(10000);

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

        //3.从连接通道中获取输入流读取数据
        InputStream is = socket.getInputStream();
        int b;
        while ((b = is.read()) != -1){
            System.out.print((char) b);
        }

        //4.释放资源
        socket.close();
        ss.close();
    }
}
相关推荐
suweijie7683 小时前
SpringCloudAlibaba | Sentinel从基础到进阶
java·大数据·sentinel
公贵买其鹿4 小时前
List深拷贝后,数据还是被串改
java
xlsw_7 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹8 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭8 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫8 小时前
泛型(2)
java
超爱吃士力架8 小时前
邀请逻辑
java·linux·后端
南宫生9 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石9 小时前
12/21java基础
java
李小白669 小时前
Spring MVC(上)
java·spring·mvc