Java第二十一章

网络程序设计基础

局域网与互联网

为了实现两台计算机的通信,必须用一个网络线路连接两台计算机。如下图所示

网络协议

1.IP协议

IP是Internet Protocol的简称,是一种网络协议。Internet 网络采用的协议是TCP/IP协议,其全称是Transmission Control Protocol/Internet Protocol。Internet 依靠TCP/IP协议,在全球范围内实现了不同硬件结构、不同操作系统、不同网络系统间的互联。在Internet 网络上存在着数以亿计的主机,每台主机都用网络为其分配的 Internet 地址代表自己,这个地址就是I地址。到目前为止,I地址用4个字节,也就是32位的二进制数来表示,称为IPv4。为了便于使用,通常取用每个字节的十进制数,并且每个字节之间用圆点隔开来表示I地址,如192.168.1.1。现在人们正在试验使用16个字节来表示I地址,这就是IPv6,但IPv6还没有投入使用。

TCP/IP 模式是一种层次结构,共分为4层,分别为应用层、传输层、互联网层和网络层。各层实现特定的功能,提供特定的服务和访问接口,并具有相对的独立性,如图所示。

2. TCP与UDP协议

在TCPAIP 协议栈中,有两个高级协议是网络应用程序编写者应该了解的,即传输控制协议(Transmission Control Protocol,TCP)与用户数据报协议(User Datagram Protocol, UDP)。

TCP 协议是一种以固接连线为基础的协议,它提供两台计算机间可靠的数据传送。TCP可以保证数据从一端送至连接的另一端时,能够确实送达,而且抵达的数据的排列顺序和送出时的顺序相同。因此,TCP协议适合可靠性要求比较高的场合。就像拨打电话,必须先拨号给对方,等两端确定连接后,相互才能听到对方说话,也知道对方回应的是什么。

HTTP、FTP 和Telnet 等都需要使用可靠的通信频道。例如,HTTP从某个URL读取数据时,如果收到的数据顺序与发送时不相同,可能就会出现一个混乱的HTML文件或是一些无效的信息。

UDP是无连接通信协议,不保证数据的可靠传输,但能够向若干个目标发送数据,或接收来自若干个源的数据。UDP以独立发送数据包的方式进行。这种方式就像邮递员送信给收信人,可以寄出很多信给同一个人,且每一封信都是相对独立的,各封信送达的顺序并不重要,收信人接收信件的顺序也不能保证与寄出信件的顺序相同。

UDP 协议适合于一些对数据准确性要求不高,但对传输速度和时效性要求非常高的网站,如网络聊天室、在线影片等。这是由于TCP协议在认证上存在额外耗费,可能使传输速度减慢,而UDP协议即使有一小部分数据包遗失或传送顺序有所不同,也不会严重危害该项通信。

端口与套接字

一般而言,一台计算机只有单一的连到网络的物理连接(Physical Connection),所有的数据都通过此连接对内、对外送达特定的计算机,这就是端口。网络程序设计中的端口(port)并非真实的物理存在,而是一个假想的连接装置。端口被规定为一个在0~65535的整数。HTTP服务一般使用80端口,FTP 服务使用21端口。假如一台计算机提供了HTTP、FTP等多种服务,那么客户机会通过不同的端口来确定连接到服务器的哪项服务上,如图所示。

通常,0~1023的端口数用于一些知名的网络服务和应用,用户的普通网络应用程序应该使用1024以上的端口数,以避免端口号与另一个应用或系统服务所用端口冲突。

网络程序中的套接字(Socket)用于将应用程序与端口连接起来。套接字是一个假想的连接装置,就像插座一样可连接电器与电线,如图所示。

Java 将套接字抽象化为类,程序设计者只需创建Socket类对象,即可使用套接字。

TCP程序

TCP网络程序设计是指利用Socket 类编写通信程序。利用TCP协议进行通信的两个应用程序是有主次之分的,一个称为服务器程序,另一个称为客户机程序,两者的功能和编写方法大不一样。服务器端与客户端的交互过程如图所示。

  1. 服务器程序创建一个 ServerSocket(服务器端套接字)对象,调用accept0方法等待客户机来连接
  2. 客户端程序创建一个Socket对象,请求与服务器建立连接
  3. 服务器接收客户机的连接请求,同时创建一个新的Socket 对象与客户建立连接。随后服务器继续等待新的请求

