二十一章(网络通信)

news2024/11/23 20:10:13

计算机网络实现了多台计算机间的互联,使得它们彼此之间能够进行数据交流。网络应用程序就是在已连接的不同计算机上运行的程序,这些程序借助于网络协议,相互之间可以交换数据。编写网络应用程序前,首先必须明确所要使用的网络协议。TCP/IP协议是网络应用程序的首选

一.网络程序设计基础\

网络程序设计编写的是与其他计算机进行通信的程序。Java已经将网络程序所需要的元素封装成不同的类,用户只要创建这些类的对象,使用相应的方法,即使不具备有关的网络知识,也可以编写出高质量的网络通信程序。

1.局域网与互联网

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

服务器是指提供信息的计算机或程序,客户机是指请求信息的计算机或程序。网络用于连接服务器与客户机,实现两者间的相互通信。但是,有时在某个网络中很难将服务器与客户机区分开。我们通常所说的局域网(Local Area Network,LAN),就是一群通过一定形式连接起来的计算机,它可以由两台计算机组成,也可以由同一区域内的上千台计算机组成。将LAN延伸到更大的范围,这样的网络称为广域网(Wide Area Network,WAN)。我们熟悉的互联网(Internet),就是由无数的LAN和WAN组成的。
 

2.网络协议

网络协议规定了计算机之间连接的物理、机械(网线与网卡的连接规定)、电气(有效的电平范围)等特征,计算机之间的相互寻址规则,数据发送冲突的解决方式,长数据如何分段传送与接收等内容。就像不同的国家有不同的法律一样,目前网络协议也有多种。下面简单地介绍几个常用的网络协议。

1.IP协议

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

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

2.TCP与UDP协议

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

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

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

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

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

注意

一些防火墙和路由器会设置成不允许UDP数据包传输,因此若遇到UDP连接方面的问题,应先确定所在网络是否允许UDP协议

3.端口与套接字

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

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

网络程序中的套接字(Socket)用于将应用程序与端口连接起来。套接字是一个假想的连接装置,就像插座一样可连接电器与电线,如图21.4所示。Java将套接字抽象化为类,程序设计者只需创建Socket类对象,即可使用套接字。

二.TCP程序

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

1.InetAddress类

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

 

 使用InetAddress类的getHostName()和getHostAddress()方法获得本地主机的本机名、本机IP地址。

package wanluo;

import java.net.*;	//导入Java.net包

public class Address {//创建类

	public static void main(String[] args) {
		InetAddress ip;//创建InetAddress对象
		try {//捕捉可能出现的异常	
			ip = InetAddress.getLocalHost();//实例化对象
			String IocaIname = ip.getHostName();//获取本机名
			String Iocalip = ip.getHostAddress();//获取本机IP地址
			System.out.println("本机名:" + IocaIname);//将本机名输出
			System.out.println("本机IP地址:" + Iocalip);//将本机IP地址输出
		}catch(UnknownHostException e) {
			e.printStackTrace();//输出异常信息
		}
	}
}

结果如下

2.ServerSocket类

java.net包中的ServerSocket类用于表示服务器套接字,其主要功能是等待来自网络上的“请求”,它可通过指定的端口来等待连接的套接字。服务器套接字一次可以与一个套接字连接。如果多台客户机同时提出连接请求,服务器套接字会将请求连接的客户机存入列队中,然后从中取出一个套接字,与服务器新建的套接字连接起来。若请求连接数大于最大容纳数,则多出的连接请求被拒绝。队列的默认大小是50。

ServerSocket类的构造方法通常会抛出IOException异常,具体有以下几种形式:

  1. ServerSocket():创建非绑定服务器套接字。
  2. ServerSocket(int port):创建绑定到特定端口的服务器套接字。
  3. ServerSocket(int port, int backlog):利用指定的backlog创建服务器套接字,并将其绑定到指定的本地端口号上。
  4. ServerSocket(int port, int backlog, InetAddress bindAddress):使用指定的端口、侦听backlog和要绑定到的本地IP地址创建服务器。这种情况适用于计算机上有多块网卡和多个IP地址的情况,用户可以明确规定ServerSocket在哪块网卡或哪个IP地址上等待客户的连接请求。

 

