第二十一章网络通信总结博客

局域网与互联网

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

网络协议
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等多种服务,那么客户机会通过不同的端口来确定连接到服务器的哪项服务上,如图所示。

TCP程序

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

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

运行结果如下; 

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

 
 
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

 

 运行结果如下;

 

 

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地址的情况。
 

 例题21.3

 
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

结果如下; 

 

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

 
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/226567.html

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

相关文章

对Spring源码的学习:一

目录 BeanFactory开发流程 ApplicationContext BeanFactory与ApplicationContext对比 基于XML方式的Bean的配置 自动装配 BeanFactory开发流程 这里的第三方指的是Spring提供的BeanFactory,Spring启动时会初始化BeanFactory,然后读取配置清单&#…

力扣每日一题:1466. 重新规划路线(2023-12-07)

力扣每日一题 题目:1466. 重新规划路线 日期:2023-12-07 用时:45 m 36 s 时间:37ms 内存:69.64MB 代码: class Solution {public int minReorder(int n, int[][] connections) {list new List[n];Arrays…

IPTABLES(一)

文章目录 1. iptables基本介绍1.1 什么是防火墙1.2 防火墙种类1.3 iptables介绍1.4 包过滤防火墙1.5 包过滤防火墙如何实现 2. iptables链的概念2.1 什么是链2.2 iptables有哪些链 3. iptables表的概念3.1 什么是表3.2 表的功能3.3 表与链的关系 4. iptables规则管理4.1 什么是…

Shell数组函数:数组——数组和循环(二)

for脚本快速定义数组 [rootlocalhost ~]# vim for12.sh #脚本编辑 #!/bin/bash for a in cat /etc/hosts do hosts[o]$a donefor i in ${!hosts[]} do echo "$i : ${hosts[$a]}" done[rootlocalhost ~]# vim for12.sh #执行脚本区别 :for的空格分割…

coredump

linux原生 一、设置 $ cat /proc/sys/kernel/core_pattern 通过查看core_pattern文件,发现其确实指定了一个路径,于是我前往那个路径,发现竟然是脚本程序,后来查看说明文件,才知道core_pattern中如果首先指定了一个 …

docker 可视化工具操作说明 portainer

官网地址 https://docs.portainer.io/start/install-ce/server/docker/linux 1.First, create the volume that Port docker volume create portainer_data2.下载并安装容器 docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restartalways -v /var/run/docker…

前端:让一个div悬浮在另一个div之上

使用 CSS 的 position 属性和 z-index 属性 首先,将第二个 div 元素的 position 属性设为 relative 或 absolute。这样可以让该元素成为一个定位元素,使得后代元素可以相对于它进行定位。 然后,将要悬浮的 div 元素的 position 属性设为 ab…

DOS 批处理 (二)

DOS 批处理 1. 基础 DOS 命令1.1 基础命令1.2 文件系统操作1.3 文件夹管理1.4 文件管理1.5 网络相关1.6 系统管理1.7 IF、FOR和NETIFFORNET 1. 基础 DOS 命令 command /? 查找帮助DOS命令不区分命令字母的大小写 C:\Users\Administrator>echo 1 1 C:\Users\Administrator…

SQL面试题,判断if的实战应用

有如下表,请对这张表显示那些学生的成绩为及格,那些为不及格 1、创建表,插入数据 CREATE TABLE chapter8 (id VARCHAR(255) NULL,name VARCHAR(255) NULL,class VARCHAR(255) NULL,score VARCHAR(255) NULL );INSERT INTO chapter8 (id, n…

嵌入式系统

嵌入式系统 目前国内一个普遍认同的嵌入式系统定义是:以应用为中心、以计算机技术为基础,软件硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。(引用自《嵌入式系统设计师教程》) …

点评项目——商户查询缓存

2023.12.7 redis实现商户查询缓存 在企业开发中,用户的访问量动辄成百上千万,如果没有缓存机制,数据库将承受很大的压力。本章我们使用redis来实现商户查询缓存。 原来的操作是根据商铺id直接从数据库查询商铺信息,为了防止频繁地…

一维相位解包裹

一维相位解包裹 本文首先介绍最简单的一维的位相解包裹算法。设W是包裹运算符,中是解包裹位相,是包裹的位相。则一维位相解包裹可表示为: 解包裹就是要选取正确的k,满足: 两个相邻像素位相的差值如下: 由式(2-1)和式(2…

JOSEF快速中间继电器DZK-916 4A AC220V板后嵌入式安装

系列型号 DZK-911快速中间继电器;DZK-912快速中间继电器; DZK-914快速中间继电器;DZK-916快速中间继电器; DZK-917快速中间继电器;DZK-918快速中间继电器; DZK-924快速中间继电器;DZK-934快速中…

德国进口高速主轴电机在机器人上的应用及选型方案

随着机器人技术的日新月异,高速主轴电机在机器人领域的应用也日趋广泛。德国进口的SycoTec高速主轴电机,以其高转速、高精度、高刚度的特点,在机器人的切割、铣削、钻孔、去毛刺等加工应用中发挥着关键作用。 一、高速主轴电机的特点 SycoT…

【项目问题解决】IDEA2020.3 使用 lombok 插件 java: 找不到符号 符号: 方法 builder()

目录 lombok找不到符号问题修改 1.问题描述2.问题原因3.解决思路4.解决方案5.总结6.参考 文章所属专区 项目问题解决 1.问题描述 IDEA2020.3 使用 lombok 插件 java: 找不到符号 符号: 方法 builder(),无法使用lombok下应有的注解,一度怀疑是版本问题 …

什么是SPA(Single Page Application)?它的优点和缺点是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

JVM理解

1、JVM是什么? JVM是Java Virtual Machine(Java虚拟机)的缩写,由一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域等组成。 他是帮助我们将java代码 生成编译后 的 class 文件。 2、JRE、JDK和JVM 的关系 …

【文件上传系列】No.0 利用 FormData 实现文件上传、监控网路速度和上传进度(原生前端,Koa 后端)

利用 FormData 实现文件上传 基础功能:上传文件 演示如下: 概括流程: 前端:把文件数据获取并 append 到 FormData 对象中后端:通过 ctx.request.files 对象拿到二进制数据,获得 node 暂存的文件路径 前端…

【STM32】TIM定时器输入捕获

1 输入捕获 1.1 输入捕获简介 IC(Input Capture)输入捕获 输入捕获模式下,当通道输入引脚出现指定电平跳变时(上升沿/下降沿),当前CNT的值将被锁存到CCR中(把CNT的值读出来,写入到…

【链表Linked List】力扣-109 有序链表转换二叉搜索树

目录 题目描述 解题过程 官方题解 题目描述 给定一个单链表的头节点 head ,其中的元素 按升序排序 ,将其转换为高度平衡的二叉搜索树。 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差不超过 1。 示例 1: 输…