用C语言编写一个HTTP协议的目录浏览和文件下载服务器

2023-05-16

#include <stdarg.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <resolv.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <signal.h>
#include <getopt.h>

#define DEFAULTIP "127.0.0.1"
#define DEFAULTPORT "80"
#define DEFAULTBACK "10"
#define DEFAULTDIR "/home"
#define DEFAULTLOG "/tmp/das-server.log"

void prterrmsg(char *msg);
#define prterrmsg(msg)        { perror(msg); abort(); }
void wrterrmsg(char *msg);
#define wrterrmsg(msg)        { fputs(msg, logfp); fputs(strerror(errno), logfp);fflush(logfp); abort(); }

void prtinfomsg(char *msg);
#define prtinfomsg(msg)        { fputs(msg, stdout);  }
void wrtinfomsg(char *msg);
#define wrtinfomsg(msg)        {  fputs(msg, logfp); fflush(logfp);}

#define MAXBUF        1024

char buffer[MAXBUF + 1];
char *host = 0;
char *port = 0;
char *back = 0;
char *dirroot = 0;
char *logdir = 0;
unsigned char daemon_y_n = 0;
FILE *logfp;

#define MAXPATH        150

/*----------------------------------------
*--- dir_up - 查找dirpath所指目录的上一级目录
*----------------------------------------
*/
char *dir_up(char *dirpath)
{
    static char Path[MAXPATH];
    int len;

    strcpy(Path, dirpath);
    len = strlen(Path);
    if (len > 1 && Path[len - 1] == '/')
        len--;
    while (Path[len - 1] != '/' && len > 1)
        len--;
    Path[len] = 0;
    return Path;
}

/*------------------------------------------------------
*--- AllocateMemory - 分配空间并把d所指的内容复制
*------------------------------------------------------
*/
void AllocateMemory(char **s, int l, char *d)
{
    *s = malloc(l + 1);
    bzero(*s, l + 1);
    memcpy(*s, d, l);
}
/************关于本文档********************************************
*filename: das-server.c
*purpose: 这是在Linux下用C语言写的目录访问服务器,支持目录浏览和文件下载
*wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2007-01-26 19:32
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Thanks to: Google.com
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/
/*------------------------------------------------------
*--- GiveResponse - 把Path所指的内容发送到client_sock去
*-------------------如果Path是一个目录,则列出目录内容
*-------------------如果Path是一个文件,则下载文件
*------------------------------------------------------
*/
void GiveResponse(FILE * client_sock, char *Path)
{
    struct dirent *dirent;
    struct stat info;
    char Filename[MAXPATH];
    DIR *dir;
    int fd, len, ret;
    char *p, *realPath, *realFilename, *nport;

    /* 获得实际工作目录或文件 */
    len = strlen(dirroot) + strlen(Path) + 1;
    realPath = malloc(len + 1);
    bzero(realPath, len + 1);
    sprintf(realPath, "%s/%s", dirroot, Path);

    /* 获得实际工作端口 */
    len = strlen(port) + 1;
    nport = malloc(len + 1);
    bzero(nport, len + 1);
    sprintf(nport, ":%s", port);

    /* 获得实际工作目录或文件的信息以判断是文件还是目录 */
    if (stat(realPath, &info)) {
        fprintf(client_sock,
                "HTTP/1.1 200 OK/r/nServer: DAS by ZhouLifa/r/nConnection: close/r/n/r/n<html><head><title>%d - %s</title></head>"
                "<body><font size=+4>Linux 下目录访问服务器</font><br><hr width=/"100%%/"><br><center>"
                "<table border cols=3 width=/"100%%/">", errno,
                strerror(errno));
        fprintf(client_sock,
                "</table><font color=/"CC0000/" size=+2>请向管理员咨询为何出现如下错误提示:/n%s %s</font></body></html>",
                Path, strerror(errno));
        goto out;
    }
    /* 处理浏览文件请求,即下载文件 */
    if (S_ISREG(info.st_mode)) {
        fd = open(realPath, O_RDONLY);
        len = lseek(fd, 0, SEEK_END);
        p = (char *) malloc(len + 1);
        bzero(p, len + 1);
        lseek(fd, 0, SEEK_SET);
        ret = read(fd, p, len);
        close(fd);
        fprintf(client_sock,
                "HTTP/1.1 200 OK/r/nServer: DAS by ZhouLifa/r/nConnection: keep-alive/r/nContent-type: application/*/r/nContent-Length:%d/r/n/r/n",
                len);
        fwrite(p, len, 1, client_sock);
        free(p);
    } else if (S_ISDIR(info.st_mode)) {
        /* 处理浏览目录请求 */
        dir = opendir(realPath);
        fprintf(client_sock,
                "HTTP/1.1 200 OK/r/nServer: DAS by ZhouLifa/r/nConnection: close/r/n/r/n<html><head><title>%s</title></head>"
                "<body><font size=+4>Linux 下目录访问服务器</font><br><hr width=/"100%%/"><br><center>"
                "<table border cols=3 width=/"100%%/">", Path);
        fprintf(client_sock,
                "<caption><font size=+3>目录 %s</font></caption>/n",
                Path);
        fprintf(client_sock,
                "<tr><td>名称</td><td>大小</td><td>修改时间</td></tr>/n");
        if (dir == 0) {
            fprintf(client_sock,
                    "</table><font color=/"CC0000/" size=+2>%s</font></body></html>",
                    strerror(errno));
            return;
        }
        /* 读取目录里的所有内容 */
        while ((dirent = readdir(dir)) != 0) {
            if (strcmp(Path, "/") == 0)
                sprintf(Filename, "/%s", dirent->d_name);
            else
                sprintf(Filename, "%s/%s", Path, dirent->d_name);
            fprintf(client_sock, "<tr>");
            len = strlen(dirroot) + strlen(Filename) + 1;
            realFilename = malloc(len + 1);
            bzero(realFilename, len + 1);
            sprintf(realFilename, "%s/%s", dirroot, Filename);
            if (stat(realFilename, &info) == 0) {
                if (strcmp(dirent->d_name, "..") == 0)
                    fprintf(client_sock,
                            "<td><a href=/"http://%s%s%s/">(parent)</a></td>",
                            host, atoi(port) == 80 ? "" : nport,
                            dir_up(Path));
                else
                    fprintf(client_sock,
                            "<td><a href=/"http://%s%s%s/">%s</a></td>",
                            host, atoi(port) == 80 ? "" : nport, Filename,
                            dirent->d_name);
                if (S_ISDIR(info.st_mode))
                    fprintf(client_sock, "<td>目录</td>");
                else if (S_ISREG(info.st_mode))
                    fprintf(client_sock, "<td>%d</td>", info.st_size);
                else if (S_ISLNK(info.st_mode))
                    fprintf(client_sock, "<td>链接</td>");
                else if (S_ISCHR(info.st_mode))
                    fprintf(client_sock, "<td>字符设备</td>");
                else if (S_ISBLK(info.st_mode))
                    fprintf(client_sock, "<td>块设备</td>");
                else if (S_ISFIFO(info.st_mode))
                    fprintf(client_sock, "<td>FIFO</td>");
                else if (S_ISSOCK(info.st_mode))
                    fprintf(client_sock, "<td>Socket</td>");
                else
                    fprintf(client_sock, "<td>(未知)</td>");
                fprintf(client_sock, "<td>%s</td>", ctime(&info.st_ctime));
            }
            fprintf(client_sock, "</tr>/n");
            free(realFilename);
        }
        fprintf(client_sock, "</table></center></body></html>");
    } else {
        /* 既非常规文件又非目录,禁止访问 */
        fprintf(client_sock,
                "HTTP/1.1 200 OK/r/nServer: DAS by ZhouLifa/r/nConnection: close/r/n/r/n<html><head><title>permission denied</title></head>"
                "<body><font size=+4>Linux 下目录访问服务器</font><br><hr width=/"100%%/"><br><center>"
                "<table border cols=3 width=/"100%%/">");
        fprintf(client_sock,
                "</table><font color=/"CC0000/" size=+2>你访问的资源'%s'被禁止访问,请联系管理员解决!</font></body></html>",
                Path);
    }
  out:
    free(realPath);
    free(nport);
}

