第21章:网络通信

 21.1  网络程序设计基础

21.1.1  局域网与互联网

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

21.1.2  网络协议

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协议即使有一小部分数据包遗失或传送顺序有所不同,也不会严重危害该项通信。
 

21.1.3  端口与套接字

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

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

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

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

21.2 TCP程序 

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

 

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

21.2.1 InetAddress 类

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

例21.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

 结果为:

21.2.2  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所示。

 21.2.3  TCP网络程序设计

例题21.2

 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

结果为:

 

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

 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

 结果为:

21.3  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包。


21.3.1DatagramPacket类

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

DatagramPacket(byte[] buf, int length)
DatagramPacket(bytel] buf, int length, InetAddress address, int port)
第一种构造方法在创建DatagramPacket 对象时,指定了数据包的内存空间和大小。

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

21.3.2 DatagramSocker 类

java.net 包中的()
DatagramSocket(int port)
DatagramSocket(int port, InetAddress addr)
第一种构造方法创建DatagramSocket对象,构造数据报套接字,并将其绑定到本地主机任何可用的端口上。

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

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

21.3.3 UDP网络程序设计

例题21.3

(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)接收广播程序。单机“开始接收”按钮,系统开始接收主机播出的信息;单机“停止接收”按钮,系统停止接收广播主机播出的信息。代码如下:

 
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(); // 创建面板对象centercenter.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);}
}

结果为:

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【教程】逻辑回归怎么做多分类

目录 一、逻辑回归模型介绍 1.1 逻辑回归模型简介 1.2 逻辑回归二分类模型 1.3 逻辑回归多分类模型 二、如何实现逻辑回归二分类 2.1 逻辑回归二分类例子 2.2 逻辑回归二分类实现代码 三、如何实现一个逻辑回归多分类 3.1 逻辑回归多分类问题 3.1 逻辑回归多分类的代…

用Rust刷LeetCode之66 加一

