C语言sendto如何发送十六进制数据?

99ANYc3cd6
预计阅读时长 21 分钟
位置: 首页 C语言 正文

这里的“十六进制”通常有两种理解:

c语言sendto十六进制
(图片来源网络,侵删)
  1. 发送字符串形式的十六进制:你想发送的字节是 0x48, 0x65, 0x6C, 0x6C, 0x6F,但你实际发送的是 ASCII 字符串 "48656C6C6F"
  2. 发送原始的十六进制字节值:这才是最常见的情况,你想直接发送 0x48, 0x65, 0x6C, 0x6C, 0x6F 这五个字节本身,而不是它们的字符串表示。

下面我将详细讲解这两种情况,并提供完整的代码示例。


发送原始的十六进制字节值 (最常用)

这是真正的“十六进制数据”传输,你的数据在内存中就是以字节形式存在的,sendto 的任务就是把这些字节原封不动地通过网络发出去。

核心思想

  1. 准备数据:将你的十六进制数(如 0x31, 0x32, 0x33)存入一个 char 数组或 uint8_t 数组中。char 在 C 语言中本质上是1字节,非常适合此场景。
  2. sendto 调用:将这个数组的地址作为 sendtobuf 参数,数组的长度作为 len 参数。

示例:发送 0x31, 0x32, 0x33, 0x0A

假设我们要发送四个字节:0x31, 0x32, 0x33, 0x0A,在 ASCII 码中,这四个字节分别对应字符 '1', '2', '3', '\n'

这是一个完整的 UDP 发送端示例:

c语言sendto十六进制
(图片来源网络,侵删)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main() {
    // 1. 创建 UDP socket
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }
    // 2. 定义目标服务器地址和端口
    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    // IPv4
    servaddr.sin_family = AF_INET;
    // IP 地址 (例如本地回环地址 127.0.0.1)
    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    // 端口号 (8080)
    servaddr.sin_port = htons(8080);
    // 3. 准备要发送的十六进制数据
    // 这是你想要发送的原始字节
    // 0x31, 0x32, 0x33, 0x0A 对应 "123\n"
    char hex_data[] = {0x31, 0x32, 0x33, 0x0A};
    // 或者,如果你有十六进制字符串,可以这样转换
    // const char *hex_str = "3132330A";
    // char hex_data[4];
    // for (int i = 0; i < 4; i++) {
    //     sscanf(hex_str + 2*i, "%2hhx", &hex_data[i]);
    // }
    size_t data_len = sizeof(hex_data);
    // 4. 使用 sendto 发送数据
    // ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
    //                const struct sockaddr *dest_addr, socklen_t addrlen);
    ssize_t sent_bytes = sendto(sockfd, 
                                (const void *)hex_data, 
                                data_len, 
                                0, 
                                (const struct sockaddr *)&servaddr, 
                                sizeof(servaddr));
    if (sent_bytes < 0) {
        perror("sendto failed");
    } else {
        printf("Successfully sent %zd bytes.\n", sent_bytes);
        // 打印发送的内容(以十六进制形式显示)
        printf("Sent data: ");
        for (int i = 0; i < data_len; i++) {
            printf("%02X ", (unsigned char)hex_data[i]);
        }
        printf("\n");
    }
    // 5. 关闭 socket
    close(sockfd);
    return 0;
}

代码解释

  1. char hex_data[] = {0x31, 0x32, 0x33, 0x0A};
    • 这是最关键的一步,我们直接定义了一个 char 数组,并用十六进制字面量初始化它,这些值就是我们要发送的原始数据。
  2. *`sendto(sockfd, (const void )hex_data, ...)`**
    • buf 参数是 hex_data,即我们存放数据的数组首地址。
    • len 参数是 sizeof(hex_data),即数组的长度(字节数)。
    • sendto 会将 hex_data 数组中的每一个字节(0x31, 0x32, 0x33, 0x0A)依次发送出去。

发送字符串形式的十六进制

你可能需要将一串十六进制数字("A1B2C3")作为文本消息发送,接收方收到的是字符 'A', '1', 'B', '2', 'C', '3',而不是字节 0xA1, 0xB2, 0xC3

核心思想

  1. 准备数据:直接使用一个包含十六进制字符的字符串,char data[] = "A1B2C3";
  2. sendto 调用:与普通字符串发送完全相同,sendto 会发送字符串的 ASCII 码值。

示例:发送字符串 "A1B2C3"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main() {
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }
    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    servaddr.sin_port = htons(8080);
    // 准备要发送的字符串数据
    // 注意:这是字符 'A', '1', 'B', '2', 'C', '3',而不是字节 0xA1, 0xB2, 0xC3
    char str_data[] = "A1B2C3"; 
    size_t data_len = strlen(str_data); // 使用 strlen 获取字符串长度
    ssize_t sent_bytes = sendto(sockfd, 
                                (const void *)str_data, 
                                data_len, 
                                0, 
                                (const struct sockaddr *)&servaddr, 
                                sizeof(servaddr));
    if (sent_bytes < 0) {
        perror("sendto failed");
    } else {
        printf("Successfully sent %zd bytes.\n", sent_bytes);
        printf("Sent string data: %s\n", str_data);
        printf("Sent data in hex: ");
        for (int i = 0; i < data_len; i++) {
            printf("%02X ", (unsigned char)str_data[i]);
        }
        printf("\n"); // 会输出 41 31 42 32 43 33
    }
    close(sockfd);
    return 0;
}

代码解释

  • char str_data[] = "A1B2C3";
    • 这里定义的是一个标准的 C 字符串,编译器会将其存储为 'A', '1', 'B', '2', 'C', '3', '\0'
  • sendto 发送的是这些字符的 ASCII 码
    • 'A' -> 0x41
    • '1' -> 0x31
    • 'B' -> 0x42
    • ... 以此类推。
  • 接收方收到的是6个字节(不包括 '\0'0x41, 0x31, 0x42, 0x32, 0x43, 0x33

总结与对比

特性 发送原始字节值 发送字符串形式的十六进制
数据准备 char data[] = {0xA1, 0xB2, 0xC3}; char data[] = "A1B2C3";
sendto 发送内容 原始字节 0xA1, 0xB2, 0xC3 字符的ASCII码 'A'(0x41), '1'(0x31), ...
网络传输 3个字节:A1 B2 C3 6个字节:41 31 42 32 43 33
用途 二进制协议、传感器数据、控制指令等 发送可读的十六进制文本、调试信息等
转换 如果从字符串转换,需要手动解析 无需转换,直接发送

如何选择?

  • 如果你的数据是二进制格式(图像、传感器读数、自定义协议的数据包),请使用场景一,这是最直接、最高效的方式。
  • 如果你的数据本质上是文本是十六进制字符(发送一个MAC地址 "AA:BB:CC:DD:EE:FF" 或一个校验和 "7F"),请使用场景二

希望这个详细的解释和示例能帮助你理解在 C 语言中如何使用 sendto 发送十六进制数据!

-- 展开阅读全文 --
头像
dede目录如何变成子目录?
« 上一篇 03-03
织梦fck编辑器哪里下载?安全吗?
下一篇 » 03-03

相关文章

取消
微信二维码
支付宝二维码

目录[+]