首页 > 解决方案 > C 中网络服务器的非 ASCII 字符

问题描述

我目前正在做一个用 C 编程的 Web 服务器。目前我正在苦苦挣扎,因为我不知道如何很好地管理非 ASCII 字符。我的意思是:

假设我将在导航栏中输入:localhost:8080/ñndex.html

我需要的是正确处理路径。如果我打印如何在服务器中获取它,我会得到

%C3%B1ndex.html

没关系,我得到了 UTF-8 的一种表示形式(我的意思是我只得到 C3 和 B1)。但问题是我如何将其转换为类似

\xC3\xB1ndex.html

这样我就可以处理它并将文件ñndex.html提供给客户。

标签: c

解决方案


不要太聪明。这本身就足够短以至于它不需要库,但足够复杂以至于我们必须小心地把它做好。另一方面,我并不是要你不要使用图书馆。如果你想用一个,就用一个。但图书馆购物是题外话。

这是一个从 URL 中提取路径(并且仅是路径)的例程。

我习惯于将参数传递给仍然完全编码的服务器脚本并让脚本处理解码,因此要提取脚本部分,在 ? 和可选的#。这是微不足道的。(# 真的不应该在那里,但我以前见过愚蠢的东西。)

static int hexdigit(char c)
{
    return (c >= '0' && c <= '9')
        ? c - '0'
        : (c >= 'A' && c <= 'F')
            ? c - 'A' + 10
            : (c >= 'a' && c <= 'f')
               ? c - 'a' + 10
               : -1;
}

/* returns NULL on any error; check errno */
char *get_path(const char *url)
{
    size_t pathlen = 0;
    const char *s;
    while (*s = url; *s && *s != '?' && *s != '#') {
        ++pathlen;
        if (*s == '%') {
            if (hexdigit(s[1]) < 0 || hexdigit(s[2]) < 0) {
                  errno = EINVAL;
                  return NULL;
            }
            s += 2;
        }
        ++pathlen;
        ++s;
    }
    char *path == malloc(pathlen + 1);
    if (!path) return NULL;
    char *t = path;
    while (*s = url; *s && *s != '?' && *s != '#') {
        if (*s == '%') {
            *t = (hexdigit(s[1]) << 4) + hexdigit(s[2]);
            s += 3;
        } else if (s == '+')
            *t++ = ' ';
            ++s;
        } else {
            *t++ = *s++;
        }
    }
    *t = 0;
    return path;
}

C 中的标准工作方式:我们进行两遍,第一遍验证输入,找到结尾并测量所需的输出空间,第二遍生成输出。


推荐阅读