66. 加一[1] 难度: 简单 func plusOne(digits []int) []int { length : len(digits) // 从最低位开始遍历&#xff0c;逐位加一 for i : length - 1; i > 0; i-- { if digits[i] < 9 { digits[i] return digits } d…

经验分享|MySQL分区实战(RANGE)

概述 分区概述 在 MySQL 中&#xff0c; InnoDB存储引擎长期以来一直支持表空间的概念。在 MySQL 8.0 中&#xff0c;同一个分区表的所有分区必须使用相同的存储引擎。但是&#xff0c;也可以为同一 MySQL 服务器甚至同一数据库中的不同分区表使用不同的存储引擎。 通俗地讲…

家电制造数字孪生5G智能工厂可视化系统,加速家电制造产业数字化转型

5G数字孪生、三维可视化与工业互联网的融合加速中国新型工业化进程&#xff0c;助推我国从制造大国迈进制造强国。家电行业是中国最具国际竞争力的产业之一&#xff0c;在企业数字化转型中&#xff0c;要求企业从生产设备到数字化系统&#xff0c;一系列的数字化、智能化改革已…

Linux指令学习

目录 1.ls指令 2.pwd命令 3.cd 指令 4. touch指令 5.mkdir指令 6.rmdir指令 && rm 指令 7.man指令 8.cp指令 9.mv指令 10.cat指令 11.more指令 12.less指令 13.head指令 14.find指令&#xff1a; -name 15.grep指令 16.zip/unzip指令&#xff1a; 17.tar…

【ARM Trace32(劳特巴赫) 使用介绍 12 -- Trace32 常用命令之 d.dump | data.dump 介绍】

请阅读【ARM Coresight SoC-400/SoC-600 专栏导读】 文章目录 Trace32 常用命令之 d.dump | data.dump 介绍1 字节显示 (Byte)4 字节显示&#xff08;word&#xff09;8 字节显示&#xff08;通常long&#xff09;十进制显示显示指定列数显示地址范围内的值不经过MMUnon-cache …

TwinCAT3 Modbus-TCP Client/Server使用

目录 一、环境配置和准备 1、PLC中安装TF6250-Modbus-TCP库 2、勾选TF6250的license 3、PLC工程中添加Tc2_ModbusSrv库文件 4、分别创建测试ModbusTCP测试的Server和Client程序 二、PLC作为Client端 1、设置测试电脑IP地址 2、运行MobusTCP测试工具 3、PLC端程序编写 …

报错处理集

这个报错处理集的错误来源于编译arm平台的so文件产生的。但是后续可以补充成linux一个大的错误处理集。 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 第一次整理的时间是2023年12月8日10:05:59&#xff0c;以下错误来源于欧拉系统编译…

LoadBalancer将服务暴露到外部实现负载均衡Openelb-layer2模式配置介绍

目录 一.openelb简介 二.主要介绍layer2模式 1.简介 2.原理 3.部署 &#xff08;1&#xff09;先在集群master上开启kube-proxy的strictARP &#xff08;2&#xff09;应用下载openelb.yaml&#xff08;需要修改镜像地址&#xff09; &#xff08;3&#xff09;编写yam…

字节跳动面试挂在2面,复盘后,决定二战.....

先说下我基本情况&#xff0c;本科不是计算机专业&#xff0c;现在是学通信&#xff0c;然后做图像处理&#xff0c;可能面试官看我不是科班出身没有问太多计算机相关的问题&#xff0c;因为第一次找工作&#xff0c;字节的游戏专场又是最早开始的&#xff0c;就投递了&#xf…

dockerfile简单实践部署(jenkins,wordpress)

实现部署jenkins的流程 配置java环境&#xff0c;导入jenkins包&#xff0c;运行命令 java -jar jenkins包&#xff0c;这里为了减少进入jenkins的web端安装插件&#xff0c;将插件提前部署到容器内。 制作dockerfile 创建镜像所在的文件夹和Dockerfile文件 mkdir /test cd …

岳阳楼3D模型纹理贴图

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 岳阳楼&#xff0c;位于湖南省岳阳市岳阳楼区洞庭北路&#xff0c;地…

会声会影2024软件还包含了视频教学以及模板素材

会声会影2024中文版是一款加拿大公司Corel发布的视频编软件。会声会影2024官方版支持视频合并、剪辑、屏幕录制、光盘制作、添加特效、字幕和配音等功能&#xff0c;用户可以快速上手。会声会影2024软件还包含了视频教学以及模板素材&#xff0c;让用户剪辑视频更加的轻松。 会…

使用高防IP防护有哪些优势

高防IP是针对互联网服务器在遭受大流量的DDoS攻击后导致服务不可用的情况下&#xff0c;推出的付费增值服务&#xff0c;用户可以通过配置高防IP&#xff0c;将攻击流量引流到高防IP&#xff0c;确保源站的稳定可靠。高防IP相当于搭建完转发的服务器。 高防IP有两种接入方式&a…

CodeBlocks添加头文件,解决fatal error: ui.h No such file or directory

问题描述 在使用codeblocks工具进行LVGL仿真过程中报错&#xff0c;找不到头文件 原因分析&#xff1a; 没有将头文件加入编辑器搜索的目录中&#xff0c;编译时找不到头文件。 解决方案&#xff1a; 将要包含的头文件的目录加进去就可以了

kyuubi整合flink yarn application model

目录 概述配置flink 配置kyuubi 配置kyuubi-defaults.confkyuubi-env.shhive 验证启动kyuubibeeline 连接使用hive catalogsql测试 结束 概述 flink 版本 1.17.1、kyuubi 1.8.0、hive 3.1.3、paimon 0.5 整合过程中&#xff0c;需要注意对应的版本。 注意以上版本 姊妹篇 k…

06、pytest将多个测试放在一个类中

官方用例 # content of test_class.py # 实例1 class TestClass:def test_one(self):x "this"assert "h" in xdef test_two(self):x "hello"assert hasattr(x,"check")# content of test_class_demo.py # 每个测试都有唯一的类实例…

GaussDB数据库语法及gsql入门

一、GaussDB数据库语法入门 之前我们讲了如何连接数据库实例&#xff0c;那连接数据库后如何使用数据库呢&#xff1f;那么我们今天就带大家了解一下GaussDB&#xff0c;以下简称GaussDB的基本语法。 关于如何连接数据库&#xff0c;请戳这里。 学习本节课程之后&#xff0c…

python画立体玫瑰图

1.源代码 from matplotlib import cm import matplotlib.pyplot as plt import numpy as npfig plt.figure()#显示绘图窗口 ax fig.add_subplot(projection 3d)#绘图窗口设置 [x, t] np.meshgrid(np.array(range(25))/24.0, np.arange(0, 575.5, 0.5)/575*17*np.pi-2*np.pi…

玩转代码|组件封装之Slots、Emit和Props穿透

目录 背景 准备工作 Slots穿透方案-单子组件 Slots穿透方案-多子组件 Props和Emit穿透方案-单子组件 Props和Emit穿透方案-多子组件 最后 背景 组内多人共同开发时免不了基于某UI库二次封装组件来适应项目业务场景的情况&#xff0c;但不知道大家有没有遇到过需要兼容部…