#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#define TARGET_IP "27.25.142.58"
// #define TARGET_IP "162.14.198.185"
#define TARGET_PORT 30100
#define BUFFER_SIZE 1400
#define TARGET_RATE_KB_S 500 // 目标发送速率(KB/s)
#define SEND_TIMEOUT_SEC 5 // 发送超时时间(秒)
volatile int keep_running = 1;
void int_handler(int sig)
{
keep_running = 0;
printf("\n接收到中断信号,准备退出...\n");
}
// 创建非阻塞连接
int connect_server()
{
int sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (sock_fd < 0) {
perror("socket创建失败");
return -1;
}
// 设置非阻塞
int flags = fcntl(sock_fd, F_GETFL, 0);
fcntl(sock_fd, F_SETFL, flags | O_NONBLOCK);
// 设置发送超时
struct timeval tv = { SEND_TIMEOUT_SEC, 0 };
setsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
// 连接服务器
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(TARGET_PORT);
inet_pton(AF_INET, TARGET_IP, &server_addr.sin_addr);
printf("连接 %s:%d...\n", TARGET_IP, TARGET_PORT);
if (connect(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
if (errno != EINPROGRESS) {
perror("连接失败");
close(sock_fd);
return -1;
}
// 等待连接完成
fd_set wfds;
FD_ZERO(&wfds);
FD_SET(sock_fd, &wfds);
tv.tv_sec = 5;
tv.tv_usec = 0;
if (select(sock_fd + 1, NULL, &wfds, NULL, &tv) <= 0) {
perror("连接超时");
close(sock_fd);
return -1;
}
}
printf("已连接\n");
return sock_fd;
}
int main(int argc, char* argv[])
{
signal(SIGINT, int_handler);
// 初始化缓冲区
unsigned char buffer[BUFFER_SIZE];
memset(buffer, 12, BUFFER_SIZE);
// 连接服务器
int sock_fd = connect_server();
if (sock_fd < 0)
return -1;
printf("开始发送数据 (速率:%d KB/s, 按Ctrl+C停止)\n", TARGET_RATE_KB_S);
// 计算发送间隔
long delay_us = (long)((double)BUFFER_SIZE / (TARGET_RATE_KB_S * 1024) * 1000000);
// 统计变量
unsigned long total_bytes = 0;
int packets_sent = 0;
int consecutive_errors = 0;
struct timeval start_time, current_time, last_success;
gettimeofday(&start_time, NULL);
last_success = start_time;
// 发送循环
while (keep_running) {
int bytes_sent = send(sock_fd, buffer, BUFFER_SIZE, 0);
if (bytes_sent < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
printf("缓冲区满\n");
// 缓冲区满,检查是否需要重连
gettimeofday(¤t_time, NULL);
double idle_time = (current_time.tv_sec - last_success.tv_sec)
+ (current_time.tv_usec - last_success.tv_usec) / 1000000.0;
if (idle_time > SEND_TIMEOUT_SEC) {
printf("发送超时(%.1f秒),重连...\n", idle_time);
close(sock_fd);
sleep(1);
sock_fd = connect_server();
if (sock_fd < 0)
break;
gettimeofday(&last_success, NULL);
consecutive_errors = 0;
continue;
}
usleep(100000); // 等待100ms
consecutive_errors++;
if (consecutive_errors > 10) {
sleep(1); // 连续失败时等待更久
consecutive_errors = 0;
}
continue;
} else {
printf("发送错误: %s\n", strerror(errno));
break;
}
} else if (bytes_sent == 0) {
printf("连接关闭\n");
break;
}
// 发送成功
consecutive_errors = 0;
gettimeofday(&last_success, NULL);
total_bytes += bytes_sent;
packets_sent++;
// 每10个包更新状态
if (packets_sent % 100 == 0) {
gettimeofday(¤t_time, NULL);
double elapsed
= (current_time.tv_sec - start_time.tv_sec) + (current_time.tv_usec - start_time.tv_usec) / 1000000.0;
printf("已发送: %d包, %luB, 速率: %.2fKB/s\n", packets_sent, total_bytes, (total_bytes / 1024.0) / elapsed);
}
// 控制发送速率
usleep(delay_us);
}
// 统计结果
gettimeofday(¤t_time, NULL);
double total_time
= (current_time.tv_sec - start_time.tv_sec) + (current_time.tv_usec - start_time.tv_usec) / 1000000.0;
printf("\n总计: %d包, %luB, 时间: %.2f秒, 平均速率: %.2fKB/s\n", packets_sent, total_bytes, total_time,
(total_bytes / 1024.0) / total_time);
close(sock_fd);
return 0;
}