/*------------------------------------------------------
*--- getoption - 分析取出程序的参数
*------------------------------------------------------
*/
void getoption(int argc, char **argv)
{
    int c, len;
    char *p = 0;

    opterr = 0;
    while (1) {
        int option_index = 0;
        static struct option long_options[] = {
            {"host", 1, 0, 0},
            {"port", 1, 0, 0},
            {"back", 1, 0, 0},
            {"dir", 1, 0, 0},
            {"log", 1, 0, 0},
            {"daemon", 0, 0, 0},
            {0, 0, 0, 0}
        };
        /* 本程序支持如一些参数:
         * --host IP地址 或者 -H IP地址
         * --port 端口 或者 -P 端口
         * --back 监听数量 或者 -B 监听数量
         * --dir 网站根目录 或者 -D 网站根目录
         * --log 日志存放路径 或者 -L 日志存放路径
         * --daemon 使程序进入后台运行模式
         */
        c = getopt_long(argc, argv, "H:P:B:D:L",
                        long_options, &option_index);
        if (c == -1 || c == '?')
            break;

        if(optarg)        len = strlen(optarg);
        else        len = 0;

        if ((!c && !(strcasecmp(long_options[option_index].name, "host")))
            || c == 'H')
            p = host = malloc(len + 1);
        else if ((!c
                  &&
                  !(strcasecmp(long_options[option_index].name, "port")))
                 || c == 'P')
            p = port = malloc(len + 1);
        else if ((!c
                  &&
                  !(strcasecmp(long_options[option_index].name, "back")))
                 || c == 'B')
            p = back = malloc(len + 1);
        else if ((!c
                  && !(strcasecmp(long_options[option_index].name, "dir")))
                 || c == 'D')
            p = dirroot = malloc(len + 1);
        else if ((!c
                  && !(strcasecmp(long_options[option_index].name, "log")))
                 || c == 'L')
            p = logdir = malloc(len + 1);
        else if ((!c
                  &&
                  !(strcasecmp
                    (long_options[option_index].name, "daemon")))) {
            daemon_y_n = 1;
            continue;
        }
        else
            break;
        bzero(p, len + 1);
        memcpy(p, optarg, len);
    }
}

