繁体   English   中英

sprintf 原始字节到 C 中的字符串?

[英]sprintf raw bytes to string in C?

我在 C 中通过网络发送一些原始字节(使用 HTTP)。 我目前正在这样做:

// response is a large buffer
int n = 0; // response length
int x = 42; // want client to read x
int y = 43; // and y 

// write a simple HTTP response containing a 200 status code then x and y in binary format
strcpy(response, "HTTP/1.1 200\r\n\r\n");
n += 16; // status line we just wrote is 16 bytes long
memcpy(response + n, &x, sizeof(x));
n += sizeof(x);
memcpy(response + n, &y, sizeof(y));
n += sizeof(y);
write(client, response, n);

在 JavaScript 中,我然后使用如下代码读取这些数据:

request = new XMLHttpRequest();
request.responseType = "arraybuffer";
request.open("GET", "/test");
request.onreadystatechange = function() { if (this.readyState === XMLHttpRequest.DONE) { console.log(new Int32Array(this.response)) } }
request.send();

它应该打印[42, 43]

我想知道在服务器端是否有更优雅的方法来做到这一点,例如

n += sprintf(response, "HTTP/1.1 200\r\n\r\n%4b%4b", &x, &y);

其中%4b是一个虚构的格式说明符,它只是说:将该地址中的 4 个字节复制到字符串中(即“*\\0\\0\\0”)是否有像虚构的%4b这样的格式说明符像这样的东西?

这是一个 XY 问题,您是在询问如何使用sprintf()来解决您的问题,而不是简单地询问如何解决您的问题。 您的实际问题是如何使该代码更“优雅”。

没有特别的理由在单个写操作中发送数据 - 网络堆栈缓冲将确保数据有效地打包:

static const char header[] = "HTTP/1.1 200\r\n\r\n" ;
write( client, header, sizeof(header) - 1 ) ;
write( client, &x, sizeof(x) ) ;
write( client, &y, sizeof(y) ) ; 

请注意,X 和 Y 将以本机机器字节顺序写入,这在接收方可能不正确。 更一般地说:

static const char header[] = "HTTP/1.1 200\r\n\r\n" ;
write( client, header, sizeof(header) - 1 ) ;

uint32_t nl = htonl( x ) ;
write( client, &nl, sizeof(nl) ) ;

nl = htonl( y ) ;
write( client, &nl, sizeof(nl) ) ; 

是否有像虚构的 %4b 这样的格式说明符?

不,没有,你的方法很好。 我建议使用snprintf和一些检查来避免缓冲区溢出,添加 ex。 static_assert(sizeof(int) == 4, "")检查平台是否使用大端和类似环境以及错误处理并避免未定义的行为检查。

也就是说,您可以多次使用%c printf 说明符,例如"%c%c%c%c", ((char*)&x)[3], ((char*)&x)[2], ((char*)&x)[1], ((char*)&x)[0]打印 4 个字节。 您可以将其包装在宏中并执行以下操作:

#include <stdio.h>

#define PRI_BYTES_4  "%c%c%c%c"
#define ARG_BYTES_BE_4(var) \
    ((const char*)&(var))[3], \
    ((const char*)&(var))[2], \
    ((const char*)&(var))[1], \
    ((const char*)&(var))[0]

int main() {
    int var = 
        'l' << 24 |
        'a' << 16 | 
        'm' << 8 |
        'e';
    printf("Hello, I am " PRI_BYTES_4 ".\n",
        ARG_BYTES_BE_4(var));
    // will print `Hello, I am lame.`
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM