linuxc语udp发送程序

news/2024/5/18 15:59:36 标签: udp, 网络协议, 网络

以下是一个基于UDP通信的C程序,用于发送含有指定格式的数据包。该程序把数据分成若干个包,每个包包含4字节数据包头+数据长度+数据内容,每个包最大8192字节。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>

#define MAX_PACKET_SIZE 8192

int main() {
    int sockfd;
    struct sockaddr_in server_addr;
    char *data = "Your data goes here.";
    int data_len = strlen(data);
    int packet_count = (data_len + MAX_PACKET_SIZE - 1) / MAX_PACKET_SIZE; // calculate total packet count

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("Error opening socket");
        exit(1);
    }

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // set to destination IP
    server_addr.sin_port = htons(12345); // set to destination port

    for (int i = 0; i < packet_count; i++) {
        char packet[MAX_PACKET_SIZE + 8]; // 4 bytes header + 4 bytes length + MAX_PACKET_SIZE data
        int current_len = (i == packet_count - 1) ? (data_len - i * MAX_PACKET_SIZE) : MAX_PACKET_SIZE; // calculate current packet length
        *(int*)packet = htonl(0x12345678); // 4 bytes header
       /*
        *(int*)packet 表示将 packet 的地址强制转换为 int* 类型的指针,并通过解引用操作符 * 获取该地址指向的 int 值。由于 packet 是一个 char 类型数组,对其进行强制类型转换可以让我们将其视为 int 类型的指针,从而访问以 int 为单位的数据。
        */
        *(int*)(packet + 4) = htonl(current_len); // 4 bytes length
        memcpy(packet + 8, data + i * MAX_PACKET_SIZE, current_len); // data

        sendto(sockfd, packet, current_len + 8, 0, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)); // send packet
    }

    close(sockfd);
    return 0;
}

好的,下面是一个简单的示例代码,演示了发送 UDP 数据包的函数定义以及调用。在这个示例中,我通过一个 send_udp_packets 函数来发送 UDP 数据包,其中除了 int sockfd 之外的其他整数类型都定义为 unsigned int 类型。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>

void send_udp_packets(int sockfd, struct sockaddr_in *server_addr, unsigned int custom_header, char *data, unsigned int data_len) {
    // 构造数据包
    char packet[1024]; // 假设数据包最大长度为 1024
    // 填入自定义头部
    memcpy(packet, &custom_header, sizeof(unsigned int));
    // 填入数据
    memcpy(packet + sizeof(unsigned int), data, data_len);
    
    // 发送数据包
    sendto(sockfd, packet, sizeof(unsigned int) + data_len, 0, (struct sockaddr *)server_addr, sizeof(struct sockaddr_in));
}

int main() {
    // 创建 UDP 套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 服务器地址
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(12345);  // 假设端口号为 12345
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 假设服务器 IP 地址为 127.0.0.1

    // 要发送的数据
    char data[] = "Hello, UDP World!";
    unsigned int custom_header = 0x12345678; // 自定义头部
    unsigned int data_len = strlen(data); // 数据长度

    // 发送数据包
    send_udp_packets(sockfd, &server_addr, custom_header, data, data_len);

    // 关闭套接字
    close(sockfd);

    return 0;
}

在这个示例中,我们定义了一个 send_udp_packets 函数,它使用 unsigned int 类型来表示自定义头部和数据长度。然后在 main 函数中,我们创建了一个 UDP 套接字,定义了服务器地址和要发送的数据,并最终调用了 send_udp_packets 函数来发送 UDP 数据包。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>

#define MAX_PACKET_SIZE 8192

