linuxc语udp发送程序
2023-12-14 15:47:31
以下是一个基于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函数将接收到的数据以十六进制形式打印出来。同时,原有的将数据保存到文件的功能也保留了下来。
文章来源:https://blog.csdn.net/weixin_38849487/article/details/134870796
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!