InetAddress 类

java.net包中的InetAddress类是与IP地址相关的类,利用该类可以获取IP地址、主机地址等信息。

例题21.1

 
  1. import java.net.*; //导出Java.net包
    
    
    public class Address { //创建类
    
    
    public static void main(String[] args) {
    
    InetAddress ip; //创建InetAddress对象
    
    try { //捕捉可能出现的异常
    
    ip = InetAddress.getLocalHost(); //实例化对象
    
    String locaIname = ip.getHostName(); //获取本机名
    
    String localip = ip.getHostAddress(); //获取本机IP地址
    
    System.out.println("本机名:"+locaIname); //将本机名输出
    
    System.out.println("本机名IP地址:"+localip); //将本机IP地址输出
    
    }catch(UnknownHostException e){
    
    e.printStackTrace(); //输出异常信息
    
    }
    
    
    }
    
    
    }//例题21.1

运行结果如下:

ServerSocket 类

  • ServerSocker 类的构造方法通常会抛出1OException异常,具体有以下几种形式:
  • ServerSocket():创建非绑定服务器套接字。
  • ServerSocket(int port):创建绑定到特定端口的服务器套接字。
  • ServerSocket(int port, int backlog):利用指定的backlog创建服务器套接字,并将其绑定到指定的本地端口号上。
  • ServerSocket(int port, int backlog, InetAddress bindAddress):使用指定的端口、侦听backlog和要绑定到的本地IP地址创建服务器。这种情况适用于计算机上有多块网卡和多个I地址的情况,用户可以明确规定ServerSocket在哪块网卡或哪个IP地址上等待客户的连接请求。

ServerSocket 类的常用方法如表21.2所示。

TCP网络程序设计

例题21.2

 
  1. 
    
    import java.io.*;
    
    import java.net.*;
    
    
    public class MyServer {
    
    private ServerSocket server; // 服务器套接字
    
    private Socket socket; // 客户端套接字
    
    
    void start() {// 启动服务器
    
    try {
    
    server = new ServerSocket(8998); // 服务器启用8998端口
    
    System.out.println("服务器套接字已经创建成功");
    
    while (true) {
    
    System.out.println("等待客户端的连接");
    
    socket = server.accept(); // 服务器监听客户端连接
    
    // 根据套接字字节流创建字符输入流
    
    BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    
    while (true) {// 循环接受信息
    
    String message = reader.readLine();// 读取一行文本
    
    if ("exit".equals(message)) {// 如果客户端发来的内容为“exit”
    
    System.out.println("客户端退出");
    
    break;// 停止接受信息
    
    }
    
    System.out.println("客户端:" + message);
    
    }
    
    reader.close(); // 关闭流
    
    socket.close(); // 关闭套接字
    
    }
    
    } catch (IOException e) {
    
    e.printStackTrace();
    
    }
    
    }
    
    
    public static void main(String[] args) {
    
    MyServer tcp = new MyServer();
    
    tcp.start(); // 启动服务器
    
    }
    
    }
    
    //21.2

运行结果如下:

编写客户端程序,将用户在文本框中输入的信息发送至服务端,并将文本框中输入的信息显示再客户端的文本域中。

 
  1. 
    
    import java.awt.*;
    
    import java.awt.event.*;
    
    import java.io.*;
    
    import java.net.Socket;
    
    import javax.swing.*;
    
    
    public class MyClient extends JFrame {
    
    private PrintWriter writer;// 根据套接字字节流创建的字符输出流
    
    Socket socket; // 客户端套接字
    
    private JTextArea area = new JTextArea();// 展示信息的文本域
    
    private JTextField text = new JTextField(); // 发送信息的文本框
    
    
    public MyClient() {
    
    setTitle("向服务器送数据");
    
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    Container c = getContentPane(); // 主容器
    
    JScrollPane scrollPane = new JScrollPane(area);// 滚动面板
    
    getContentPane().add(scrollPane, BorderLayout.CENTER);
    
    c.add(text, "South"); // 将文本框放在窗体的下部
    
    text.addActionListener(new ActionListener() {// 文本框触发回车事件
    
    public void actionPerformed(ActionEvent e) {
    
    writer.println(text.getText().trim()); // 将文本框中的信息写入流
    
    area.append(text.getText() + '\n'); // 将文本框中的信息显示在文本域中
    
    text.setText(""); // 将文本框清空
    
    }
    
    });
    
    }
    
    
    private void connect() { // 连接服务器方法
    
    area.append("尝试连接\n"); // 文本域中提示信息
    
    try {
    
    socket = new Socket("127.0.0.1", 8998); // 连接本地计算机的8998端口
    
    writer = new PrintWriter(socket.getOutputStream(), true);
    
    area.append("完成连接\n");
    
    } catch (IOException e) {
    
    e.printStackTrace();
    
    }
    
    }
    
    
    public static void main(String[] args) {
    
    MyClient clien = new MyClient();
    
    clien.setSize(200, 200); // 窗体大小
    
    clien.setVisible(true); // 显示窗体
    
    clien.connect(); // 连接服务器
    
    }
    
    }
    
    //21.2

运行结果如下:

UDP程序

基于 UDP通信的基本模式如下:

  • 将数据打包(称为数据包),然后将数据包发往目的地。
  • 接收别人发来的数据包,然后查看数据包。

发送数据包的步骤如下:

(1)使用DatagramSocketO创建一个数据包套接字。

(2)使用DatagramPacket(byte[] buf,int offset, int length,InetAddress address,int port)创建要发送的数据包。

(3)使用DatagramSocket 类的sendO方法发送数据包。

接收数据包的步骤如下:

(1)使用DatagramSocket(int port)创建数据包套接字,绑定到指定的端口。

  (2)使用 DatagramPacket(byte buf, int length)创建字节数组来接收数据包。

(3)使用DatagramPacket 类的receive0方法接收UDP包。

DatagramPacket类

java.net 包的DatagramPacket 类用来表示数据包。DatagramPacket 类的构造方法如下:

  • DatagramPacket(byte[] buf, int length)
  • DatagramPacket(bytel] buf, int length, InetAddress address, int port)

第一种构造方法在创建DatagramPacket 对象时,指定了数据包的内存空间和大小。

第二种构造方法不仅指定了数据包的内存空间和大小,还指定了数据包的目标地址和端口。

DatagramSocker 类

  • java.net 包中的()
  • DatagramSocket(int port)
  • DatagramSocket(int port, InetAddress addr)

第一种构造方法创建DatagramSocket对象,构造数据报套接字,并将其绑定到本地主机任何可用的端口上。

第二种构造方法创建DatagramSocket对象,创建数据报套接字,并将其绑定到本地主机的指定端口上。

第三种构造方法创建DatagramSocket对象,创建数据报套接字,并将其绑定到指定的端口和指定的本地地址上。第三种构造函数适用于有多块网卡和多个I地址的情况。

UDP网络程序设计

例题21.3

(1)广播主机程序不断地向外播放信息,代码如下:

 
  1. 
    import java.io.IOException;
    
    import java.net.*;
    
    
    public class Notification extends Thread {
    
    String weather = "节目预报:八点有大型晚会,请收听";// 发送的消息
    
    int port = 9898; // 端口
    
    InetAddress iaddress = null;
    
    MulticastSocket socket = null; // 多点广播套接字
    
    
    Notification() {
    
    try {
    
    iaddress = InetAddress.getByName("224.255.10.0"); // 实例化InetAddress,指定地址
    
    socket = new MulticastSocket(port); // 实例化多点广播套接字
    
    socket.setTimeToLive(1); // 指定发送范围是本地网络
    
    socket.joinGroup(iaddress); // 加入广播组
    
    } catch (IOException e) {
    
    e.printStackTrace(); // 输出异常信息
    
    }
    
    }
    
    
    public void run() {
    
    while (true) {
    
    DatagramPacket packet = null; // 数据包
    
    byte data[] = weather.getBytes(); // 字符串消息的字节数组
    
    packet = new DatagramPacket(data, data.length, iaddress, port); // 将数据打包
    
    System.out.println(weather); // 控制台打印消息
    
    try {
    
    socket.send(packet); // 发送数据
    
    sleep(3000); // 线程休眠
    
    } catch (IOException e) {
    
    e.printStackTrace();
    
    } catch (InterruptedException e) {
    
    e.printStackTrace();
    
    }
    
    }
    
    }
    
    
    public static void main(String[] args) {
    
    Notification w = new Notification();
    
    w.start(); // 启动线程
    
    }
    
    }
    
    //21.3