void send_udp_packets(int sockfd, struct sockaddr_in *server_addr, char *data, int data_len, unsigned int header1, unsigned int header2, unsigned int header3) {
    int packet_count = (data_len + MAX_PACKET_SIZE - 1) / MAX_PACKET_SIZE; // 计算总的数据包数量

    for (int i = 0; i < packet_count; i++) {
        char packet[MAX_PACKET_SIZE + 12]; // 4字节头部 + 4字节长度 + 3个4字节自定义头部 + MAX_PACKET_SIZE数据
        int current_len = (i == packet_count - 1) ? (data_len - i * MAX_PACKET_SIZE) : MAX_PACKET_SIZE; // 计算当前数据包长度
        *(int*)packet = htonl(header1); // 第1个4字节自定义头部
        *(int*)(packet + 4) = htonl(header2); // 第2个4字节自定义头部
        *(int*)(packet + 8) = htonl(header3); // 第3个4字节自定义头部
        *(int*)(packet + 12) = htonl(current_len); // 4字节长度
        memcpy(packet + 16, data + i * MAX_PACKET_SIZE, current_len); // 数据

        sendto(sockfd, packet, current_len + 12, 0, (struct sockaddr *)server_addr, sizeof(struct sockaddr)); // 发送数据包
    }
}

int main() {
    int sockfd;
    struct sockaddr_in server_addr;
    char *data = "Your data goes here.";
    int data_len = strlen(data);
    unsigned int custom_header1 = 0xabcdef01;
    unsigned int custom_header2 = 0x12345678;
    unsigned int custom_header3 = 0xdeadbeef;

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("Error opening socket");
        exit(1);
    }

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 设置目标IP地址
    server_addr.sin_port = htons(12345); // 设置目标端口

    send_udp_packets(sockfd, &server_addr, data, data_len, custom_header1, custom_header2, custom_header3); // 调用发送函数发送数据包
    

    unsigned int network_header1 = htonl( custom_header1);
    printf("htonl(header1): 0x%08x\n", network_header1);

    close(sockfd);
    return 0;
}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>

int initialize_udp_socket(struct sockaddr_in *server_addr, int port) {
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("Error opening socket");
        return -1;
    }

    memset(server_addr, 0, sizeof(*server_addr));
    server_addr->sin_family = AF_INET;
    server_addr->sin_addr.s_addr = htonl(INADDR_ANY); // 设置目标IP地址
    server_addr->sin_port = htons(port); // 设置目标端口

    return sockfd;
}

void send_udp_packets(int sockfd, struct sockaddr_in *server_addr, char *data, int data_len, unsigned int header1, unsigned int header2, unsigned int header3) {
    // 发送数据包的函数保持不变
}

int main() {
    struct sockaddr_in server_addr;
    char *data = "Your data goes here.";
    int data_len = strlen(data);
    int port = 12345;
    unsigned int custom_header1 = 0xabcdef01;
    unsigned int custom_header2 = 0x12345678;
    unsigned int custom_header3 = 0xdeadbeef;

    int sockfd = initialize_udp_socket(&server_addr, port);
    if (sockfd == -1) {
        exit(1);
    }

    send_udp_packets(sockfd, &server_addr, data, data_len, custom_header1, custom_header2, custom_header3);

    close(sockfd);
    return 0;
}

htonl函数大小端转换:

unsigned int network_header1 = htonl( custom_header1);
    printf("htonl(header1): 0x%08x\n", network_header1);

htonl(header1): 0x01efcdab

当接收到数据后,您可以使用printf函数将接收到的数据以十六进制形式打印出来。下面
是修改后的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>

#define MAX_PACKET_SIZE 1024

void save_to_hex_file(unsigned char *data, unsigned int length) {
    FILE *file = fopen("received_data.txt", "w");
    if (file == NULL) {
        perror("file opening failed");
        return;
    }

    for (unsigned int i = 0; i < length; ++i) {
        fprintf(file, "%02X ", data[i]);
    }

    fclose(file);
}

