目录
Java网络编程

[toc]

TCP和OSI参考模型

要想计算机之间是如何进行通信的,我们知道数据都是以0101这种二级制数字在电脑中保存并在互联网中进行通信的,单纯的分析二进制数据完全无从下手,TCP和OSI参考模型为我们进行数据通信的分析提供了方便。这里进行简单的介绍,毕竟这不是重点,我们的重点是java网络编程!!!
::: hljs-center

图片描述

:::

现在TCP/IP已经成为国际标准了,其实以前没有OSI和TCP/IP谁是老大老二,OSI还是IETF组织经过研究的推出的,但是最后还是被这个毛头小子TCP/IP独占天下,所以说被推崇的东西不一定是最好的。言归正传,我们开发一般混迹与传输层和网络层,java不是服务端的语言吗,服务端只管提供服务就好了,至于有没有漂亮的界面(应用层的部分)交给前端去做就ok了,我们只管数据的提供,可以说是我们是数据生产者。各层的功能各位去看计算机网络去吧!

混迹于各层的网络协议

不成规矩不成方圆,就像交通法规一样,红灯停绿灯行黄灯亮了等一等,你就想如果计算机在互联网中传递数据报文如果没有规律,那不得乱成一套。所以说网络协议就相当于生活中的交通法规,比如http、ftp、smtp、tcp、udp、arp等,他们位于网络模型的哪几层,我们要有个清晰的认识

::: hljs-center

图片描述

:::

其中最重要的是,其实都很重要,这里我们说开发中比较常用的比如http、TCP、UDP和IP。互联网中主机的通信对于用户来说大部分都是将数据以一定的形式展示给用户,从底层的01数据流到IP、TCP、UDP相应的数据封装,最后以http协议或者其他以文本格式或者图片形式展示给用户。(大致的分析)

UDP协议

UDP(User Data Protocol)用户数据协议,无连接,不可靠;传输快,系统耗费资源低,适用于对性能要求高于据完整性的场景。

运行于UDP协议之上的协议:

  • DHCP协议:动态主机配置协议,动态配置IP地址
  • NTP协议:网络时间协议,用于网络时间同步
  • BOOTP协议:引导程序协议,DHCP协议的前身,用于无盘工作站从中心服务器上获取IP地址

TCP协议

TCP(Transfer Control Protocol)传输控制协议,三次握手建连接,传输可靠,大数据传输,效率略低于UDP,适用于对数据完整性要求比较高的场景

运行于TCP协议之上的协议:

  • HTTP协议:超文本传输协议,用于普通浏览
  • HTTPS协议:安全超文本传输协议,身披SSL外衣的HTTP协议
  • FTP协议:文件传输协议,用于文件传输
  • POP3协议:邮局协议,收邮件使用
  • SMTP协议:简单邮件传输协议,用来发送电子邮件
  • Telent协议:远程登陆协议,通过一个终端登陆到网络
  • SSH协议:安全外壳协议,用于加密安全登陆,替代安全性差的Telent协议

InetAddress类及其常用方法

InetAddress类提供了操作互联网上IP地址和域名的的相关方法,该类本身没有构造函数,而是通过调用相关静态方法获取实例。常用方法如下:

方法名称 说明
byte[] getAddress() 返回此 InetAddress 对象的原始 IP 地址
static InetAddress getByAddress(byte[] addr) 在给定原始 IP 地址的情况下,返回 InetAddress 对象
static InetAddress getByAddress(String host) 在给定主机名的情况下确定主机的 IP 地址
String getCanonicalHostName() 获取此 IP 地址的完全限定域名
String getHostAddress() 返回 IP 地址字符串(以文本表现形式)
String getHostName() 返回此 IP 地址的主机名
static InetAdderss getLocalHost() 返回本地主机

UDP之DatagramSocket&DatagramPacket

DatagramPacket的构造方法

构造方法 说明
DatagramPacket(byte[] buf,int length) 构造 DatagramPacket,用来接收长度为 length 的数据包
DatagramPacket(byte[] buf,int offset, int length) 构造 DatagramPacket,用来接收长度为 length 的包,在缓冲区中指定了偏移量
DatagramPacket(byte[] buf,int length, InetAddress address,int port) 构造 DatagramPacket,用来将长度为 length 的包发送到指定主机上的指定端口
DatagramPacket(byte[] buf,int length, SocketAddress address) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口

DatagramPacket常用方法