调用ServerSocket类的accept()方法,会返回一个和客户端Socket对象相连接的Socket对象。服务器端的Socket对象使用getOutputStream()方法获得的输出流,将指向客户端Socket对象使用getInputStream()方法获得的那个输入流;同样,服务器端的Socket对象使用getInputStream()方法获得的输入流,将指向客户端Socket对象使用getOutputStream()方法获得的那个输出流。也就是说,当服务器向输出流写入信息时,客户端通过相应的输入流就能读取,反之亦然。

注意

accept()方法会阻塞线程的继续执行,直到接收到客户的呼叫。如果没有客户呼叫服务器,那么System.out.println("连接中")语句将不会执行。语句如果没有客户请求,accept()方法没有发生阻塞,肯定是程序出现了问题。通常是使用了一个被其他程序占用的端口号,ServerSocket绑定没有成功。

yu = server.accept();

System.out.println("连接中");

3.TCP网络程序设计

明白了TCP程序工作的过程,就可以编写TCP服务器程序了。在网络编程中,如果只要求客户机向服务器发送消息,不要求服务器向客户机发送消息,称为单向通信。客户机套接字

和服务器套接字连接成功后,客户机通过输出流发送数据,服务器则通过输入流接收数据。下面是简单的单向通信的实例。

例题21.2:创建TCP/IP协议服务器
package wanluo;

import java.io.*;
import java.net.*;

public class MyServer {
	private ServerSocket server;//服务器套接字
	private Socket socket;//客户机套接字
	
	void start() {//启动服务器
		try {
			server = new ServerSocket(5555);//服务器启用5555端口
			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();//启动服务器
	}

}

结果如下

运行服务器端程序,将输出提示信息,等待客户呼叫。下面再来看一下客户端程序。

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

package wanluo;

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 JFormattedTextField();//发送信息的文本框
		
		public MyClient() {
			setTitle("向服务器送数据");
			setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			Container c = getContentPane();//主容器
			JScrollPane sctollPane = new JScrollPane(area);//滚动面板
			getContentPane().add(sctollPane,BorderLayout.CENTER);
			c.add(text,"South");//将文本框放在窗体的下部
			text.addActionListener(new ActionListener() {//文本框触发回车事件
				@Override
				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",5555);//连接本地计算机的5555端口
				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();
		}
	}

结果如下

说明

当一台机器上安装了多个网络应用程序时,很可能指定的端口号已被占用。还可能遇到以前运行良好的网络程序突然运行不了的情况,这种情况很可能也是由于端口被别的程序占用了。此时可以运行netstat-help来获得帮助,使用netstat-an命令来查看该程序所使用的端口

三.UDP程序

用户数据报协议(UDP)是网络信息传输的另一种形式。基于UDP的通信和基于TCP的通信不同,基于UDP的信息传递更快,但不提供可靠性保证。使用UDP传递数据时,用户无法知道数据能否正确地到达主机,也不能确定到达目的地的顺序是否和发送的顺序相同。虽然UDP是一种不可靠的协议,但如果需要较快地传输信息,并能容忍小的错误,可以考虑使用UDP。

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

  1. 将数据打包(称为数据包),然后将数据包发往目的地。

  2. 接收别人发来的数据包,然后查看数据包。

发送数据包的步骤如下:

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

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

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

接收数据包的步骤如下:

  1. 使用DatagramSocket(int port)创建数据包套接字,绑定到指定的端口。
  2. 使用DatagramPacket(byte[] buf, int length)创建字节数组来接收数据包。
  3. 使用DatagramPacket类的receive()方法接收UDP包。

注意

DatagramSocket类的receive()方法接收数据时,如果还没有可以接收的数据,在正常情况下receive()方法将阻塞,一直等到网络上有数据传来,receive()方法接收该数据并返回。如果网络上没有数据发送过来,receive()方法也没有阻塞,肯定是程序有问题,大多数情况下是因为使用了一个被其他程序占用的端口号。
 

1.DatagramPacket类

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

DatagramPacket(byte[] buf, int length)。
DatagramPacket(byte[] buf, int length, InetAddress address, int port)。
第一种构造方法在创建DatagramPacket对象时,指定了数据包的内存空间和大小。第二种构造方法不仅指定了数据包的内存空间和大小,还指定了数据包的目标地址和端口。在发

送数据时,必须指定接收方的Socket地址和端口号,因此使用第二种构造方法可创建发送数据的DatagramPacket对象。

2.DatagramSocket类

java.net包中的DatagramSocket类用于表示发送和接收数据包的套接字。该类的构造方法如下:

  1. DatagramSocket()。
  2. DatagramSocket(int port)。
  3. DatagramSocket(int port, InetAddress addr)。

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

如果接收数据时必须指定一个端口号,不允许系统随机产生,此时可以使用第二种构造方法。比如有个朋友要你给他写信,那他的地址就必须确定,不确定是不行的。在发送数据时通常使用第一种构造方法,不指定端口号,而是系统为我们分配一个端口号,就像寄信不需要到指定的邮局去寄一样。

3.UDP网络程序设计

根据前面所讲的网络编程的基本知识以及UDP网络编程的特点,下面创建一个广播数据报程序。广播数据报是一项较新的技术,其原理类似于电台广播。广播电台需要在指定的波段和频率上广播信息,收听者也要将收音机调到指定的波段、频率,才可以收听广播内容。

例题21.3:创建UDP协议广播电台程序

package wanluo;

import java.io.IOException;
import java.net.*;

public class Notification extends Thread{
	String weather = "节日预报:八点有大型晚会,请收听";//发送的消息
	int port = 9898;//端口
	InetAddress iaddress = null;
	MulticastSocket socket = null;//多点广播套接字
	
	
	@SuppressWarnings("deprecation")
	Notification(){
		try {
			iaddress = InetAddress.getByName("224.255.10.0");//广播组地址
			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();//启动线程
	}
}

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

package wanluo;


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();
		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);//将接收内容显示在文本域中
				inceAr.append(message + "\n");//每条信息为一行
			}catch(IOException e){
				e.printStackTrace();//输出异常信息
			}
		}
	}
	
	public void actionPerformed(ActionEvent e) {//单击按钮ince触发的事件
		if(e.getSource() == inceBtn) {
			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);//设置按钮颜色
			inceBtn.setBackground(Color.red);
			stop = true;//停止接收信息
		}
	}
	public static void main(String[] args) {
		Receive rec = new Receive();
		rec.setSize(460,200);
	}

}