int main() {
    // 创建 UDP 套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 绑定地址
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY; // 接收所有地址的数据包
    server_addr.sin_port = htons(12345); // 假设端口号为 12345

    if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    // 接收数据
    unsigned char buffer[MAX_PACKET_SIZE];
    struct sockaddr_in client_addr;
    unsigned int len = sizeof(client_addr);
    int recv_len = recvfrom(sockfd, buffer, MAX_PACKET_SIZE, 0, (struct sockaddr *)&client_addr, &len);
    if (recv_len < 0) {
        perror("recvfrom failed");
        exit(EXIT_FAILURE);
    }

    // 打印接收到的数据
    for (int i = 0; i < recv_len; ++i) {
        printf("%02X ", buffer[i]);
    }
    printf("\n"); // 换行

    // 保存接收到的数据到文件
    save_to_hex_file(buffer, recv_len);

    printf("Received data saved to received_data.txt\n");

    // 关闭套接字
    close(sockfd);

    return 0;
}

在这个修改后的示例中,我添加了一个循环,用于通过printf函数将接收到的数据以十六进制形式打印出来。同时,原有的将数据保存到文件的功能也保留了下来。


http://www.niftyadmin.cn/n/5248971.html

相关文章

Maven——坐标和依赖

Maven的一大功能是管理项目依赖。为了能自动化地解析任何一个Java构件&#xff0c;Maven就必须将它们唯一标识&#xff0c;这就依赖管理的底层基础——坐标。将详细分析Maven坐标的作用&#xff0c;解释其每一个元素&#xff1b;在此基础上&#xff0c;再介绍如何配置Maven&…

【深入剖析K8s】第四章 K8S集群搭建与配置

使用kubeadm工具来部署K8S K8S 部署利器: kubeadm 2017年一个独立的部署工具才终于诞生名叫kubeadm。这个项目的目标就是要让用户能够通过如下两条指令部署—个Kubernetes集群: # 创建一个Master 节点 kubeadm init# 将一个Node节点加入当前集群 Kubeadm join <Master 节…

List forEach基础操作

介绍 该forEach()方法是Stream接口的一部分&#xff0c;用于执行由定义的指定操作Consumer。 的Consumer接口表示需要一个参数作为输入的任何操作&#xff0c;并且没有输出。这种行为是可以接受的&#xff0c;因为该forEach() 方法用于通过副作用而不是显式的返回类型来更改程序…

CGAL的3D简单网格数据结构

由具有多个曲面面片的多面体曲面生成的多域四面体网格。将显示完整的三角剖分&#xff0c;包括属于或不属于网格复合体、曲面面片和特征边的单元。 1、网格复合体、 此软件包致力于三维单纯形网格数据结构的表示。 一个3D单纯形复杂体由点、线段、三角形、四面体及其相应的组合…

spark链接hive时踩的坑

使用spark操作hive&#xff0c;使用metastore连接hive&#xff0c;获取hive的数据库时&#xff0c;当我们在spark中创建数据库的时候&#xff0c;创建成功。 同时hive中也可以看到这个数据库&#xff0c;建表插入数据也没有问题&#xff0c;但是当我们去查询数据库中的数据时&a…

C++ SEH结构化异常捕获处理(双平台支持 Linux、Windows)。

测试&#xff1a; try_ctor();try_call([](){printf("1111111111111111111111\r\n");int* p NULL;*p 100;throw 1;// try_eeh();}, [](){printf("2222222222222222222222\r\n");}); 设置NULL指针P的值引发程式崩溃&#xff0c;可以被正确捕获&#xff0…

【后端学前端学习记录】第一天 css动画 内凹导航栏

1、学习信息 css动画 内凹导航栏_哔哩哔哩_bilibili 随便找的的视频&#xff0c;主要原因是在公司不方便有声音 2、源码 最终源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title…

python打开相机,用鼠标左键框选矩形区域,支持一次框选多个矩形区域,通过鼠标右标清除上一次画的矩形。

方案一 import cv2# Global variables rectangles [] current_rectangle [] drawing False# Mouse callback function def mouse_callback(event, x, y, flags, param):global rectangles, current_rectangle, drawingif event cv2.EVENT_LBUTTONDOWN:drawing Truecurren…