方法 说明
InetAddress getAddress() 返回某台机器的 IP 地址,此数据报将要发往该机器或者从该机器接收。
byte[] getData() 返回数据缓冲区。
int getLength() 返回将要发送或者接收的数据的长度。
int getPort() 返回某台远程主机的端口号,此数据报将要发往该主机或者从该主机接收。
getSocketAddress() 获取要将此包发送或者发出此数据报的远程主机的SocketAddress(通常为 IP地址+端口号)。

DatagramSocket构造方法

构造方法 说明
DatagramSocket() 构造数据报包套接字并将其绑定到本地主机上任何可用的端口。
DatagramSocket(int port) 创建数据报包套接字并将其绑定到本地主机上的指定端口。
DatagramSocket(int portJnetAddress addr) 创建数据报包套接字,将其绑定到指定的本地地址。
DatagramSocket(SocketAddress bindaddr) 创建数据报包套接字,将其绑定到指定的本地套接字地址。

DatagramSocket 的常用方法

方法 说明
void bind(SocketAddress addr) 将此 DatagramSocket 绑定到特定的地址和端口。
void close() 关闭此数据报包套接字。
void connect(InetAddress address,int port) 将套接字连接到此套接字的远程地址。
void connect(SocketAddress addr) 将此套接子连接到远程套接子地址(IP地址+端口号)。
void disconnect() 断开套接字的连接。
InetAddress getInetAddress() 返回此套接字连接的地址。
InetAddress getLocalAddress() 获取套接字绑定的本地地址。
int getLocalPort() 返回此套接字绑定的本地主机上的端口号。
int getPort() 返回此套接字的端口。

使用UDP协议模拟从客户端输入信息发送一条消息,服务端接收并显示

java
复制代码
public class UDPClient {
 
    public static void main(String[] args) throws IOException {
        // client
        // 建立服务
        DatagramSocket ds = null;
        // 获取输入字符
        BufferedReader br = null;
        try {
            if (ds == null)
                ds = new DatagramSocket();
            if (br == null)
                br = new BufferedReader(new InputStreamReader(System.in));
            // 把读取的资源打包
            byte[] buf = br.readLine().getBytes();
            DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getLocalHost(), 10005);
            // 将打包好的数据发送出去
            ds.send(dp);
        } catch (IOException e) {
            System.out.println("数据发送失败");
        } finally {
            ds.close();
            if (br != null)
                br.close();
        }
        // server
    }
 
}
public class UDPServer {
 
    public static void main(String[] args) throws IOException {
        // 创建服务
        DatagramSocket ds = null;
        DatagramPacket dp = null;
        try {
            if (ds == null)
                ds = new DatagramSocket(10005);
            // 创建缓冲区
            byte[] buf = new byte[1024];
            // 接收数据
            if (dp == null)
                dp = new DatagramPacket(buf,buf.length);
            ds.receive(dp);
            String ip = dp.getAddress().getHostAddress();
            //输出数据到控制台
            System.out.println(ip+":"+new String(buf, 0, dp.getLength()));
        } catch (IOException e) {
            System.out.println(e.getMessage());
        } finally {
            ds.close();
        }
    }
}

注意先开启server端的程序,因为UDP是无状态的协议,如果先开启Client那么Client只会发送一条消息,他不管你是否监听,只管发送,可能就会导致输出空白,鬼知道你有没有开启Server端口的监听。

UDP之聊天案例

java
复制代码
public class NetChatDemo {
 
    public static void main(String[] args) throws IOException {
        new Thread(new Server()).start();
        DatagramSocket ds = null;
        BufferedReader br = null;
        try {
            // 发送数据的时候指定端口
            ds = new DatagramSocket();
            br = new BufferedReader(new InputStreamReader(System.in));
            byte[] buf;
            String line = null;
            while ((line = br.readLine()) != null) {
                buf = line.getBytes();
                DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getLocalHost(), 10006);
                ds.send(dp);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            ds.close();
            if (br != null) {
                br.close();
            }
        }
    }
}
class Server implements Runnable {
    @Override
    public void run() {
        DatagramSocket ds = null;
        DatagramPacket dp = null;
        // 循环包裹,如果单单一个线程没有循环,那么运行一遍就完事了
        while (true) {
            try {
                ds = new DatagramSocket(10006);
                byte[] buf = new byte[1024];
                dp = new DatagramPacket(buf, buf.length);
                ds.receive(dp);
                String ip = dp.getAddress().getHostAddress();
                System.out.println(ip+" : "+new String(buf, 0, dp.getLength()));
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                ds.close();
                System.out.println("run end...");
            }
        }
    }
}

