如果 send
函数调用失败且需要重新建立 TCP socket,可以在 send
失败后进行适当的处理。以下是一个示例,展示了如何在发送数据时检查错误,并在发生特定错误时重新建立 TCP socket。
假设我们已经有一个创建和连接 TCP socket 的函数,以及发送心跳和 CPU 使用情况的代码。我们可以添加一个重试机制来处理 send
失败的情况。
下面是更新后的代码示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/timerfd.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define SERVER_PORT 12345 // 假设服务器端口为 12345
#define SERVER_IP "127.0.0.1" // 假设服务器 IP 为本地地址
int create_tcp_socket() {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket");
return -1;
}
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr);
if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("connect");
close(sockfd);
return -1;
}
return sockfd;
}
void record_cpu_usage() {
static long prev_idle = 0;
static long prev_total = 0;
FILE *fp = fopen("/proc/stat", "r");
if (!fp) {
perror("fopen");
return;
}
char buffer[256];
fgets(buffer, sizeof(buffer), fp);
long user, nice, system, idle, iowait, irq, softirq;
sscanf(buffer,"cpu %ld %ld %ld %ld %ld %ld %ld",&user,&nice,&system,&idle,&iowait,&irq,&softirq);
long total = user + nice + system + idle + iowait + irq + softirq;
long diff_idle = idle - prev_idle;
long diff_total = total - prev_total;
if (diff_total > 0) {
double cpu_usage = (double)(diff_total - diff_idle) / diff_total * 100.0;
printf("CPU Usage: %.2f%%\n", cpu_usage);
}
prev_idle = idle;
prev_total = total;
fclose(fp);
}
void heartbeat(int sockfd) {
const char *message = "Heartbeat: System is alive!\n";
ssize_t bytes_sent = send(sockfd, message, strlen(message), 0);
if (bytes_sent < 0) {
perror("send failed");
// 如果发送失败,尝试重新建立TCP连接
close(sockfd); // 首先关闭旧的socket
sockfd = create_tcp_socket(); // 创建新的socket
if (sockfd >= 0) {
printf("Reconnected to the server.\n");
// 可以考虑重发之前的数据(如心跳),这里仅作为示例。
send(sockfd,message ,strlen(message), 0);
} else {
fprintf(stderr,"Failed to reconnect to the server.\n");
}
} else{
printf("%s", message); // 打印已成功发送的消息
}
}
void monitor_cpu_and_send_heartbeat(int tfd) {
uint64_t expirations;
int heartbeat_counter = 0;
int sockfd = create_tcp_socket(); // 建立初始TCP连接
if (sockfd < 0) return; // 如果连接失败则返回
while (1) {
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(tfd ,&readfds);
select(tfd +1 , &readfds , NULL ,NULL,NULL );
if (FD_ISSET(tfd ,&readfds)){
read(tfd , &expirations,sizeof(expirations));
record_cpu_usage();
heartbeat_counter++;
if (heartbeat_counter >=30){
heartbeat(sockfd);
heartbeat_counter=0;
}
}
}
close(sockfd); // 不要忘记在退出前关闭socket
}
int main() {
int tfd= timerfd_create(CLOCK_MONOTONIC ,0);
if(tfd ==-1){
perror("timerfd_create");
exit(EXIT_FAILURE);
}
struct itimerspec new_value ;
new_value.it_value.tv_sec=1;
new_value.it_value.tv_nsec=0;
new_value.it_interval.tv_sec=1;
new_value.it_interval.tv_nsec=0;
timerfd_settime(tfd ,0 ,&new_value,NULL);
monitor_cpu_and_send_heartbeat(tfd);
close(tfd );
return EXIT_SUCCESS;
}
更新说明:
- 新增了
create_tcp_socket()
函数,该函数用于创建并连接到指定服务器的 TCP socket。 - 在
heartbeat()
函数中,如果send()
调用失败,关闭旧的 socket,并调用create_tcp_socket()
尝试重新建立连接。如果成功建立新连接,则可以选择重发之前的信息。 - 在主循环中维护一个有效的 socket,以确保每次心跳都能通过有效的 TCP 链接发送。
这种实现方式能够确保程序在网络故障情况下依然保持稳定,通过重连机制恢复与服务端的通信。
内容由零声教学AI助手提供,问题来源于学员提问