int main(int argc, char **argv)
{
    struct sockaddr_in addr;
    int sock_fd, addrlen;

    /* 获得程序工作的参数,如 IP 、端口、监听数、网页根目录、目录存放位置等 */
    getoption(argc, argv);

    if (!host) {
        addrlen = strlen(DEFAULTIP);
        AllocateMemory(&host, addrlen, DEFAULTIP);
    }
    if (!port) {
        addrlen = strlen(DEFAULTPORT);
        AllocateMemory(&port, addrlen, DEFAULTPORT);
    }
    if (!back) {
        addrlen = strlen(DEFAULTBACK);
        AllocateMemory(&back, addrlen, DEFAULTBACK);
    }
    if (!dirroot) {
        addrlen = strlen(DEFAULTDIR);
        AllocateMemory(&dirroot, addrlen, DEFAULTDIR);
    }
    if (!logdir) {
        addrlen = strlen(DEFAULTLOG);
        AllocateMemory(&logdir, addrlen, DEFAULTLOG);
    }

    printf
        ("host=%s port=%s back=%s dirroot=%s logdir=%s %s是后台工作模式(进程ID:%d)/n",
         host, port, back, dirroot, logdir, daemon_y_n?"":"不", getpid());

    /* fork() 两次处于后台工作模式下 */
    if (daemon_y_n) {
        if (fork())
            exit(0);
        if (fork())
            exit(0);
        close(0), close(1), close(2);
        logfp = fopen(logdir, "a+");
        if (!logfp)
            exit(0);
    }

    /* 处理子进程退出以免产生僵尸进程 */
    signal(SIGCHLD, SIG_IGN);

    /* 创建 socket */
    if ((sock_fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
        if (!daemon_y_n) {
            prterrmsg("socket()");
        } else {
            wrterrmsg("socket()");
        }
    }

    /* 设置端口快速重用 */
    addrlen = 1;
    setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &addrlen,
               sizeof(addrlen));

    addr.sin_family = AF_INET;
    addr.sin_port = htons(atoi(port));
    addr.sin_addr.s_addr = inet_addr(host);
    addrlen = sizeof(struct sockaddr_in);
    /* 绑定地址、端口等信息 */
    if (bind(sock_fd, (struct sockaddr *) &addr, addrlen) < 0) {
        if (!daemon_y_n) {
            prterrmsg("bind()");
        } else {
            wrterrmsg("bind()");
        }
    }

    /* 开启临听 */
    if (listen(sock_fd, atoi(back)) < 0) {
        if (!daemon_y_n) {
            prterrmsg("listen()");
        } else {
            wrterrmsg("listen()");
        }
    }
    while (1) {
        int len;
        int new_fd;
        addrlen = sizeof(struct sockaddr_in);
        /* 接受新连接请求 */
        new_fd = accept(sock_fd, (struct sockaddr *) &addr, &addrlen);
        if (new_fd < 0) {
            if (!daemon_y_n) {
                prterrmsg("accept()");
            } else {
                wrterrmsg("accept()");
            }
            break;
        }
        bzero(buffer, MAXBUF + 1);
        sprintf(buffer, "连接来自于: %s:%d/n",
                inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
        if (!daemon_y_n) {
            prtinfomsg(buffer);
        } else {
            wrtinfomsg(buffer);
        }
        /* 产生一个子进程去处理请求,当前进程继续等待新的连接到来 */
        if (!fork()) {
            bzero(buffer, MAXBUF + 1);
            if ((len = recv(new_fd, buffer, MAXBUF, 0)) > 0) {
                FILE *ClientFP = fdopen(new_fd, "w");
                if (ClientFP == NULL) {
                    if (!daemon_y_n) {
                        prterrmsg("fdopen()");
                    } else {
                        prterrmsg("fdopen()");
                    }
                } else {
                    char Req[MAXPATH + 1] = "";
                    sscanf(buffer, "GET %s HTTP", Req);
                    bzero(buffer, MAXBUF + 1);
                    sprintf(buffer, "请求取文件: /"%s/"/n", Req);
                    if (!daemon_y_n) {
                        prtinfomsg(buffer);
                    } else {
                        wrtinfomsg(buffer);
                    }
                    /* 处理用户请求 */
                    GiveResponse(ClientFP, Req);
                    fclose(ClientFP);
                }
            }
            exit(0);
        }
        close(new_fd);
    }
    close(sock_fd);
    return 0;
}

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

用C语言编写一个HTTP协议的目录浏览和文件下载服务器 的相关文章

  • Transfer-Encoding: chunked添加Content-Length: 574712返回

    一 问题背景 xff1a 开发中有时候有的功能需要返回content length字段 xff0c 根据此字段进行下载进度的展示 而springboot默认在数据量大的时候是进行了Transfer Encoding chunked 设置的
  • 工具(十一):随机密码生成工具-可选择字符种类

    工具 xff08 十一 xff09 随机密码生成工具 可选择字符种类 废话少絮 xff0c 上代码 xff1a 一 可选择字符种类随机密码生成工具的实现思路 xff1a 准备好要包含的字符串 xff0c 去掉易混淆字符 xff1b 随机生成
  • K8S异常之Unable to update cni config err=no vaild network found in /etc/cni/net.d

    一 背景问题描述 我们在初始化k8s节点的时候 xff0c 可能会遇到类似如下问题Unable to update cni config err 61 no vaild network found in etc cni net d xff0
  • Docker镜像之不同服务器间迁移大法

    背景需求 有个需求 xff1a 需要将一台服务器A上的docker镜像迁移到另一台服务器B上 xff0c 并可以在服务器B上 xff0c 通过命令docker images可以查看到对应的镜像 xff08 这个镜像一般是你自己打包的镜像 x
  • CSDN云IDE浅试之体验与建议

    云IDE产品介绍 云IDE使用教程 免费使用地址 xff1a 点击 云IDE xff0c 即可开始创建工作空间啦 个人认为任何好的软件都是第一印象比较重要 从几个方面说下个人比较赞同的点 一 新建项目变的简单 体现在几个方面 xff1a 1
  • K8S异常之Unable to connect to the server: x509: certificate has expired or is not yet valid

    一 问题 xff1a k8s证书过期 root 64 nb001 kubectl get node Unable to connect to the server x509 certificate has expired or is not
  • Debian远程控制SSH和putty

    转自 http blog sina com cn s blog 6ffafb910100omeu html SSH是一种在远程传输数据时可加密的传输手段 作为远程控制的首选服务 xff0c 给数据的传输安全带来的很大的好处 在debian
  • K8S异常之Harbor证书过期处理(完整版流程)

    1 背景 如图所示 xff0c 在登录harbor仓库时 xff0c 提示证书已经过期 2 更新证书 2 1 停止harbor docker compose down span class token punctuation span ro
  • jar命令之替换已有jar包依赖库的版本

    背景 由于项目使用的是nacos1 1 4 xff0c 其依赖的fastjson的版本为1 2 58 xff0c 包含了AVD 2022 1243027和AVD 2022 1243027的 fastjson lt 61 1 2 80 反序列
  • Java项目热部署方案之IDEA-HotSwapAgent和DCEVM大法

    一 环境准备 HotSwapAgent xff08 http hotswapagent org xff09 依赖 DCEVM 而 DCEVM要求jdk版本必须对应 xff0c 如果你用的 jdk1 8 xff0c 首先需要确认安装的是jdk
  • 使用rclone将本机文件或文件夹导入minIO

    一 背景 minio大量文件上传 xff0c 通过console xff0c web端控制台上传的话是可以的 xff0c 但是文件量太大 xff0c 效率很低 xff0c 就想办法上传服务器 xff0c 然后读取服务器文件的方式进行 二 过
  • 记录一次docker容器引起的时间相差8h的问题

    一 背景 系统打印日志时间小8h xff0c 部分插入mysql的日期却大8h xff0c 简直诡异 测试时间是上午10 05 经过排查 xff0c mysql设置的时区 xff0c 链接url设置的时区都是ok的 而且有其他服务时间正常
  • c++常见面试题30道

    转自 xff1a http blog csdn net shihui512 article details 9092439 xff1b 1 new delete malloc free 关系 delete会调用对象的析构函数 和 new 对
  • __attribute__ 机制详解

    attribute 语法的来源 GNU C 的一大特色就是 attribute 机制 attribute 可以设置函数属性 xff08 Function Attribute xff09 变量属性 xff08 Variable Attribu
  • 进程和线程的理解

    一 进程和线程的概念 xff08 一句话概述 xff09 进程 xff1a 我们运行的程序通常会对应一个或多个进程 xff0c 进程是操作系统分配内存的基本单位 线程 xff1a 一个进程通常会包含一个或多个线程 xff0c 线程是操作系统
  • ubuntu中sudo apt-get install 出现 failed to fetch

    在ubuntu中 安装samba时 xff08 sudo apt get install samba xff09 出现 failed to fetch 通过以下方式成功解决了 xff1a 我直接更新了下就解决了 通过sudo apt get
  • Docker删除镜像和容器

    一 删除容器 首先需要停止所有的容器 xff08 只停止单个时把后面的变量改为image id即可 xff09 docker stop docker ps a q 删除所有的容器 xff08 只删除单个时把后面的变量改为image id即可
  • 【读书】只读经典

    本文摘自豆瓣上 八百步 的收集的资料 xff1a http book douban com review 5289501 Ch 1 xff1a 管理 1 弗雷德里克 温斯洛 泰勒著 xff0c 科学管理的基本原理 xff0c 1911年出版
  • 卸载Docker

    一 准备工作 xff1a 1 杀死docker有关的容器 xff1a docker kill docker ps a q 2 删除所有docker容器 xff1a docker rm docker ps a q 3 删除所有docker镜像
  • IDEA2020启动Tomcat控制台中文乱码解决

    IDEA2020启动Tomcat控制台中文乱码解决 1 中文乱码原因 基本上大家安装的windows系统本地语言都是选择中文 xff08 不会有人选择英文吧 xff1f 不会吧 xff1f 不会吧 xff1f xff09 xff0c 也就是

随机推荐

  • MyEclipse配置Tomcat 7

    1 打开步骤 xff1a 窗口 gt 首选项 gt MyEclipse gt Servers gt Tomcat gt Tomcat 7 x 2 配置自己本地的Tomcat 7版本 3 关闭MyEclipse自带的Tomcat服务器 4 启
  • mysql之模糊查询的方法

    Mysql模糊查询正常情况下在数据量小的时候 xff0c 速度还是可以的 xff0c 但是不容易看出查询的效率 xff0c 在数据量达到百万级 xff0c 千万级的甚至亿级时mysql查询的效率是很关键的 xff0c 也是很重要的 一 一般
  • Spring Cloud限流详解

    Spring Cloud限流详解 Spring Cloud Spring Cloud 2017 12 01 在高并发的应用中 xff0c 限流往往是一个绕不开的话题 本文详细探讨在Spring Cloud中如何实现限流 在Zuul上实现限流
  • springboot启动注解

    为什么springboot不需要配置文件就可以启动成功 springboot入口SpringBootApplication是一个启动类 xff0c 主要的注解是以下的三个 xff1a 1 SpringBootConfiguration是一个
  • 如何释放linux的内存

    你们知道怎么释放linux的内存吗不知道的话跟着学习啦小编一起来学习怎么释放linux的内存 释放linux的内存的步骤 Linux下操作频繁时 xff0c 物理内存会被快速用完 xff0c 当操作结束后 xff0c 物理内存没有被正常的释
  • 跨域的五种解决方案详解

    1 跨域解决方案一 cors技术 CORS 全称cross origin resource share xff08 资源共享 xff09 工作原理 xff1a 服务器 在返回响应报文的时候 xff0c 在响应头中 设置一个允许的header
  • MySQL 日期时间类型精确到毫秒

    MySQL 常用的日期时间类型常用的是datetime timestamp 其中datetime占用5个字节 xff08 有些文档中说占用8个字节是不对的 xff0c 默认也不会保存毫秒 xff09 DATETIME和TIMESTAMP两种
  • Spring Boot——Thymeleaf

    哈喽 xff01 大家好 xff0c 我是 xff0c 一位上进心十足的 Java领域博主 xff01 的写作风格 xff1a 喜欢用 通俗易懂 的文笔去讲解每一个知识点 xff0c 而不喜欢用 高大上 的官方陈述 博客的领域是 面向后端技
  • [BZOJ3185][Coci2011][DP]kamion

    考虑转化一下问题 令 f i j k 表示从i到j恰好用了k步 xff0c 并且到j的时候火车厢为空的方案数 那么转移就是 f i j k 61 f a b k 1 f c j k 2 xff0c 转移成立当且仅当存在i gt a的边 xf
  • 查看docker 容器的端口

    查看docker 容器的端口 sudo netstat tulpn grep docker 查看指定端口 xff0c 可以结合grep命令 xff1a netstat ap grep 80 查找指定端口使用的pid fuser 80 tcp
  • Docker服务的停止命令(systemctl stop docker)

    停止Docker服务 停止docker服务 systemctl stop docker 非root用户使用 停止docker服务 sudo systemctl stop docker
  • Docker查找镜像版本的命令

    Docker查找镜像版本的命令 有时候想查一下镜像有哪些版本 xff0c 因为有墙 xff0c 官网一直在转圈进不去 xff0c 这时候就可以使用命令查询了 xff0c 以centos为例 xff0c 自己想要哪个更改一下命令就可以了 do
  • ES6 如何将 Set 转化为数组

    例如 xff1a const mySet 61 new Set Set 对象具有以下特征 xff1a Set 实例的成员唯一 xff0c 不会重复 Set 实例可以存储任何类型的值 xff0c 包括基本类型和对象 Set 实例是可迭代的 x
  • Request.url用法

    網址 xff1a http localhost 1897 News Press Content aspx 123 id 61 1 toc Request ApplicationPath Request PhysicalPath D Proj
  • oracle IO 优化

    数据库的作用就是实现对数据的管理和查询 任何一个数据库系统 xff0c 必然存在对数据的大量读或者写或者两中操作都大量存在 IO问题也往往是导致数据库性能问题的重要原因 在这篇文章中 xff0c 主要帮助大家在理解Oracle的读写操作机制
  • oracle中imp命令详解

    oracle中imp命令详解 Oracle的导入实用程序 Import utility 允许从数据库提取数据 xff0c 并且将数据写入操作系统文 件 imp使用的基本格式 xff1a imp username password 64 se
  • C# 非顶端窗口截图

    panel上可以通过DrawToBitmap截图 xff0c 不管是否在屏幕外是否有遮挡 Bitmap sourceBitmap 61 new Bitmap 400 300 Control ct 61 frmMain mianForm pa
  • bat中的特殊字符,以及需要在bat中当做字符如何处理

    bat中的特殊字符 xff0c 以及需要在bat中当做字符如何处理 批处理 Bat 中特殊符号的实际作用 xff0c Windows 批处理中特殊符号的作用 xff1a 64 隐藏命令的回显 在for中表示使用增强的变量扩展 xff1b 在
  • rviz无法显示的问题

    1 启用初始化配置 首先删除保存好的rviz xff0c 运行最初始化的配置 rviz运行后会选择保存在 home cbc rviz default rviz 删除之后 xff0c 重新运行 xff1a roscore rosrun rvi
  • 用C语言编写一个HTTP协议的目录浏览和文件下载服务器

    include lt stdarg h gt include lt errno h gt include lt stdio h gt include lt fcntl h gt include lt unistd h gt include