TCP之Socket&ServerSocket

Socket构造函数

Socket(InetAddress address,int port) 创建一个流套接字并将其连接到指定IP地址的端口
Socket(String host,int port) 创建一个流套接字并将其连接到指定主机上的端口

Socket常用方法

void close() 关闭此套接字。
InetAddress getInetAddress() 返回套接字的连接地址。
InputStream getInputStream() 返回此套接字的输入流。
OutputStream getOutputStream() 返回此套接字的输出流。
int getPort() 返回此套接字连接的远程端口。
void shutdownInput( ) 将套接字的输入流关闭
void shutdownOutput( ) 将套接字的输出流关闭

Java使用TCP进行发送数据

  • Socket建立连接
  • Socket获取输出流,想输出流中写数据
  • shutdownOutput关闭发送流
  • Socket获取输入流,获取服务端给与的反馈信息
  • 关闭连接

Java使用TCP进行接收数据

  • 实例化ServerSocket对象并设置监听端口
  • 调用ServerSocket的accept方法获取Socket对象
  • 从Socket对象中获取输入流进行操作
  • 利用输出流向客户端发送信息
  • 关闭连接

总结:底层还是借助输入输出流进行数据的传递,只要对java流的操作很熟练,那么这些都不在话下了

java
复制代码
public class SocketDemo {
 
