JAVA实现简易HTTP服务器

2023-11-20

说实话,之前完全没有想过,我还能写出服务器。感觉服务器这么高端的东西,能会用就不错了,还能写。

不吐槽了,开始了。
这次的作业是搭建一个服务器,要能接收请求,并给浏览器返回正确响应。
项目的下载地址

项目目标:实现一个简易的多线程服务器,可以处理来自浏览器的请求(GET/POST),并做出正确的回应。
请求分以下四种类型:
1. 无参数,文本文件类型
2. 无参数,图片文件类型
3. 有参数,GET方式请求,并完成表单验证(登陆验证)
4. 有参数,POST方式请求,并完成表单验证(登陆验证)

首先,应该明确这个项目的基本实现原理,从浏览器读入用户请求的信息,服务器解析并记录返回的文件名和参数列表,如果文件存在,用流读取文件,并返回到浏览器上,如果不存在,返回相应的提示信息,参数列表和服务器存储的相同的话,返回登陆成功,否则返回失败。

第一步,既然要解析从浏览器传过来的信息,那就要明白传过来信息的所使用的协议HTTP\UDP\FTP 和 URL的组成元素,因为是简易服务器,我们就只解析HTTP协议先。

这里写图片描述

Request是指从客户端到服务器端的请求消息
Request 消息分为3部分,第一部分叫请求行, 第二部分叫http header, 第三部分是body. header和body之间有个空行,结构如下图

这里写图片描述

Method表示请求方法,比如”POST”,”GET”,
Path-to-resoure表示请求的资源,
Http/version-number 表示HTTP协议的版本号,
当使用的是”GET” 方法的时候, body是为空的,当使用”POST”,body不为空,但是没有换行,readline()方法不能读

Response是指服务器端到客户端的响应信息
和Request消息的结构基本一样。 同样也分为三部分,第一部分叫request line, 第二部分叫request header,第三部分是body. header和body之间也有个空行, 结构如下图

这里写图片描述

状态码用来告诉HTTP客户端,HTTP服务器是否产生了预期的Response. HTTP/1.1中定义了5类状态码,1XX 提示信息 - 表示请求已被成功接收,继续处理;2XX 成功 - 表示请求已被成功接收,理解,接受;3XX 重定向 - 要完成请求必须进行更进一步的处理;4XX 客户端错误 - 请求有语法错误或请求无法实现;5XX 服务器端错误 - 服务器未能实现合法的请求,当然不写也是可以得,状态码就是便于程序员去分析当前页面是正确响应还是错误的。

第二步,在了解URL和HTTP协议之后,就可以开始构建项目了。

目前这个项目的UML图

这里写图片描述

第三步,准备文本、图片、HTML文件,然后开始编编编

效果图:(端口号:23333)2333…
默认访问
这里写图片描述

aaron.txt
这里写图片描述

a.jpg
这里写图片描述

GET/POST请求
注意地址栏的变化
login.html(GET)
这里写图片描述

login.html(GET) (登陆失败情况)
这里写图片描述

login.html(GET) (登陆成功情况)
这里写图片描述

login.html(POST)
这里写图片描述

login.html(POST) (登陆失败情况)
这里写图片描述

login.html(POST) (登陆成功情况)
这里写图片描述

部分源码:(全部源码去上面下载)

//Server.java
package cn.net.sight.server;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;
import cn.net.sight.thread.ServerThread;

public class Server {
    private static ServerSocket server;
    private static Properties properties;
    private int port;