运行结果如下:

(2)接收广播程序。单机“开始接收”按钮,系统开始接收主机播出的信息;单机“停止接收”按钮,系统停止接收广播主机播出的信息。代码如下:

 
  1.  

    import java.awt.*;
    
    import java.awt.event.*;
    
    import java.io.IOException;
    
    import java.net.*;
    
    import javax.swing.*;
    
    
    public class Receive extends JFrame implements Runnable, ActionListener {
    
    int port; // 端口
    
    InetAddress group = null; // 广播组地址
    
    MulticastSocket socket = null; // 多点广播套接字对象
    
    JButton inceBtn = new JButton("开始接收");
    
    JButton stopBtn = new JButton("停止接收");
    
    JTextArea inceAr = new JTextArea(10, 10); // 显示接收广播的文本域
    
    JTextArea inced = new JTextArea(10, 10);
    
    Thread thread;
    
    boolean stop = false; // 停止接受信息状态
    
    
    public Receive() {
    
    setTitle("广播数据报");
    
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    
    thread = new Thread(this);
    
    inceBtn.addActionListener(this); // 绑定按钮ince的单击事件
    
    stopBtn.addActionListener(this); // 绑定按钮stop的单击事件
    
    inceAr.setForeground(Color.blue); // 指定文本域中文字的颜色
    
    JPanel north = new JPanel(); // 创建Jpanel对象
    
    north.add(inceBtn); // 将按钮添加到面板north上
    
    north.add(stopBtn);
    
    add(north, BorderLayout.NORTH); // 将north放置在窗体的上部
    
    JPanel center = new JPanel(); // 创建面板对象center
    
    center.setLayout(new GridLayout(1, 2)); // 设置面板布局
    
    center.add(inceAr); // 将文本域添加到面板上
    
    center.add(inced);
    
    add(center, BorderLayout.CENTER); // 设置面板布局
    
    validate(); // 刷新
    
    port = 9898; // 设置端口号
    
    try {
    
    group = InetAddress.getByName("224.255.10.0"); // 指定接收地址
    
    socket = new MulticastSocket(port); // 绑定多点广播套接字
    
    socket.joinGroup(group); // 加入广播组
    
    } catch (IOException e) {
    
    e.printStackTrace(); // 输出异常信息
    
    }
    
    setBounds(100, 50, 360, 380); // 设置布局
    
    setVisible(true); // 将窗体设置为显示状态
    
    }
    
    
    public void run() { // run()方法
    
    while (!stop) {
    
    byte data[] = new byte[1024]; // 创建缓存字节数组
    
    DatagramPacket packet = null;
    
    packet = new DatagramPacket(data, data.length, group, port); // 待接收的数据包
    
    try {
    
    socket.receive(packet); // 接收数据包
    
    String message = new String(packet.getData(), 0, packet.getLength()); // 获取数据包中的内容
    
    inceAr.setText("正在接收的内容:\n" + message); // 将接收内容显示在文本域中
    
    inced.append(message + "\n"); // 每条信息为一行
    
    } catch (IOException e) {
    
    e.printStackTrace(); // 输出异常信息
    
    }
    
    }
    
    }
    
    
    public void actionPerformed(ActionEvent e) { // 单击事件
    
    if (e.getSource() == inceBtn) { // 单击按钮ince触发的事件
    
    inceBtn.setBackground(Color.red); // 设置按钮颜色
    
    stopBtn.setBackground(Color.yellow);
    
    if (!(thread.isAlive())) { // 如线程不处于“新建状态”
    
    thread = new Thread(this); // 实例化Thread对象
    
    }
    
    thread.start(); // 启动线程
    
    stop = false; // 开始接受信息
    
    }
    
    if (e.getSource() == stopBtn) { // 单击按钮stop触发的事件
    
    inceBtn.setBackground(Color.yellow); // 设置按钮颜色
    
    stopBtn.setBackground(Color.red);
    
    stop = true; // 停止接受信息
    
    }
    
    }
    
    
    public static void main(String[] args) {
    
    Receive rec = new Receive();
    
    rec.setSize(460, 200);
    
    }
    
    }

