帮我实现一个TCP客户端,用C语言实现,要求有超时处理机制,心跳检测机制
时间: 2023-04-03 08:03:34 浏览: 146
好的,我可以回答这个问题。以下是一个简单的TCP客户端的C语言实现,包括超时处理机制和心跳检测机制:
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/time.h>
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8888
#define TIMEOUT_SEC 5
#define HEARTBEAT_INTERVAL 10
int main() {
int sockfd;
struct sockaddr_in server_addr;
char buf[1024];
int ret, len;
fd_set readfds;
struct timeval timeout;
time_t last_heartbeat_time;
// 创建socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket");
exit(1);
}
// 设置非阻塞模式
int flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
// 设置服务器地址
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
server_addr.sin_port = htons(SERVER_PORT);
// 连接服务器
ret = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if (ret < 0 && errno != EINPROGRESS) {
perror("connect");
exit(1);
}
// 等待连接完成或超时
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
timeout.tv_sec = TIMEOUT_SEC;
timeout.tv_usec = 0;
ret = select(sockfd + 1, NULL, &readfds, NULL, &timeout);
if (ret < 0) {
perror("select");
exit(1);
} else if (ret == 0) {
printf("connect timeout\n");
exit(1);
} else {
int error = 0;
socklen_t len = sizeof(error);
getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len);
if (error != 0) {
printf("connect failed: %s\n", strerror(error));
exit(1);
}
}
// 连接成功,设置为阻塞模式
fcntl(sockfd, F_SETFL, flags);
// 发送心跳包
last_heartbeat_time = time(NULL);
while (1) {
// 检查是否需要发送心跳包
time_t now = time(NULL);
if (now - last_heartbeat_time >= HEARTBEAT_INTERVAL) {
ret = send(sockfd, "heartbeat", strlen("heartbeat"), 0);
if (ret < 0) {
perror("send");
exit(1);
}
last_heartbeat_time = now;
}
// 等待读事件或超时
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
timeout.tv_sec = TIMEOUT_SEC;
timeout.tv_usec = 0;
ret = select(sockfd + 1, &readfds, NULL, NULL, &timeout);
if (ret < 0) {
perror("select");
exit(1);
} else if (ret == 0) {
printf("timeout\n");
continue;
}
// 读取数据
len = recv(sockfd, buf, sizeof(buf), 0);
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
printf("no data\n");
continue;
} else {
perror("recv");
exit(1);
}
} else if (len == 0) {
printf("server closed\n");
exit(1);
} else {
buf[len] = '\0';
printf("recv: %s\n", buf);
}
}
// 关闭socket
close(sockfd);
return 0;
}
```
阅读全文