    static {
        properties = new Properties();
        try {
            properties.load(new FileInputStream(new File("src/resources/property.proterties")));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //initialize the server
    public void init() {
        try {
            port = Integer.parseInt(properties.getProperty("port"));
            server = new ServerSocket(port);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //receive the request from the web browser
    public void receive() {
        Socket clientSocket = new Socket();
        try {
            clientSocket = server.accept();
        } catch (IOException e) {
            e.printStackTrace();
        }

        ServerThread thread = new ServerThread(clientSocket);
        thread.start();
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    //startup server
    public static void main(String[] args) {
        Server Aaroncat = new Server();
        Aaroncat.init();
        System.out.println("----Aaroncat has startup----");
        while(true){
            Aaroncat.receive();
        }
    }
}
//Request.java
package cn.net.sight.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

import cn.net.sight.util.MessageUtil;

public class Request {

    private InputStream input; // Socket --> InputStream
    private Socket socket; // client --> socket
    private BufferedReader buffer; // InputStream --> BufferedReader
    private String schema; // the schema of the request GET or POST
    private String requestFileName; // exact file name
    private String requestData; // file name + <key=value>...
    private String values_Str; // a string the user input in the form
    private int paramLength; // using in the POST: the length of parameters
    private Map<String, String> socketValues;// values_str --> MAP
    private PrintStream print;

    protected MessageUtil messageUtil = new MessageUtil();

    //省略了全部的setter() getter()

    private void doSchema(String firstLineInData) throws IOException {
        socketValues = new HashMap<String, String>();
        if (this.schema.equals("GET")) {
            // GET请求 --> 包含文件名和参数键值对
            // 实现了对FileName、SocketValues的赋值
            this.setRequestData(messageUtil.getRequestData(firstLineInData));
            if (this.requestData.contains("?")) {
                this.setRequestFileName(messageUtil.getFileName(this.getRequestData()));
                this.setSocketValues(messageUtil.getValues(this.getRequestData()));
            } else {
                // GET请求 -->只包含文件名
                // 实现了对FileName的赋值
                this.setRequestFileName(requestData);
            }
        } else {
            // POST请求 第一行只包含文件名
            // 实现了对FileName、SocketValues的赋值
            this.setRequestFileName(messageUtil.getRequestData(firstLineInData));
            this.getUserInfo(buffer);
        }
    }

    private void getUserInfo(BufferedReader br) throws IOException {
        while (this.buffer.ready()) {
            String remained = buffer.readLine();
            if (remained.contains("Content-Length")) {
                String[] temp = remained.split(" ");
                this.setParamLength(Integer.parseInt(temp[1]));
                break;
            }
        }
        buffer.readLine();
        String userInfo = "";
        for (int i = 0; i < this.getParamLength(); i++) {
            userInfo += (char) buffer.read();
        }
        this.setValues_Str(userInfo);
        this.setSocketValues(messageUtil.getValues(this.getValues_Str()));
    }

    public Request(Socket clientSocket) throws IOException {
        this.setSocket(clientSocket);
        this.setPrint(new PrintStream(clientSocket.getOutputStream()));
        this.setInput(clientSocket.getInputStream());
        this.setBuffer(new BufferedReader(new InputStreamReader(clientSocket.getInputStream())));

        // get something from the first line
        String firstLineInData = buffer.readLine();

        this.setSchema(messageUtil.getSchema(firstLineInData)); // 获得请求方式Schema

        doSchema(firstLineInData); // 对Schema进行判断

    }
}
//Response.java
package cn.net.sight.server;

import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Date;
import java.util.Map;
import cn.net.sight.util.FileUtil;
import cn.net.sight.util.LoginUtil;

public class Response {

    private String fileName;
    private Map<String, String> userValues;
    private PrintStream ps;
    private Request request;
    private Socket clientSocket;

    protected FileUtil fileUtil = new FileUtil();
    protected LoginUtil loginUtil = new LoginUtil();

    public String getFileName() {
        return fileName;
    }

    //省略了全部的setter() 和 getter()

    public Response(Request request) {
        this.setRequest(request);
        this.setClientSocket(request.getSocket());
        this.setFileName(request.getRequestFileName());
        userValues = this.request.getSocketValues();

        try {
            this.init();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void showup(String fileName) throws IOException {
        this.ps = this.request.getPrint();
        // 要处理正常文件名和空文件名
        if (!fileName.equals("")  && !fileName.equals("error.html")) {
            this.ps.println("HTTP/1.1 200 OK");
            this.ps.println();
            fileUtil.readFile(fileName, ps);
        } else if (fileName.equals("error.html")) {
            ps.println("HTTP/1.1 404 fileNotFound");
            ps.println();
            fileUtil.readFile("error.html", ps);
        } else {
            ps.println(new Date().toString());
        }
        if (ps != null){
            ps.close();
        }
    }

    public void init() throws IOException {
        //如果信息MAP是空,则代表是普通文件或者是默认访问
        if (userValues.isEmpty()) {
            if (fileName != "") {
                this.showup(fileName);
            } else {
                this.ps = this.request.getPrint();
                ps.println(new Date().toString());
                if(ps != null) ps.close();
                if(clientSocket != null)clientSocket.close();
            }
        } else {
            //如果信息MAP不为空,代表是GET/POST请求,并带有参数键值对
            this.Check(userValues, fileName);
        }

    }

    public void Check(Map<String, String> values_list, String respFileName) throws IOException {
        // 验证用户输入信息的合法性
        if (loginUtil.isValid(values_list)) {
            this.showup(respFileName);
        } else {
            this.showup("error.html");
        }
    }

}

//ServerThread.java
package cn.net.sight.thread;

import java.io.IOException;
import java.net.Socket;
import cn.net.sight.server.Response;
import cn.net.sight.server.Request;

public class ServerThread extends Thread {
    private Socket clientSocket;
    private Request request;
    private Response response;

    public ServerThread() {
        super();
    }

    public ServerThread(Socket clientSocket) {
        super();
        this.clientSocket = clientSocket;
    }

    public Socket getClientSocket() {
        return clientSocket;
    }

    public void setClientSocket(Socket clientSocket) {
        this.clientSocket = clientSocket;
    }

    public Request getRequest() {
        return request;
    }

    public void setRequest(Request request) {
        this.request = request;
    }

    public Response getResponse() {
        return response;
    }

    public void setResponse(Response response) {
        this.response = response;
    }

    public void run(){
        super.run();
        try {
            this.setRequest(new Request(clientSocket));
            this.response = new Response(request);
            this.setResponse(response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
//FileUtil.java
package cn.net.sight.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;

public class FileUtil {
    private static final int BUFFER_SIZE = 1024;

    public void readFile(String file_Name, PrintStream ps) throws IOException {
        byte[] buffer = new byte[BUFFER_SIZE];
        int length;
        File file = new File("src/resources/" + file_Name);
        FileInputStream fis = null;

        if (file.exists()) {
            try {
                fis = new FileInputStream(file);
                while ((length = fis.read(buffer)) != -1) {
                    ps.write(buffer, 0, length);
                    ps.flush();
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        } else {
            ps.println("File not found");
            ps.println();
        }
    }
}
//LoginUtil.java
package cn.net.sight.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Map;
import java.util.Properties;

public class LoginUtil {
    protected boolean flag = false;
    protected Map<String, String> values;
    private static Properties properties;

    static {
        properties = new Properties();
        try {
            properties.load(new FileInputStream(new File("src/resources/property.proterties")));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public Map<String, String> getValues() {
        return values;
    }

    public void setValues(Map<String, String> values) {
        this.values = values;
    }

    // 验证用户信息的合法性(应用JDBC桥,连接数据库)
    public boolean isValid(Map<String, String> values) {

        String username = properties.getProperty("username");
        String password = properties.getProperty("password");
        if (values.get("username").equals(username)) {
            if (values.get("password").equals(password)) {
                flag = true;
                System.out.println("The user " + values.get("username") + " was log the server.");
                return flag;
            }
        } else {
            System.out.println("Forbide the " + values.get("username") + " log the server");
            return flag;
        }
        return false;
    }
}
//MessageUtil.java
package cn.net.sight.util;

import java.util.HashMap;
import java.util.Map;

public class MessageUtil {

    // schema : GET or POST
    public String getSchema(String requestMsg) {
        String[] result = new String[1];
        if (requestMsg.contains(" ")) {
            result = requestMsg.split(" ");
            requestMsg = result[0];
        }
        return requestMsg;
    }

    // get the resquestData = (filename + map<S,S>)
    public String getRequestData(String firstLineInData) {
        String[] result = new String[10];
        result = firstLineInData.split(" ");
        firstLineInData = result[1].substring(1);
        return firstLineInData;
    }

    // get the filename from the requestData
    public String getFileName(String requestData) {
        String[] result = new String[10];
        result = requestData.split("[?]");
        return result[0];
    }

    // save the info into the map<S,S>
    public Map<String, String> getValues(String requestData) {
        Map<String, String> values = new HashMap<String, String>();
        String[] result = new String[10];
        String regex = "[&=]";

        if (requestData.contains("?")) {
            result = requestData.split("[?]");
            String data_List = result[1];
            result = data_List.split(regex);
            for (int i = 0; i < result.length - 1; i += 2) {
                values.put(result[i], result[i + 1]);
            }
            return values;
        } else {
            result = requestData.split(regex);
            for (int i = 0; i < result.length - 1; i += 2) {
                values.put(result[i], result[i + 1]);
            }
            return values;
        }
    }

}

整个项目结构
这里写图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JAVA实现简易HTTP服务器 的相关文章

  • 尝试使用 Eclipse 启动 Glassfish 服务器时出现 org.apache.catalina.LifecycleException

    我一直忙于使用 angularjs 前端构建一个 REST 应用程序 使用 MAVEN jersey quickstart webapp 使用 GLASSFISH Web 服务器在 Eclipse 上开发 今天 当我开始对项目进行一些开发时
  • 如何在Spring的applicationContext.xml中指定默认范围来请求范围?

    我想让所有 bean 请求默认作用域 但是 Spring 文档说默认作用域是 Singleton 第 3 4 1 和 3 4 2 节http static springsource org spring docs 2 5 x referen
  • 如何正确配置Tomcat SSLHostConfig?

    我正在按照本教程在 tomcat 中启用 ssl https medium com raupach how to install lets encrypt with tomcat 3db8a469e3d2 https medium com
  • firestore快照监听器生命周期和定价之间有什么关系?

    在我的活动中 我有一个字符串列表 这些字符串表示我想要附加快照侦听器的 Firestore 文档 我使用 Acivity ModelView 存储库结构 在活动的 onCreate 中 我向 ViewModelProvider 询问适当的
  • 如何在具有动态列的表中插入值 Jdbc/Mysql

    我想在具有动态列的表中添加值 我设法创建一个包含动态列的表 但我不知道如何插入数据 Create Table sql CREATE TABLE MyDB myTable level INTEGER 255 int columnNumber
  • 如何模拟一个方面

    我目前正在使用aspectj 开发一些监控工具 因为这个工具应该是技术独立的 尽可能 所以我没有使用 Spring 进行注入 但我希望我的方面能够经过单元测试 方面示例 Aspect public class ClassLoadAspect
  • getClassLoader().getResource() 返回 null

    我有这个测试应用程序 import java applet import java awt import java net URL public class Test extends Applet public void init URL
  • 会话 bean 中的 EntityManager 异常处理

    我有一个托管无状态会话 bean 其中注入了 EntityManager em 我想做的是拥有一个具有唯一列的数据库表 然后我运行一些尝试插入实体的算法 但是 如果实体存在 它将更新它或跳过它 我想要这样的东西 try em persist
  • 您能让 Tomcat 6 stdout.log 文件表现得像 log4j DailyRollingFileAppender 吗?

    我们使用的是 Tomcat 6 的 Windows 安装 默认情况下 我们应用程序的 log4j 输出将转到 catalina base logs stdout log 文件 该日志文件仅在我们重新启动 Tomcat 时滚动 并且文件名始终
  • java 属性文件作为枚举

    是否可以将属性文件转换为枚举 我有一个包含很多设置的属性文件 例如 equipment height equipment widht equipment depth and many more like this and not all a
  • 如何在将数据发送到 Firebase 数据库之前对其进行加密?

    我正在使用 Firebase 实时数据库制作聊天应用程序 我知道 Firebase 非常安全 只要您的规则正确 但我自己可以阅读使用我的应用程序的人的所有聊天记录 我想阻止这种情况 为此我需要一种解密和加密方法 我尝试使用凯撒解密 但失败了
  • 通用 JSF 实体转换器[重复]

    这个问题在这里已经有答案了 我正在编写我的第一个 Java EE 6 Web 应用程序作为学习练习 我没有使用框架 只是使用 JPA 2 0 EJB 3 1 和 JSF 2 0 我有一个自定义转换器 用于将存储在 SelectOne 组件中
  • @TestPropertySource 不适用于 Spring 1.2.6 中使用 AnnotationConfigContextLoader 的 JUnit 测试

    似乎我在 Spring 4 1 17 中使用 Spring Boot 1 2 6 RELEASE 所做的任何事情都不起作用 我只想访问应用程序属性并在必要时通过测试覆盖它们 无需使用 hack 手动注入 PropertySource 这不行
  • Android同步onSensorChanged?

    这是我的问题的后续 Android线程可运行性能 https stackoverflow com questions 36395440 android thread runnable performance 我在理解应用程序的同步方法时遇到
  • JDK 7 的快速调试/调试构建

    我正在寻找 JDK 的调试 或者我猜他们称之为快速调试构建 以启用在运行时生成的打印程序集以及查找性能问题时所需的其他诊断 就目前情况而言 我似乎找不到可以直接使用的 现成的 快速调试构建二进制包 有人可以帮我提供下载链接 或者至少提供有关
  • 日期时间解析异常

    解析日期时 我的代码中不断出现异常错误 日期看起来像这样 Wed May 21 00 00 00 EDT 2008 这是尝试读取它的代码 DateTimeFormatter formatter DateTimeFormatter ofPat
  • 使用 Android 的 Mobile Vision API 扫描二维码

    我跟着这个tutorial http code tutsplus com tutorials reading qr codes using the mobile vision api cms 24680关于如何构建可以扫描二维码的 Andr
  • Java 9 中紧凑字符串和压缩字符串的区别

    有什么优点紧凑的字符串 http openjdk java net jeps 254JDK9 中的压缩字符串 压缩字符串 Java 6 和紧凑字符串 Java 9 都有相同的动机 字符串通常实际上是 Latin 1 因此浪费了一半的空间 和
  • 将隐藏(生物识别)数据附加到 pdf 上的数字签名

    我想知道是否可以使用 iText 我用于签名 或 Java 中的其他工具在 pdf 上添加生物识别数据 我会更好地解释一下 在手写板上签名时 我会收集签名信息 例如笔压 签名速度等 我想将这些信息 java中的变量 与pdf上的签名一起存储
  • 如何使用 Spring AOP 建议静态方法?

    在执行类的静态方法之前和之后需要完成一些日志记录 我尝试使用 Spring AOP 来实现这一点 但它不起作用 而对于正常方法来说它起作用 请帮助我理解如何实现这一点 如果可以使用注释来完成 那就太好了 也许您应该在使用 Spring AO

随机推荐

  • [3dsMax]2018版下拉菜单项的子菜单无法选中

    软件自身问题 安装更新补丁即可解决 不想更新补丁也可以使用键盘的方向键进行选中 补丁百度云链接 https pan baidu com s 1LDxRFwQnR0GSONuz7wcEfA 提取码 6gpk
  • 面试高频的CMS回收器

    CMS回收器 低延迟 想了解更多GC垃圾回收器的知识 可以看下面这篇文章JVM之垃圾回收篇 在JDK1 5时期 Hotspot推出了一款在强交互应用中几乎可认为有划时代意义的垃圾收集器 CMS Concurrent Mark Sweep 收
  • CROSSFORMER: A VERSATILE VISION TRANSFORMER BASED ON CROSS-SCALE ATTENTION 论文阅读笔记

    CROSSFORMER A VERSATILE VISION TRANSFORMER BASED ON CROSS SCALE ATTENTION 论文阅读笔记 这是浙大 腾讯 哥伦比亚大学一起发表在ICCV的一篇文章 文章有三个贡献 一是
  • python-数据分析-numpy、pandas、matplotlib的常用方法

    一 numpy import numpy as np 1 numpy 数组 和 list 的区别 输出方式不同 里面包含的元素类型 2 构造并访问二维数组 使用 索引 切片 访问ndarray元素 切片 左闭右开 np array list
  • javascript,声明变量和导入时,大括号的特殊用法

    作为一个新手 今天看到一段奇怪的代码 定义变量时用大括号把变量名括起来了 还有import时也使用了大括号 import getToken from utils auth let data request 一脸懵 这是啥意思 度娘一番 记录
  • 【读书笔记】-《工业互联网-技术与实践》

    前言 现在的技术发展潮流 基本上往大数据 人工智能的方向发展 但是归根结底 是什么推动了这些技术产业的发展 是什么支撑的 主要说的话 这和互联网的发展息息相关 也就是说现在一些主要的发达国家是如何拓展先技术新领域 并且如何把这些新技术应用到
  • Jina 2.0 快速入门指"北"

    What Why 选择Jina的4大理由 支持所有数据类型 大规模索引和查询任何类型的非结构化数据 视频 图像 长文本 语音 源代码 PDF等 速度极快 云原生 从第一天开始 Jina就是分布式架构 具有可扩展和云原生的设计 支持容器 并行
  • shell脚本 for循环实现文件和目录遍历

    一个for循环实现一个目录下的文件和目录遍历 很实用 root localhost shell order cat test27 sh bin bash print the directory and file for file in ho
  • 浅谈数据挖掘

    一 数据挖掘起源 人们迫切希望能对海量数据进行深入分析 发现并提取隐藏在其中的信息 以更好地利用这些数据 但仅以数据库系统的录入 查询 统计等功能 无法发现数据中存在的关系和规则 无法根据现有的数据预测未来的发展趋势 更缺乏挖掘数据背后隐藏
  • 面试经典算法-回文数判断,最长回文子串

    01 回文数 Leetcode 09 回文数 判断一个整数是否是回文数 回文数是指正序 从左向右 和倒序 从右向左 读都是一样的整数 比如20200202就是一个回文数 判断回文数有三种解法 1 一般解法 将整数转为字符串 然后将字符串分割
  • 如何理解电容的阻抗-频率曲线

    B站视频讲解 https www bilibili com video BV1vz4y197kP p 3 今天我们来说一说电容的阻抗频率曲线 首先呢 为什么要讲这个呢 那是因为这个非常重要 对我们使用电容有很大的指导意义 电容阻抗 频率曲线
  • 程序员必知的23种设计模式之组合模式

    文章目录 1 模式引出 学校院系展示需求 1 1 传统方案 1 2 传统方案问题分析 2 组合模式基本介绍 2 1 方案修改 3 组合模式解决的问题 4 组合模式的注意事项和细节 1 模式引出 学校院系展示需求 编写程序展示一个学校院系结构
  • 苹果数据恢复软件:Omni Recover Mac

    Omni Recover是一款十分实用的Mac数据恢复软件 为用户提供了简单 安全 快速和高效的数据恢复服务 如果您遇到了Mac或iOS设备中的数据丢失和误删情况 不要着急 不妨尝试一下Omni Recover 相信它一定会给您带来惊喜 首
  • LeetCode题目笔记——17.19消失的两个数字

    文章目录 题目描述 题目难度 困难 方法一 暴力 代码 代码优化 方法二 数学方法 代码 总结 题目描述 题目直达 题目难度 困难 方法一 暴力 虽然题目说你能在 O N 时间内只用 O 1 的空间找到它们吗 但是也没有限制我们不能用暴力
  • 深度学习之学习路线

    本文知识来源参考网络与专业书籍 文章目录 一 先简单认识什么是深度学习 二 深度学习之学习路线推荐 1 学习基础 2 学习书籍与视频推荐 一 先简单认识什么是深度学习 直接看图 深度学习是属于人工智能 再细分下来就是深度学习是一种比较火的机
  • Scala安装教程

    1 Scala官网滑到最下面如图 选择Allversions 2 我们将下载2 12 16版本 如图下 3 选scala 2 12 16 zip安装 4 先将scala 2 12 16zip解压为文件夹我解压到了D盘的scalal文件夹下面
  • 计算机网络物理层概述

    物理层 一 物理层基本概念 用于物理层协议常被称为物理层规程 物理层有四个特性 1 机械特性 指明接口所用接线器的形状和尺寸 引脚数目和排列 固定和锁定装置等 平时常见的各种规格的插件都有严格的标准化规定 2 电器特性 指明在接口电缆的各条
  • OpenSSL生成密钥对

    OpenSSL工具安装 Linux用户 以Ubuntu为例 sudo apt get install openssl Windows用户 开发者可以在OpenSSL官方网站下载Windows的 OpenSSL安装包 进行安装 RSA私钥及公
  • 泰勒公式的介绍、应用及常见题型

    目录 一 简介 1 泰勒公式及其证明过程 2 两种类型的余项 3 麦克劳林公式 二 泰勒公式常见题型 1 用泰勒公式展开函数 2 用泰勒公式求极限 3 用泰勒公式讨论无穷小的比较 4 用泰勒公式证明等式和不等式 一 简介 1 泰勒公式及其证
  • JAVA实现简易HTTP服务器

    说实话 之前完全没有想过 我还能写出服务器 感觉服务器这么高端的东西 能会用就不错了 还能写 不吐槽了 开始了 这次的作业是搭建一个服务器 要能接收请求 并给浏览器返回正确响应 项目的下载地址 项目目标 实现一个简易的多线程服务器 可以处理