运行结果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/236641.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

node.js express cors解决跨域

目录 什么是跨域 示例 postman请求 前端请求 cors中间件解决跨域 流程 配置cors参数 什么是跨域 跨域(Cross-Origin)是指在 Web 开发中,当一个网页的源(Origin)与另一个网页的源不同时,就发生了跨域…

【USRP】LFTX / LFRX

LFTX/LFRX 设备概述 LFTX 子板利用两个高速运算放大器来允许 0-30 MHz 的传输。该板仅接受实模式信号。LFTX 非常适合 HF 频段的应用,或使用外部前端来上变频和放大中间信号的应用。LFTX 的输出可以独立处理,也可以作为单个 I/Q 对进行处理。 主要特征…

Mac 如何删除文件及文件夹?可以尝试使用终端进行删除

MacOS 是 Mac 电脑采用的操作系统,你知道 Mac 如何删除文件吗?除了直接将文件或者文件夹拖入废纸篓之外,我们还可以采用终端命令的办法去删除文件,本文为大家总结了 Mac 删除文件方法。 为何使用命令行删除文件 在使用 Mac 电脑…

无人零售柜:快捷舒适购物体验

无人零售柜:快捷舒适购物体验 通过无人零售柜和人工智能技术,消费者在购物过程中可以自由选择商品,根据个人需求和喜好查询商品清单。这种自主选择的购物环境能够为消费者提供更加舒适和满意的体验。此外,无人零售柜还具有节约时间…

字符统计[c]

#include<stdio.h> #include<string.h> int main() {int a,b,c;abc0;char s[100];int i0;while(1){i;scanf("%c",&s[i]);if(s[i]?)break;}for(int k1;k<i;k){if(s[k]>48&&s[k]<57){a;//数字}else if((s[k]>65&&s[k]<…

我的 CSDN 三周年创作纪念日:2020-12-12

本人大叔一枚&#xff0c;自1992年接触电脑&#xff0c;持续了30年的业余电脑发烧爱好者&#xff0c;2022年CSDN博客之星Top58&#xff0c;阿里云社区“乘风者计划”专家博主。自某不知名财校毕业后进入国有大行工作至今&#xff0c;先后任职于某分行信息科技部、电子银行部、金…

12月11日作业

完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号和密码不匹配&#xf…

Vue 创建一个 Vue 应用

下载安装Node.js Node.Js中文网Node.jsNode.Js中文网 按步骤安装到你想安装的目录即可 安装完毕在控制台输入node 或者node -v测试 将Node.js下载路径改为国内镜像站 npm config set registryhttps://registry.npm.taobao.org/ 查看镜像 npm config get registry 创建项目 …

【C语言】【数据结构】自定义类型:结构体

引言 这是一篇对结构体的详细介绍&#xff0c;这篇文章对结构体声明、结构体的自引用、结构体的初始化、结构体的内存分布和对齐规则、库函数offsetof、以及进行内存对齐的原因、如何修改默认对齐数、结构体传参进行介绍和说明。 ✨ 猪巴戒&#xff1a;个人主页✨ 所属专栏&am…

雨云服务器快速搭建Cloudreve网盘网站并挂载雨云对象存储的教程

