Java网络套接字

在Java的开发中,有一个很重要!很重要!很重要!的东西,叫做网络套接字,它被广泛的用来二次开发服务,比如大数据中台的服务链路调用等。

它的实现原理是依靠三次握手来完成通信的建立,也是TCP(传输控制协议)连接建立过程中的一个重要机制。TCP是一种可靠的、面向连接的传输层协议,它在正式传输数据之前,需要通过三次握手来建立一个可靠的连接。这个过程涉及到客户端和服务器之间的交互,具体步骤如下:、
第一次握手:客户端向服务器发送一个SYN(同步序列编号)报文段,请求建立连接。这个报文段中,SYN标志位被设置为1,同时客户端会随机生成一个初始序列号(seq)作为自己的起始序号,并将其发送给服务器。此时,客户端进入SYN_SEND状态,等待服务器的确认。

第二次握手:服务器收到客户端的SYN报文段后,会回复一个SYN-ACK(同步-确认)报文段给客户端。在这个报文段中,SYN和ACK标志位都被设置为1,表示服务器同意建立连接,并同步自己的序列号。同时,服务器会确认客户端的序列号,即在ACK字段中填写客户端的序列号加1(作为确认号ack)。此时,服务器进入SYN_RCVD状态。

第三次握手:客户端收到服务器的SYN-ACK报文段后,会发送一个ACK(确认序列编号)报文段给服务器,以确认连接建立。在这个报文段中,ACK标志位被设置为1,同时确认号ack为服务器的序列号加1。此时,客户端和服务器都进入ESTABLISHED状态,表示连接已经成功建立,可以开始传输数据了。

三次握手的目的和意义在于:
确保双方通信能力正常:通过三次握手,客户端和服务器可以相互确认对方的发送和接收能力是否正常,从而确保连接的可靠性。
同步双方初始序列号:在三次握手过程中,双方会交换并确认各自的初始序列号,这是为了后续数据传输时能够正确地进行序号匹配和确认。
防止已失效的连接请求:三次握手还可以防止因网络延迟或丢包等原因导致的已失效的连接请求被错误地接受。

总的来说,三次握手是TCP连接建立过程中的一个关键步骤,它确保了连接的可靠性和双方通信能力的正常性。在开发Java网络套接字时,理解并掌握三次握手的原理和实现方式是非常重要的。


涉及到的类都在java.net包下,如果你是刚接触套接字,你可以用下面这个最简单的案例来感受一下套接字的能力

首先准备一个服务端:

package one;import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;/*** 作者: wangyang <br/>* 创建时间: 2025/1/2 <br/>* 描述: 网络套接字的服务端,用来处理所有客户端的链接请求 <br/>* &nbsp;&nbsp;&nbsp;&nbsp;ServerSoc*/
public class ServerSoc {public static void main(String[] args) {try {ServerSocket ss = new ServerSocket(9000);System.out.println("等待连接。。。。。");//accept方法会阻塞进程,检测到有客户端连接则放行Socket s1 = ss.accept();System.out.println("连接成功");//向客户端输出一句话,因此这里获取对客户端的输出流OutputStream os = s1.getOutputStream(); //获得输出流byte[] b = "客户端,客户端,我是服务器,收到请回答".getBytes();os.write(b);os.flush();//必须刷一下,不然写不进去//关闭资源os.close();s1.close(); ss.close();//关闭自己} catch (IOException e) {e.printStackTrace();}}}

然后是客户端:

package one;import java.io.InputStream;
import java.net.Socket;/*** 作者: wangyang <br/>* 创建时间: 2025/1/2 <br/>* 描述: 网络套接字的客户端,用来链接服务端,面向用户操作 <br/>* &nbsp;&nbsp;&nbsp;&nbsp;ClientSoc*/
public class ClientSoc {public static void main(String[] args) {try {Socket s = new Socket("127.0.0.1", 9000);//客户端要读取服务端的信息,所以这里获取连接中的输入流InputStream is = s.getInputStream();byte[] b = new byte[100];//读取int num = is.read(b);String msg = new String(b, 0, num);System.out.println(msg);//关资源is.close();s.close();} catch (Exception e) {e.printStackTrace();}}}

启动的时候,要先启动服务端,然后在启动客户端,你就可以看到如下的输出
在这里插入图片描述
在这里插入图片描述


同样的,客户端也可以在接收完信息后,给服务端也写一句话,你只需要在上面的代码中加上各自的输入和输出流即可

服务端:

package one;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;/*** 作者: wangyang <br/>* 创建时间: 2025/1/2 <br/>* 描述: 网络套接字的服务端,用来处理所有客户端的链接请求 <br/>* &nbsp;&nbsp;&nbsp;&nbsp;ServerSoc*/
public class ServerSoc {public static void main(String[] args) {try {ServerSocket ss = new ServerSocket(9000);System.out.println("等待连接。。。。。");//accept方法会阻塞进程,检测到有客户端连接则放行Socket s1 = ss.accept();System.out.println("连接成功");//向客户端输出一句话,因此这里获取对客户端的输出流OutputStream os = s1.getOutputStream(); //获得输出流byte[] b = "客户端,客户端,我是服务器,收到请回答".getBytes();os.write(b);os.flush();//必须刷一下,不然写不进去/*服务端这里多了从客户端读消息的输入流也就是上面的代码向客户端写一句话之后服务端从连接的客户端中获取输入流从而等待客户端给服务端发送的信息*/InputStream in = s1.getInputStream();byte[] b1 = new byte[100];int read = in.read(b1);String msg = new String(b1, 0, read);System.out.println(msg);//关闭资源in.close();os.close();s1.close();ss.close();} catch (IOException e) {e.printStackTrace();}}}

客户端:

package one;import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;/*** 作者: wangyang <br/>* 创建时间: 2025/1/2 <br/>* 描述: 网络套接字的客户端,用来链接服务端,面向用户操作 <br/>* &nbsp;&nbsp;&nbsp;&nbsp;ClientSoc*/
public class ClientSoc {public static void main(String[] args) {try {Socket s = new Socket("127.0.0.1", 9000);//客户端要读取服务端的信息,所以这里获取连接中的输入流InputStream is = s.getInputStream();byte[] b = new byte[100];//读取int num = is.read(b);String msg = new String(b, 0, num);System.out.println(msg);/*客户端这里在接收完服务端的信息后向服务端写入一条信息*/OutputStream out = s.getOutputStream();byte[] b1 = "服务器,服务器,我是客户端,收到请回答".getBytes();out.write(b1);out.flush();//必须刷一下,不然写不进去//关资源out.close();is.close();s.close();} catch (Exception e) {e.printStackTrace();}}}

同样的,先启动服务端,然后启动客户端连接,就会得到如下输出
在这里插入图片描述
在这里插入图片描述

上面这两个案例,可以让你很方便的了解到Java提供的网络套接字能力,当然这不是全部,你还可以获取客户端的ip等等,这些都可以办到。但是上面的案例中有着写入顺序的限制,也就是无论那边都不能同时先发信息或接受,不然流就拥堵了


那么怎么能够实现基本的双向通道?来实现一对一正常对话的效果,可以用如下的代码实现

服务端:

package one;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;/*** 作者: wangyang <br/>* 创建时间: 2025/1/2 <br/>* 描述: 网络套接字的服务端,用来处理所有客户端的链接请求 <br/>* &nbsp;&nbsp;&nbsp;&nbsp;ServerSoc*/
public class ServerSoc {public static void main(String[] args) {try {ServerSocket ss = new ServerSocket(9000);System.out.println("等待连接。。。。。");//accept方法会阻塞进程,检测到有客户端连接则放行Socket s1 = ss.accept();System.out.println("连接成功");//获取来自客户端的输入和输出流,向客户端发送与接收信息BufferedReader in = new BufferedReader(new InputStreamReader(s1.getInputStream()));PrintWriter out = new PrintWriter(s1.getOutputStream());Scanner input = new Scanner(System.in);//服务端获取控制台输入的扫描器while(true){//服务端先开始写信息发给客户端String serverMsg = input.nextLine();out.println(serverMsg);out.flush();//发送完消息后,进入等待发消息的状态String clientMsg = in.readLine();System.out.println(clientMsg);}//关闭资源
//            in.close();
//            out.close();
//            s1.close();
//            ss.close();} catch (IOException e) {e.printStackTrace();}}}

客户端:

package one;import java.io.*;
import java.net.Socket;
import java.util.Scanner;/*** 作者: wangyang <br/>* 创建时间: 2025/1/2 <br/>* 描述: 网络套接字的客户端,用来链接服务端,面向用户操作 <br/>* &nbsp;&nbsp;&nbsp;&nbsp;ClientSoc*/
public class ClientSoc {public static void main(String[] args) {try {Socket s = new Socket("127.0.0.1", 9000);//客户端一样,获取服务端的输入和输出流,向服务端端发送与接收信息BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));PrintWriter out = new PrintWriter(s.getOutputStream());Scanner input = new Scanner(System.in);//服务端获取控制台输入的扫描器while(true){//等待服务端发来的消息String serverMsg = in.readLine();System.out.println(serverMsg);//接收完消息,进入向服务端写数据的状态String clientMsg = input.nextLine();out.println(clientMsg);out.flush();}//关资源
//            out.close();
//            in.close();
//            s.close();} catch (Exception e) {e.printStackTrace();}}}

启动还是一样的顺序,先器服务端,并先由服务端发送消息
在这里插入图片描述
在这里插入图片描述


上面的案例,虽然初步的让服务端和客户端都能发送和接收消息,但是很明显,仍然没有摆脱需要有一方先写,不能一起先写的限制,而且还是只能一句一句的来,因为用的是死循环,当然至于那一方先写是你自己决定的。那么怎么能够彻底摆脱这个问题,这就要用到多线程了,你可以把接收信息的流程放在子线程里面,如下

服务端:

package one;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;/*** 作者: wangyang <br/>* 创建时间: 2025/1/2 <br/>* 描述: 网络套接字的服务端,用来处理所有客户端的链接请求 <br/>* &nbsp;&nbsp;&nbsp;&nbsp;ServerSoc*/
public class ServerSoc {public static void main(String[] args) {try {ServerSocket ss = new ServerSocket(9000);System.out.println("等待连接。。。。。");//accept方法会阻塞进程,检测到有客户端连接则放行Socket s1 = ss.accept();System.out.println("连接成功");//获取客户端的输入和输出流,向客户端发送与接收信息BufferedReader in = new BufferedReader(new InputStreamReader(s1.getInputStream()));PrintWriter out = new PrintWriter(s1.getOutputStream());Scanner input = new Scanner(System.in);//服务端获取控制台输入的扫描器/*将双方的接收放在子线程中*/new Thread(new Runnable() {@Overridepublic void run() {String clientMsg = null;try {while (true){clientMsg = in.readLine();System.out.println(clientMsg);}} catch (IOException e) {throw new RuntimeException(e);}}}).start();//主线程正常进入死循环写信息while(true){String serverMsg = input.nextLine();out.println(serverMsg);out.flush();}//关闭资源
//            in.close();
//            out.close();
//            s1.close();
//            ss.close();} catch (IOException e) {e.printStackTrace();}}}

客户端:

package one;import java.io.*;
import java.net.Socket;
import java.util.Scanner;/*** 作者: wangyang <br/>* 创建时间: 2025/1/2 <br/>* 描述: 网络套接字的客户端,用来链接服务端,面向用户操作 <br/>* &nbsp;&nbsp;&nbsp;&nbsp;ClientSoc*/
public class ClientSoc {public static void main(String[] args) {try {Socket s = new Socket("127.0.0.1", 9000);//客户端一样,获取服务端的输入和输出流,向服务端端发送与接收信息BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));PrintWriter out = new PrintWriter(s.getOutputStream());Scanner input = new Scanner(System.in);//服务端获取控制台输入的扫描器/*将双方的接收放在子线程中*/new Thread(new Runnable() {@Overridepublic void run() {String clientMsg = null;try {while (true){clientMsg = in.readLine();System.out.println(clientMsg);}} catch (IOException e) {throw new RuntimeException(e);}}}).start();//主线程正常进入死循环写信息while(true){String clientMsg = input.nextLine();out.println(clientMsg);out.flush();}//关资源
//            out.close();
//            in.close();
//            s.close();} catch (Exception e) {e.printStackTrace();}}}

这次启动服务端和客户端后,就可以实现畅通无阻的对话了
在这里插入图片描述
在这里插入图片描述


上面的案例始终是但对单的,那么怎么实现群聊呢?其实现在就很简单了,不需要动客户端,让它保持现状,只需要改造一下服务端即可。上面的所有案例中,服务端其实有点不务正业了,只不过为了简化代码,强行给它写了手动输入并发送的代码,兼职一个客户端的身份相互直接对话,但其实它只需要负责接收客户端的消息,并按照要求发给所有客户端连接即可,要完成这样的流程需要对服务端做出如下更改

首先抽离服务端中所有的客户端流程,并编写所有服务端业务

package one;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;/*** 作者: wangyang <br/>* 创建时间: 2025/1/2 <br/>* 描述: 网络套接字的服务端,用来处理所有客户端的链接请求 <br/>* &nbsp;&nbsp;&nbsp;&nbsp;ServerSoc*/
public class ServerSoc {//服务端持有一个所有链接的容器集合public static ArrayList<Socket> connections = new ArrayList<Socket>();//服务端群发信息方法,参数是要发送的消息public static void sendAll(String s) throws IOException {if (connections != null) {for (int i = 0;i<connections.size();i++) { //遍历Socket集合//获取每个socket的输出流PrintWriter pw = new PrintWriter( connections.get(i).getOutputStream() );//使用每个输出流发送同一条消息pw.println(s);pw.flush();//这里有个重点!!不能关流,因为要不停的监听消息并发送,所以不能再这里关流}}}public static void main(String[] args) {try {ServerSocket ss = new ServerSocket(9000);//服务端等待所有的连接while (true){System.out.println("等待新连接。。。。。");//accept检测到链接之后将这个套接字对象放入容器并且为每个连接启动一个监听读取的线程Socket s1 = ss.accept();connections.add(s1);new ServerThreadForClient(s1).start();System.out.println("连接成功,当前所以连接如下--》");System.out.println(connections);}} catch (IOException e) {e.printStackTrace();}}}

为每一个连接启动一个监听消息的线程类:

package one;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;/*** 作者: wangyang <br/>* 创建时间: 2025/1/2 <br/>* 描述: <br/>* &nbsp;&nbsp;&nbsp;&nbsp;ServerThreadForClient 用来承载服务端对每个连接的发送消息处理*/
public class ServerThreadForClient extends Thread{private Socket s = null;public ServerThreadForClient(Socket adds){this.s = adds;}/*** 描述: 为一个连接启动发出消息的监听 <br/>* 作者: wangyang <br/>* 创建时间: 2025/1/2 <br/>* 参数: <br/>* 返回值:  <br/>*/@Overridepublic void run() {try {BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));String clientMsg = null;while (true){clientMsg = in.readLine();//调用服务端的方法向所有的客户端发送消息ServerSoc.sendAll(clientMsg);}} catch (IOException e) {throw new RuntimeException(e);}}
}

客户端保持不变:

package one;import java.io.*;
import java.net.Socket;
import java.util.Scanner;/*** 作者: wangyang <br/>* 创建时间: 2025/1/2 <br/>* 描述: 网络套接字的客户端,用来链接服务端,面向用户操作 <br/>* &nbsp;&nbsp;&nbsp;&nbsp;ClientSoc*/
public class ClientSoc {public static void main(String[] args) {try {Socket s = new Socket("127.0.0.1", 9000);System.out.println("客户端连接服务器成功");//客户端一样,获取服务端的输入和输出流,向服务端端发送与接收信息BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));PrintWriter out = new PrintWriter(s.getOutputStream());Scanner input = new Scanner(System.in);//服务端获取控制台输入的扫描器/*将双方的接收放在子线程中*/new Thread(new Runnable() {@Overridepublic void run() {String clientMsg = null;try {while (true){clientMsg = in.readLine();System.out.println(clientMsg);}} catch (IOException e) {throw new RuntimeException(e);}}}).start();//主线程正常进入死循环写信息while(true){String clientMsg = input.nextLine();out.println(clientMsg);out.flush();}} catch (Exception e) {e.printStackTrace();}}}

启动服务端后,启动多个客户端,就可以看到如下效果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
到此,Java套接字的基本应用就介绍完了,可以自己以此为基础衍生很多有意思的小程序,市面上也有很多现成的类库和架构,来完成不同的能力,比如上面的socket其实是一种二进制接口,想要完成丰富的能力需要写很复杂的代码,而Springboot提供了websocket用来在web的基础上完成套接字的实现,从而实现在线客服等能力的支持

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

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

相关文章

Mac 安装Mysql启动Mysql以及数据库的常规操作

Mac 安装Mysql启动Mysql以及数据库的常规操作 一、mysql的安装 1、登录官方网站:dev.mysql.com/downloads/mysql/ 二、查看系统架构 uname -m 在MAC中&#xff1a; 如果输出结果是 x86_64&#xff0c;则表示你的系统是 x86-64 架构。 如果输出结果是 arm64&#xff0c;则表示…

OpenCV的人脸检测模型FaceDetectorYN

OpenCV的人脸检测模型FaceDetectorYN 1. 官网地址2. 如何使用2.1.到opencv_zoo下载模型文件和代码2.2. 下载文件展示2.3. 修改了demo支持读取视频文件&#xff0c;默认是图片和摄像头## 2.4 效果展示 1. 官网地址 https://docs.opencv.org/4.x/df/d20/classcv_1_1FaceDetector…

DeepSeek-VL2

《DeepSeek-VL2: Mixture-of-Experts Vision-Language Models for Advanced Multimodal Understanding》是 DeepSeek-AI 团队发布的关于视觉语言模型 DeepSeek-VL2 的论文&#xff0c;以下是对该论文的详细介绍&#xff1a; 研究背景与动机 多模态理解的重要性&#xff1a;在当…

电子应用设计方案82:智能 AI 椅子系统设计

智能 AI 椅子系统设计 一、引言 智能 AI 椅子旨在为用户提供更加舒适、个性化和智能化的坐乘体验&#xff0c;结合了先进的技术和人体工程学原理。 二、系统概述 1. 系统目标 - 自动适应用户的体型和坐姿&#xff0c;提供最佳的支撑和舒适度。 - 实时监测用户的健康数据&…

Ps:创建数据驱动的图像

在设计实践中&#xff0c;常常需要处理大量内容变化但设计格式统一的任务&#xff0c;例如批量生成名片、工作证、学生证、胸牌、奖状或证书甚至图册。这些工作如果逐一手动制作&#xff0c;不仅耗时费力&#xff0c;还容易出错。 为解决这一问题&#xff0c;Photoshop 提供了强…

彻底解决 Selenium ChromeDriver 不匹配问题:Selenium ChromeDriver 最新版本下载安装教程

在 Python 的 Selenium 自动化测试中&#xff0c;ChromeDriver 是不可或缺的工具。它作为代码与 Chrome 浏览器的桥梁&#xff0c;但如果版本不匹配&#xff0c;就会导致各种报错&#xff0c;尤其是以下常见问题&#xff1a; selenium.common.exceptions.SessionNotCreatedExc…

天猫推荐数据集实践

参考自 https://github.com/xufengtt/recom_teach_code&#xff0c;学习记录。 环境配置&#xff08;maxcomputedataworks&#xff09; 下载天猫推荐数据集&#xff1b;开启 aliyun 的 maxcompute&#xff0c;dataworks&#xff0c;pai&#xff1b;使用 odpscmd 上传本地数据…

人脑处理信息的速度与效率:超越计算机的直观判断能力

人脑处理信息的速度与效率&#xff1a;超越计算机的直观判断能力 关键词&#xff1a; #人脑信息处理 Human Brain Information Processing #并行处理 Parallel Processing #视觉信息分析 Visual Information Analysis #决策速度 Decision Speed #计算机与人脑比较 Computer v…

checked 溢出问题

{try{int i int.MaxValue;int j;checked{j i 1;}}catch (OverflowException er){Console.WriteLine($"加Checked——>{er.Message}");}}{try{int i int.MaxValue;int j;j i 1;}catch (OverflowException er){Console.WriteLine($"没有加Checked——&g…

LabVIEW 使用 Resample Waveforms VI 实现降采样

在数据采集与信号处理过程中&#xff0c;降采样是一种重要的技术&#xff0c;用于在减少数据点的同时保留信号的关键特性&#xff0c;从而降低存储和计算需求。本文通过 LabVIEW 的 Resample Waveforms (continuous).vi 示例&#xff0c;详细介绍如何使用该功能实现波形数据的降…

数字化供应链创新解决方案在零售行业的应用研究——以开源AI智能名片S2B2C商城小程序为例

摘要&#xff1a; 在数字化转型的浪潮中&#xff0c;零售行业正经历着前所未有的变革。特别是在供应链管理方面&#xff0c;线上线下融合、数据孤岛、消费者需求多样化等问题日益凸显&#xff0c;对零售企业的运营效率与市场竞争力构成了严峻挑战。本文深入探讨了零售行业供应…

《计算机网络》(B)复习

目录 一、问答题测试 1.论述具有五层协议的网络体系结构的要点&#xff0c;包括各层的主要功能。 2.物理层的接口有哪几个方面的特性&#xff1f;各包含些什么内容&#xff1f; 3.小明想要访问淘宝&#xff0c;当他打开浏览器输入www.taobao.com浏览淘宝的 过程是什么&#…

用Tkinter制作一个用于合并PDF文件的小程序

需要安装PyPDF2库&#xff0c;具体原代码如下&#xff1a; # -*- coding: utf-8 -*- """ Created on Sun Dec 29 14:44:20 2024author: YBK """import PyPDF2 import os import tkinter as tk import windndpdf_files [] def dragged_files(f…

“大数据+职业本科”:VR虚拟仿真实训室的发展前景

在新时代背景下&#xff0c;随着科技的飞速进步和产业结构的不断升级&#xff0c;职业教育正迎来前所未有的变革。“大数据职业本科”的新型教育模式&#xff0c;结合VR&#xff08;虚拟现实&#xff09;技术的广泛应用&#xff0c;为实训教学开辟了崭新的道路&#xff0c;尤其…

【异常解决】生产环境 net :: ERR_INCOMPLETE_CHUNKED_ENCODING的问题修复

博主介绍&#xff1a;✌全网粉丝22W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…

矩阵运算提速——玩转opencv::Mat

介绍:用Eigen或opencv::Mat进行矩阵的运算&#xff0c;比用cpp的vector或vector进行矩阵运算要快吗? 使用 Eigen 或 OpenCV 的 cv::Mat 进行矩阵运算通常比使用 std::vector<int> 或 std::vector<double> 更快。这主要有以下几个原因&#xff1a; 优化的底层实现…

mac m2 安装 docker

文章目录 安装1.下载安装包2.在downloads中打开3.在启动台打开打开终端验证 修改国内镜像地址小结 安装 1.下载安装包 到官网下载适配的安装包&#xff1a;https://www.docker.com/products/docker-desktop/ 2.在downloads中打开 拖过去 3.在启动台打开 选择推荐设置 …

redis的集群模式与ELK基础

一、redis的集群模式 1.主从复制 &#xff08;1&#xff09;概述 主从模式&#xff1a;这是redis高可用的基础&#xff0c;哨兵和集群都是建立在此基础之上。 主从模式和数据库的主从模式是一样的&#xff0c;主负责写入&#xff0c;然后把写入的数据同步到从服务器&#xff…

建立一个Macos载入image的实例含界面

前言 为了方便ios程序的开发&#xff0c;有时候需要先用的Macos平台进行一些功能性的程序开发。 作为对比和参考。 1、创建一个MacOS的App 2、主界面控件的增加 添加的控件方法与ios相同&#xff0c;也是再用commandshiftL&#xff08;CtrlShiftL&#xff09;,就会弹出控件…

《机器学习》从入门到实战——逻辑回归

目录 一、简介 二、逻辑回归的原理 1、线性回归部分 2、逻辑函数&#xff08;Sigmoid函数&#xff09; 3、分类决策 4、转换为概率的形式使用似然函数求解 5、对数似然函数 ​编辑 6、转换为梯度下降任务 三、逻辑回归拓展知识 1、数据标准化 &#xff08;1&#xf…