结果如下

 

说明

发出广播和接收广播的主机地址必须位于同一个组内,地址范围为224.0.0.0~224.255.255.255,该地址并不代表某个特定主机的位置。加入同一个组的主机可以在某个端口上广播信息,也可以在某个端口上接收信息。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

hive映射es表任务失败,无错误日志一直报Task Transitioned from NEW to SCHEDULED

一、背景 要利用gpt产生的存放在es种的日志表做统计分析,通过hive建es的映射表,将es的数据拉到hive里面。 在最初的时候同事写的是全量拉取,某一天突然任务报错,但是没有错误日志一直报:Task Transitioned from NEW t…

MySQL数据库从小白到入门(二)

多表关系: 项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构。由于业务之间相互关联,所以各个表结构之间也存在着各种联系,基本上分为三种。 外键: 创…

JavaSE基础50题:11. 输出一个整数的每一位

概述 输出一个整数的每一位。 如:1234的每一位是4,3,2,1 。 个位:1234 % 10 4 十位:1234 / 10 123 123 % 10 3 百位:123 / 10 12 12 % 10 2 千位: 12 / 10 1 代码 ublic sta…

LinuxBasicsForHackers笔记 -- 管理用户环境变量

查看和修改环境变量 env – 您可以通过从任何目录在终端中输入 env 来查看所有默认环境变量。环境变量的名称始终为大写,如 HOME、PATH、SHELL 等。 查看所有环境变量 set – 查看所有环境变量,包括 shell 变量、局部变量和 shell 函数(例…

java学习part40collections工具类

162-集合框架-Collections工具类的使用_哔哩哔哩_bilibili 1.collections工具类 感觉类似c的algorithm包,提供了很多集合的操作方法 2.排序 3.查找 4.复制替换 5.添加,同步

蓝桥杯day03——Bigram 分词

1.题目 给出第一个词 first 和第二个词 second,考虑在某些文本 text 中可能以 "first second third" 形式出现的情况,其中 second 紧随 first 出现,third 紧随 second 出现。 对于每种这样的情况,将第三个词 "th…

计数排序(C语言实现)

文章目录 算法思想操作步骤计数排序的特性总结代码实现 算法思想 计数排序是一种非比较排序,又称为鸽巢原理,是对哈希直接定址法的变形应用。 操作步骤 统计相同元素出现次数;根据统计的结果将序列回收到原来的序列中。 计数排序的特性总…

数据库:JDBC编程

专栏目录 MySQL基本操作-CSDN博客 MySQL基本操作-CSDN博客 数据库的增删查改(CRUD)基础版-CSDN博客 数据库增删改查(CRUD)进阶版-CSDN博客 数据库的索引-CSDN博客 基本概念 JDBC编程就是通过Java代码来操作数据库 api 数据库是…

基于 Flink CDC 构建 MySQL 的 Streaming ETL to MySQL

简介 CDC 的全称是 Change Data Capture ,在广义的概念上,只要是能捕获数据变更的技术,我们都可以称之为 CDC 。目前通常描述的 CDC 技术主要面向数据库的变更,是一种用于捕获数据库中数据变更的技术。CDC 技术的应用场景非常广泛…

【学习记录】从0开始的Linux学习之旅——字符型设备驱动及应用

一、概述 Linux操作系统通常是基于Linux内核,并结合GNU项目中的工具和应用程序而成。Linux操作系统支持多用户、多任务和多线程,具有强大的网络功能和良好的兼容性。基于前面应用与驱动的开发学习,本文主要讲述如何在linux系统上把应用与驱动…

随笔-这都是命吗

我与鹏哥、小付有个小群,前几天,鹏哥在群里发了一个图,是他那个城市准备扶持的高新产业,有元宇宙、量子信息、生物制药、人工智能什么的。 先前的时候鹏哥给我说过,当地准备了六百多亩地,准备发展高新产业…

Labelme2Yolo labelme格式的json标注转yolo格式txt

该工作适用于目标检测工作。 由于labelme标注出的文件是如下图的单个json文件格式,不符合yolo的训练格式,需要转格式。 观察发现labelme标注的json文件中有imageData,还挺大的,查阅后得知是base64后的图片数据,也就是…

多表操作、其他字段和字段参数、django与ajax(回顾)

多表操作 1 基于对象的跨表查 子查询----》执行了两句sql,没有连表操作 2 基于双下滑线的连表查 一次查询,连表操作 3 正向和反向 放在ForeignKey,OneToOneField,ManyToManyField的-related_namebooks:双下滑线连表查询,反向…

深圳锐杰金融:用金融力量守护社区健康

深圳市锐杰金融投资有限公司,作为中国经济特区的中流砥柱,近年来以其杰出的金融成绩和坚定的社会责任立场引人注目。然而,这并非一个寻常的金融机构。锐杰金融正在用自己的方式诠释企业责任和慈善精神,通过一系列独特的慈善项目&a…

定兴县第三实验小学开展“宪法宣传周”系列活动

2023年12月4日是我国第十个国家宪法日,我校集中深入学习宣传宪法,弘扬宪法精神,维护宪法权威,开展“宪法宣传周”系列活动。 宪法主题升旗仪式 五(6)班薛谨熙同学以《学法懂法 与我同行》为主题做国旗下讲…

【开源】基于JAVA语言的APK检测管理系统

项目编号: S 038 ,文末获取源码。 \color{red}{项目编号:S038,文末获取源码。} 项目编号:S038,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 开放平台模块2.3 软…

低代码你需要了解一下

低代码的概念可以追溯到1980年代,当时IBM的快速应用程序开发工具(RAD)被冠以新的名称——低代码,由此,低代码的概念首次面向大众。然而,在近40年的历程中,低代码发展经历了两个阶段:…

Ray构建GPU隔离的机器学习平台

Ray框架介绍 Ray 是一个开源分布式计算框架,在 机器学习基础设施中发挥着至关重要的作用。Ray 促进分布式机器学习训练,使机器学习从业者能够有效利用多个 GPU 的能力。 Ray可以在集群上分布式地运行任务,并且可以指定任务运行时需要使用的GPU数量。Ray可与Nvidia-docker等…

Adobe系列软件:创意之旅的得力助手

在数字创意领域,Adobe系列软件一直以其卓越的性能和广泛的应用而备受瞩目。从图像处理、视频编辑到音频编辑,从网页开发到排版设计,这些软件都提供了强大的功能和工具,帮助用户实现他们的创意。 让我们详细介绍这些软件的作用&…