    public static void main(String[] args) {
        new Thread(new Server()).start();
        Socket socket = null;
        try {
            socket = new Socket(InetAddress.getLoopbackAddress(), 13000);
            byte[] buf = "新冠带来的影响".getBytes();
 
            // 获取输出流
            OutputStream out = socket.getOutputStream();
            out.write(buf);
 
            // 关闭发送流
            socket.shutdownOutput();
 
            // 获取输入流,获取反馈信息
            InputStream in = socket.getInputStream();
            byte[] buffer = new byte[1024];
            int len = in.read(buffer);
            System.out.println(new String(buffer, 0, len));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
 
class Server implements Runnable {
 
    @Override
    public void run() {
        ServerSocket ss = null;
        Socket s = null;
        InputStream in = null;
        try {
            ss = new ServerSocket(13000);
            s = ss.accept();
 
 
            String ip = s.getInetAddress().getHostAddress();
            // 输出连接上来的机器
            System.out.println(ip + "->connected");
 
            in = s.getInputStream();
 
        // 读取数据
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len = in.read(buf)) != -1) {
            System.out.println(new String(buf, 0, len));
        }
        s.shutdownInput();
        // 发送反馈信息
        OutputStream out = s.getOutputStream();
        out.write("服务端收到了!".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                s.close();
                ss.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
 
 
    }
}

URI和URL

URI简介

  1. URI(Uniform Resource Identifier)统一资源标识符,字如其名,它是采用特定的语法标识互联网主机上的资源的字符串表示。这里不需要纠结标识的目标资源到底是什么,因为使用者不会见到资源的实体,从服务器接受的只是01流。

  2. URI的语法构成

    URI的语法构成是:一个模式和一个模式特定部分

    [ scheme :][ // authority][ path][ ? query][ # fragment]

    URI的常用模式(scheme)包括data:(链接中直接包含经过BASE64编码的数据。)、file:(本地磁盘上的文件)、ftp、http、mailto(电子邮件协议的地址)、magnet(可以通过对等网络比如端对端P2PBitTorrent下载的资源)、telnet。authority部分指定了负责解析该URI其他部分的授权机构(authority),一般URI都是使用Internet主机作为授权机构。典型的URI的其他三个部分(模式特定部分,也就是授权机构、路径和查询参数)分别由ASCII字母组成(也就是字母A-Z、a-z和数字0-9),此外,还可以使用标点符号-、_、.、!和~,而定界符(如/、?、&和=)有其预定义的用途。所有的其他字符,包括ASCII中拉丁字母,都需要使用百分号(%)转义,转义后的格式是:%+字符按照UTF-8编码再转成16进制的字符串表示。注意一点,如果前面提到的定界符没有作为定界符使用,也需要进行转义。举个简单的例子,如URI中存在中文字符"木",木字的UTF-8编码为0xE6 0x9C 0xA8,那么它在URI中应该转义为%E6%9C%A8。Jdk中的URLEncoder或者apache-codec中的相关类库提供URI(URL)编码的功能。

URL简介

  1. URL(Uniform Resource Location)统一资源定位符。URL本质是一种特殊的URI,它除了可以标识资源外,还可以定位资源,也就是提供了访问资源的入口,通过URL就可以访问到特定主机上的某个资源。

    URL所表示的网络资源位置通常包括用于访问服务器的协议(如http、ftp等)、服务器的主机名或者IP地址、以及资源文件在该服务器上的路径。典型的URL例如http://localhost/myProject/index.html,它指示本地服务器的myProject目录下有一个名为index.html的文档,这个文档可以通过http协议访问(实际上,URL不一定是指服务器中的真实的物理路径,因为我们一般在服务器中部署应用,如Servlet应用,URL访问的很可能是应用的接口,至于最终映射到什么资源可以由应用自身决定)。

  2. URL的语法

    protocol://userInfo@host:port/path?query#fragment

    protocol:其实就是URI模式中schema的另外一个叫法,常用的和schema前面列出的大致一样。

    port:URL中的端口号是指服务器中应用运行的端口,默认为80(可选)

    path:表示服务器上的一个特定文件或目录,可以是相对的。

    query:查询参数,key1=value1&key2=value2...形式

  • URI&URL

    换句话说,每个URL都是URI,但是不是每个URI都是URL的。他们之间最明显的不同就是在java.net.URI你只能看到他的一些属性,他只是表示一个位置,**但是你没有办法通过URI获取到这个对象的流,但是URL就不同了。java.net.URL该类提供方法(openConnection()),通过该方法我们可以通过IO流操作他。**但是URI中我貌似没看到相关的方法。

URI和URL的简单使用

  1. URI的使用,URI并不常用,所以这里没有列举相应的方法,实际中也不会去记忆的每个方法,主要用的时候查看底层源码结合注释来使用相应方法。

    java
    复制代码
    // URI.create(String str)底层还是通过构造new
            URI uri = URI.create("http://localhost:8080/index.html");
            String authority = uri.getAuthority();
            System.out.println("authority-->" + authority);
            String host = uri.getHost();
            System.out.println("host-->" + host);
            String path = uri.getPath();
            System.out.println("path-->" + path);
            int port = uri.getPort();
            System.out.println("port-->" + port);
            // 输出
            // authority-->localhost:8080
            // host-->localhost
            // path-->/index.html
            // port-->8080
            URI uri1 = URI.create("http://localhost:8080/index?key=你好世界");
            /**
             * toString()方法返回未编码的字符串形式,也就是特殊的字符不使用百分号转义,
             * 因此这个方法的返回值不能保证符合URI的语法,尽管它的各个部分是遵循URI的语法规范的。
             * toASCIIString()方法返回经过编码的字符串形式(US-ACSII编码),也就是特殊的字符一定经过了百分号转义。
             * toString()存在的意义是提高URI的可读性,toASCIIString()方法存在的意义是提高URI的可用性。
             */
            System.out.println(uri1.toString());
            System.out.println(uri1.toASCIIString());
            // 输出
            // http://localhost:8080/index?key=你好世界
            // http://localhost:8080/index?key=%E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C
  2. URL的使用

    URL的构造

    java
    复制代码
    //基于URL的各个部分构造URL实例,其中file相当于path、query和fragment三个部分组成
    public URL(String protocol, String host, int port, String file) throws MalformedURLException
    
    //基于URL的各个部分构造URL实例,其中file相当于path、query和fragment三个部分组成,使用默认端口80
    public URL(String protocol, String host, String file) throws MalformedURLException
    
    //基于URL模式构造URL实例
    public URL(String spec) throws MalformedURLException
    
    //基于上下文(父)URL和URL模式构造相对URL实例
    public URL(URL context, String spec) throws MalformedURLException

    获取URL的属性

    java
    复制代码
    public final InputStream openStream() throws java.io.IOException
    
    public URLConnection openConnection() throws java.io.IOException
    
    public URLConnection openConnection(Proxy proxy) throws java.io.IOException
    
    public final Object getContent() throws java.io.IOException
    
    public final Object getContent(Class[] classes) throws java.io.IOException

    获取URL的组成部分

    java
    复制代码
    
    //获取模式(协议)
    public String getProtocol()
    
    //获取主机名
    public String getHost()
    
    //获取授权机构,一般是host:port的形式
    public String getAuthority()
    
    //获取端口号port
    public int getPort()
    
    //返回协议的默认端口,如http协议的默认端口号为80,如果没有指定协议的默认端口则返回-1
    public int getDefaultPort()
    
    //返回URL字符串中从主机名后的第一个斜杆/一直到片段标识符的#字符之前的所有字符
    public String getFile()
    
    //返回的值和getFile()相似,但是不包含查询字符串
    public String getPath()
    
    //返回URL的片段标识符部分
    public String getRef()
    
    //返回URL的查询字符串
    public String getQuery()
    
    //返回URL中的用户信息,不常用
    public String getUserInfo()

    示例

    java
    复制代码
    // 注意file前要加前缀 "/"
            URL url = new URL("http", "localhost", 80, "/index?key=hello");
            System.out.println(url.toString());// http://localhost:80/index?key=hello
            System.out.println(url.getPath());// /index 不包含查询字段
            System.out.println(url.getFile());//  /index?key=hello包含查询路径
    
            // 1.1 使用URL.openStream获取输入流
            URL url1 = new URL("http://www.baidu.com");
            InputStream in = url1.openStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String result;
            while ((result = reader.readLine()) != null) {
                System.out.println(result);// 输出 百度首页 html代码
            }
            in.close();
            reader.close();
    
            // 1.2. 使用URLConnection.getInputStream获取输入流
            URLConnection urlConnection = url1.openConnection();
            in = urlConnection.getInputStream();
            reader = new BufferedReader(new InputStreamReader(in));
            while ((result = reader.readLine()) != null) {
                System.out.println(result);// 输出 百度首页 html代码
            }
            // 关闭流
            in.close();
            reader.close();
    
            

URL的编码和解码

为什么需要进行编码呢?这个是历史遗留原因,因为发明Web或者说Http(s)协议的时候,Unicode编码并未完全普及,URL中使用的字符必须来自ASCII的一个固定子集,这个固定子集是:

  • 大写字母A-Z。
  • 小写字母a-z。
  • 数字0-9。
  • 标点符号字符-_.!~*'(和,)。

其他字符如:/&?@#;$+=%也可以使用,但是它们限定于使用在特定的用途,如果这些字符串出现在URL路径或者查询字符串,它们以及路径和查询字符串的内容必须进行编码。(避免歧义)

这里有个需要注意的地方:URL编码只针对URL路径和URL路径之后的部分,因为URL规范中规定,路径之前的部分必须满足ASCII固定子集的内容。

java
复制代码
URL url = new URL("http://www.baidu.com/s?wd=新冠");
// URL编码针对path及path之后的
// String s = URLEncoder.encode(url.toString(), "utf-8");
// 很显然不符合URL规范 http%3A%2F%2Fwww.baidu.com%2Fs%3Fwd%3D%E6%96%B0%E5%86%A0
String file = url.getFile();
String[] split = file.split("=");
String encode = URLEncoder.encode(split[1], "utf-8");
String decode = URLDecoder.decode(encode, "utf-8");
System.out.println(decode);

URLConnection&HttpURLConnection

在JDK的java.net包中已经提供了访问HTTP协议的基本功能的类:HttpURLConnection。

HttpURLConnection是Java的标准类,它继承自URLConnection,可用于向指定网站发送GET请求、POST请求。

注意事项:

  • HttpURLConnection对象不能直接构造,需要通过URL类中的openConnection()方法来获得。

  • HttpURLConnection的connect()函数,实际上只是建立了一个与服务器的TCP连接,并没有实际发送HTTP请求。HTTP请求实际上直到我们获取服务器响应数据(如调用getInputStream()、getResponseCode()等方法)时才正式发送出去。

  • 对HttpURLConnection对象的配置都需要在connect()方法执行之前完成。

  • HttpURLConnection是基于HTTP协议的,其底层通过socket通信实现。如果不设置超时(timeout),在网络异常的情况下,可能会导致程序僵死而不继续往下执行。

  • HTTP正文的内容是通过OutputStream流写入的, 向流中写入的数据不会立即发送到网络,而是存在于内存缓冲区中,待流关闭时,根据写入的内容生成HTTP正文。
    调用getInputStream()方法时,返回一个输入流,用于从中读取服务器对于HTTP请求的返回信息。

感觉这篇文章排版不是很好,整篇读下来没怎么有感觉,以后要注意一下了,可否给个:star:、:+1:、:heart:。

本文由 康师傅的小跟班 原创发布于 阳光沙滩 , 未经作者授权,禁止转载
评论
0 / 1024
用户头像
拜读大佬文章
2020-05-01 07:22回复
用户头像
顶
2020-04-22 04:42回复
用户头像
卧槽,才发现你文章的图片有点问题,哈哈。
2020-04-22 03:25回复
用户头像
测试评论
2020-04-21 06:48回复
用户头像
推荐评论
2020-04-21 06:46回复
推荐文章
linux服务器的日志、容器清理
本手册提供了一套全面的Linux服务器磁盘清理与排查方法,帮助用户高效管理磁盘空间。通过查看磁盘使用情况、分析Docker占用、清理无用容器和日志,确保系统运行流畅。适合需要优化服务器性能的运维人员参考。
记给网站接入图形验证码
本文分享了如何为个人站点添加图形验证码以提升安全性,详细介绍了使用第三方接口实现验证码功能的过程,并通过代码示例展示了具体实现方式。对于关注网站安全的开发者来说,这篇文章提供了实用的参考价值。
Java开发环境搭建
本文是一份详细的Java开发环境搭建指南,涵盖了Java的发展历史、版本选择及安装配置过程。无论你是初学者还是有经验的开发者,都能从中找到实用的信息和步骤,帮助你快速上手Java开发。
Vue3.js项目的创建
本文详细介绍了如何使用Vue3创建项目,包括Node.js的安装和配置,以及项目的初始化过程。适合初学者学习如何快速搭建Vue3开发环境,并推荐了相关课程供进一步学习。
Network Tools : 您的运维“助手”升级了
Network Tools是一款专为解决运维难题而设计的软件,集设备管理、配置备份、性能监控和告警处理于一体。通过统一的工作台,帮助运维人员更高效地管理资产、定位故障并提升团队协作效率。无论是设备在线状态还是具体问题排查,都能得到全面支持。
Ubuntu 软件安装与彻底卸载指南
本文详细介绍了在 Ubuntu 系统中如何规范安装和彻底卸载 .deb 格式软件,包括依赖修复、残留清理以及图形化工具推荐,适合需要维护系统环境的用户。
JavaWeb开发客户程序更新特殊环境下的骚操作
本文分享了在无外网环境下,如何利用Docker和docker-compose实现高效部署的实战经验。通过基础镜像和本地jar包挂载的方式,解决了内网环境下的依赖问题,适合需要灵活部署方案的技术人员参考。
Linux 防火墙完全指南:从原理到多发行版实战
本文全面解析Linux防火墙的底层原理与主流工具配置,涵盖UFW、firewalld、iptables、nftables等方案,适合不同发行版用户。从基础概念到生产环境加固建议,助你掌握核心安全策略,确保服务器与网络的安全运行。
水上派对英语单词篇
探索FLOATOPIA水上派对的完整指南,涵盖签到流程、场地指引、安全须知、活动安排及夜场舞会等实用英语词汇与对话。无论是初学者还是老手,都能轻松掌握关键术语,享受完美水上体验。
麒麟操作系统下使用 virt-customize 重置虚拟机 root 密码实战
本文详细介绍了在麒麟操作系统环境下使用 virt-customize 工具重置 KVM 虚拟机 root 密码的完整流程,包含安装步骤、常见问题及解决方案,帮助运维人员高效处理密码遗忘或批量初始化场景,避免数据丢失。
浅析JS预编译-函数篇
本文详细讲解了JavaScript中函数的预编译过程,包括AO对象的创建、变量和函数声明的提升,以及执行阶段的变化。适合初学者了解JS执行机制,帮助深入理解代码运行逻辑。
访问Github的另一种姿势
本文介绍了如何通过Watt ToolKit等工具加速访问Github,适合对网络技术感兴趣的读者。内容涵盖工具介绍、下载和使用方法,以及一些实用技巧,值得一看。
使用Gulp压缩JS
本文详细介绍了如何使用Gulp压缩JavaScript文件,特别是支持ES6语法的处理方法。通过实际操作和效果对比,帮助开发者提升代码性能,适合对前端自动化工具感兴趣的读者。
使用Gulp压缩CSS
本文详细介绍了如何使用Gulp工具对CSS文件进行压缩,提升网页加载速度。适合需要优化静态资源的开发者,提供清晰的步骤和示例,帮助快速上手。
从0部署Nuxtjs项目
本文详细介绍了如何将Nuxt.js项目部署到公网,涵盖Node.js安装、环境配置、源码上传及使用PM2启动服务的全过程,适合开发者学习和实践。
Linux 命令行美化利器:tree 命令完全指南(安装 + 全部参数详解)
掌握 Linux 下的 `tree` 命令,快速直观地查看目录结构。本文详细讲解安装方法、参数含义及实战场景,适合开发者和系统管理员提升工作效率。
Linux常用命令(一)
本文详细介绍了Linux基础命令,包括文件操作、系统显示、网络状态、软件包管理等,适合初学者学习和查阅,是掌握Linux系统的实用指南。
大模型推理参数解码:温度、Top-p 与核采样如何塑造生成文本的灵魂
探索大语言模型的采样参数如何塑造生成内容,从温度到Top-p,从惩罚机制到熵控制,揭示背后的信息论原理与实践策略。了解如何通过参数调优,让AI既保持知识的严谨,又拥有创造力的自由。
记从0使用Claude code写代码
本文介绍了如何使用Claude Code搭配DeepSeek进行编程,详细讲解了安装Node.js、全局安装Claude、配置模型以及使用方法。对于开发者来说,这是一份实用的技术教程,尤其适合对AI编程工具感兴趣的读者。
Android-Studio-Gradle同步失败-Library为null的通用排查指南
遇到 Android Studio Gradle Sync 失败时,不要轻易删除全局缓存。本文详细解析了错误原因,并提供了一系列精准的排查步骤和解决方案,帮助开发者快速定位并解决问题,提升开发效率。
PHP实现密码加密
本文详细介绍了Bcrypt密码加密技术及其在PHP中的应用,帮助开发者提升用户密码的安全性。通过实际代码示例,展示了如何使用password_hash和password_verify函数进行密码加密与验证,是学习网络安全知识的实用指南。
WordCloud效果,滚动标签
本文详细介绍了如何在Vue项目中集成WordCloud组件,包括依赖安装、属性配置和使用方法。适合开发者学习如何实现数据可视化功能,提升项目交互体验。
从0使用WordPress搭建一个优美的网站
本文详细介绍了如何使用WordPress搭建一个美观的网站,从安装到主题配置和功能拓展,为读者提供了实用的操作指南。无论是初学者还是有一定经验的开发者,都能从中获得有价值的参考。
JS实现在网站底部添加运行时间
想知道如何在网站底部显示运行时间?本文详细讲解了通过JavaScript实现这一功能的方法,包括时间计算逻辑和代码实现。适合前端开发者学习参考,轻松为网站添加实用功能。
在Vercel上部署Hexo博客
本文详细介绍了如何在Vercel上快速部署Hexo博客,无需后端服务即可实现高效发布。相比传统方式,省去了手动生成和上传静态文件的步骤,更加便捷。适合想要搭建个人博客的开发者参考。
从0搭建一个Hexo博客
本文详细介绍了Hexo博客框架的使用方法,从安装到部署全流程讲解,适合想快速搭建个人博客的技术爱好者。内容清晰易懂,是入门Hexo的理想指南。
离线设备激活方案:古老的 Windows 光盘激活,离线算法授权等
本文深入解析了离线激活的核心原理与实现方式,从历史案例到现代技术,全面剖析了如何在无网络环境下确保软件授权的安全性。通过设备指纹、授权文件校验等手段,为开发者提供了可复用的架构设计思路,适用于工业、医疗等对网络依赖较低的场景。
Hexo实现生成站点地图
想为你的Hexo博客添加站点地图功能吗?本文详细介绍了如何通过安装插件和配置文件来实现,适合没有内置该功能的新主题或自定义主题的用户。简单步骤助你提升搜索引擎优化效果。
Hexo实现代码压缩
本文分享了如何通过Hexo插件优化博客性能,详细介绍了安装和配置过程,帮助提升网页加载速度。适合对网站优化感兴趣的开发者阅读。
记一次 GitHub 幽灵协作者大清洗:强制重写 Git 历史与穿透 CDN 缓存实践
本文详细讲解了如何解决GitHub上出现的‘幽灵协作者’问题,通过重写Git历史和穿透CDN缓存,彻底清理错误提交记录。适合开发者学习如何高效管理项目历史与优化仓库信息。