雨云服务器快速搭建Cloudreve网盘网站并挂载雨云对象存储的教程。本教程的Cloudreve安装就直接用雨云云服务器的预安装APP功能了&#xff0c;然后安装宝塔面板用于反代&#xff0c;如果不需要域名访问功能也可以直接IP端口来访问。 其他建站教程&#xff1a;https://blog.zeru…

C++——继承

目录&#xff1a; 继承的概念及定义 面向对象的三个基本特征&#xff1a;封装、继承、多态。在前面的讲解中封装已经用的很多了&#xff0c;那么接下来的两篇文章就来介绍一下继承和多态。 继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&am…

记录 | xftp远程连接两台windows

1、打开openssh 设置 -> 应用 -> 可选功能 -> 添加功能 -> OpenSSH 客户端&#xff0c;将 ssh 客户端安装将两台电脑的 ssh 开启&#xff0c;cmd 中输入 net start sshd2、配置 win10 账号密码 3、进行 xftp 连接

SSD在AI发展中的关键作用:从高速缓存到数据湖-1

随着人工智能技术的飞速发展&#xff0c;存储在其中发挥着至关重要的作用。特别是在AI训练过程中&#xff0c;存储SSD&#xff08;固态硬盘&#xff09;的高性能和可靠性对于提升训练效率和保证数据安全具有不可替代的作用。 存储SSD在AI发展中的作用和趋势&#xff0c;存储将…

自动化测试之读取配置文件

前言&#xff1a; 在日常自动化测试开发工作中&#xff0c;经常要使用配置文件&#xff0c;进行环境配置&#xff0c;或进行数据驱动等。我们常常把这些文件放置在 resources 目录下&#xff0c;然后通过 getResource、ClassLoader.getResource 和 getResourceAsStream() 等方法…

Spring框架学习:Bean生命周期

目录 SpringBean的生命周期 Bean实例属性填充 三级缓存 常用的Aware接口 Spring IoC容器实例化Bean总结 SpringBean的生命周期 Spring Bean的生命周期是从 Bean 实例化之后&#xff0c;即通过反射创建出对象之后&#xff0c;到Bean成为一个完整对象&#xff0c;最终存储到…

[足式机器人]Part2 Dr. CAN学习笔记-自动控制原理Ch1-3燃烧卡路里-系统分析实例

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记-自动控制原理Ch1-3燃烧卡路里-系统分析实例 1. 数学模型2. 比例控制 Proprotional Control 1. 数学模型 2. 比例控制 Proprotional Control

<JavaEE> 经典设计模式之 -- 单例模式(“饿汉模式”和“懒汉模式”实现单例模式)

目录 一、单例模式概述 二、“饿汉模式”实现单例模式 三、“懒汉模式”实现单例模式 3.1 单线程下的“懒汉模式” 3.2 多线程下的“懒汉模式” 一、单例模式概述 1&#xff09;什么是单例模式&#xff1f; 单例模式是一种设计模式。 单例模式可以保证某个类在程序中只存…

Leetcode 40 组合总和 II

题意理解&#xff1a; 每个数字在每个组合中只能使用 一次 数字可以重复——>难点&#xff08;如何去重&#xff09; 每个组合和target 求组合&#xff0c;对合限制&#xff0c;考虑回溯的方法。——将其抽象为树结构。 树的宽度——分支大小 树的深度——最…

分配栈空间的三种方式(基于适配qemu的FreeRTOS分析)

1、定义全局的数组 定义的全局数组属于bss段&#xff0c;相当于把bss段的一部分作为栈空间&#xff0c;栈空间的大小就是数组的大小如果把栈空间放在bss段&#xff0c;则在bss段清零时会多清零一段地址空间 2、在链接脚本中指定 用链接脚本在所有段的后面增加stack段&#xff…

Altair Radioss碰撞 安全与冲击 衡祖仿真

Altair Radioss是解决瞬态加载工况下非线性问题的领先的结构分析求解器。其具备高扩展性、高品质、高鲁棒性&#xff0c;以及诸多功能&#xff1a;多域求解技术、高级材料功能(复合材料)等。Radioss求解器被广泛应用于汽车、航空航天、电子/家电、包装、轨道机车、生物医疗、能…