使用Socket通信实现,【客户端】每隔1s从【服务端】请求最新的时间戳
Server端
#include <iostream> // 包含输入输出流库
#include <cstring> // 包含C字符串库,用于字符串操作
#include <sys/socket.h> // 包含套接字编程的库
#include <netinet/in.h> // 包含Internet协议家族的定义
#include <unistd.h> // 包含UNIX标准函数定义
#include <ctime> // 包含时间相关的库
#define PORT 8080 // 定义服务器监听的端口号
int main() {
int server_fd, new_socket; // 定义服务器文件描述符和新连接的套接字
struct sockaddr_in address; // 定义用于存储地址信息的结构体
int opt = 1; // 选项值,用于设置套接字选项
int addrlen = sizeof(address); // 地址长度
char buffer[1024] = {0}; // 缓存区,用于存储从客户端接收的数据
// 创建套接字文件描述符
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed"); // 打印错误信息
exit(EXIT_FAILURE); // 退出程序
}
// 设置套接字选项,允许地址重用
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
perror("setsockopt");// 打印错误信息
exit(EXIT_FAILURE);
}
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET; // 地址族为IPv4
address.sin_addr.s_addr = INADDR_ANY; // 监听所有本地地址
address.sin_port = htons(PORT); // 设置端口,转换为网络字节序
// 将套接字绑定到指定的IP地址和端口上
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed"); // 打印错误信息
exit(EXIT_FAILURE); // 退出程序
}
// 使套接字进入监听状态,等待客户端连接
if (listen(server_fd, 3) < 0) {
perror("listen"); // 打印错误信息
exit(EXIT_FAILURE); // 退出程序
}
// 接受客户端连接请求
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("accept"); // 打印错误信息
exit(EXIT_FAILURE); // 退出程序
}
// 无限循环,处理客户端请求
while (true) {
// 从客户端读取数据
int valread = read(new_socket, buffer, 1024);
if (valread <= 0) {
break; // 如果客户端关闭连接或发生错误,退出循环
}
std::cout << "Message from client: " << buffer << std::endl; // 输出收到的消息
// 获取当前时间戳
std::time_t now = std::time(nullptr);
std::string timestamp = std::to_string(now); // 将时间戳转换为字符串
// 发送时间戳到客户端
send(new_socket, timestamp.c_str(), timestamp.size(), 0);
}
// 关闭客户端套接字
close(new_socket);
// 关闭服务器套接字
close(server_fd);
return 0; // 程序正常结束
}
客户端
#include <iostream> // 包含输入输出流库
#include <cstring> // 包含C字符串库,用于字符串操作
#include <sys/socket.h> // 包含套接字编程的库
#include <arpa/inet.h> // 包含Internet地址库
#include <unistd.h> // 包含UNIX标准函数定义
#include <chrono> // 包含时间相关的库,用于延时
#include <thread> // 包含线程库,用于实现延时功能
#define PORT 8080 // 定义客户端要连接的服务器端口
int main() {
int sock = 0; // 定义套接字文件描述符
struct sockaddr_in serv_addr; // 定义用于存储服务器地址的结构体
char buffer[1024] = {0}; // 缓存区,用于存储从服务器接收的数据
// 创建套接字
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
std::cout << "Socket creation error" << std::endl; // 套接字创建错误信息
return -1; // 返回错误
}
serv_addr.sin_family = AF_INET; // 设置地址族为IPv4
serv_addr.sin_port = htons(PORT); // 设置端口,转换为网络字节序
// 将IP地址从文本格式转换为二进制格式
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
std::cout << "Invalid address/ Address not supported" << std::endl; // 地址无效或不支持
return -1; // 返回错误
}
// 连接到服务器
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
std::cout << "Connection Failed" << std::endl; // 连接失败信息
return -1; // 返回错误
}
// 无限循环,每秒请求一次服务器
while (true) {
// 向服务器发送请求消息
const char* message = "Requesting timestamp";
send(sock, message, strlen(message), 0);
// 从服务器读取响应
int valread = read(sock, buffer, 1024);
if (valread > 0) {
buffer[valread] = '\0'; // 确保字符串以null结尾
std::cout << "Timestamp from server: " << buffer << std::endl; // 输出接收到的时间戳
}
// 每隔1秒请求一次
std::this_thread::sleep_for(std::chrono::seconds(1));
}
// 关闭套接字
close(sock);
return 0; // 程序正常结束
}