设计一个简单计算服务器,能够计算两个数的加,减,乘,除,使用自定义字符串设计协议包c语言
时间: 2023-12-17 14:03:27 浏览: 97
好的,以下是我为您设计的简单计算服务器的协议包格式和示例代码,使用C语言实现:
协议包格式:
```c
#define MAGIC_NUM 0x12345678
struct packet {
uint32_t magic; // 魔数,固定为0x12345678
uint8_t type; // 包的类型,0表示请求包,1表示响应包
uint8_t oper; // 操作类型,0表示加法,1表示减法,2表示乘法,3表示除法
uint32_t num1; // 第一个操作数
uint32_t num2; // 第二个操作数
uint32_t result; // 计算结果
uint32_t crc32; // 校验和,使用CRC32算法计算
};
```
示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <zlib.h>
#define SERVER_PORT 8888
#define OP_ADD 0
#define OP_SUB 1
#define OP_MUL 2
#define OP_DIV 3
bool handle_request(int conn_fd, struct sockaddr_in client_addr) {
// 接收请求包
struct packet req_packet;
if (recv(conn_fd, &req_packet, sizeof(req_packet), 0) != sizeof(req_packet)) {
perror("recv");
return false;
}
// 校验魔数和校验和
if (req_packet.magic != htonl(MAGIC_NUM) || req_packet.crc32 != htonl(crc32(0L, (const Bytef*)&req_packet, sizeof(req_packet) - sizeof(req_packet.crc32)))) {
printf("Invalid packet from %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
return false;
}
// 计算结果
uint32_t result = 0;
switch (req_packet.oper) {
case OP_ADD:
result = ntohl(req_packet.num1) + ntohl(req_packet.num2);
break;
case OP_SUB:
result = ntohl(req_packet.num1) - ntohl(req_packet.num2);
break;
case OP_MUL:
result = ntohl(req_packet.num1) * ntohl(req_packet.num2);
break;
case OP_DIV:
result = ntohl(req_packet.num1) / ntohl(req_packet.num2);
break;
default:
printf("Invalid operation type from %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
return false;
}
// 发送响应包
struct packet resp_packet = {
.magic = htonl(MAGIC_NUM),
.type = 1,
.oper = req_packet.oper,
.num1 = req_packet.num1,
.num2 = req_packet.num2,
.result = htonl(result),
.crc32 = 0,
};
resp_packet.crc32 = htonl(crc32(0L, (const Bytef*)&resp_packet, sizeof(resp_packet) - sizeof(resp_packet.crc32)));
if (send(conn_fd, &resp_packet, sizeof(resp_packet), 0) != sizeof(resp_packet)) {
perror("send");
return false;
}
printf("Handled request from %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
return true;
}
int main() {
// 创建套接字并开始监听
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd == -1) {
perror("socket");
return EXIT_FAILURE;
}
struct sockaddr_in listen_addr = {
.sin_family = AF_INET,
.sin_addr.s_addr = htonl(INADDR_ANY),
.sin_port = htons(SERVER_PORT),
};
if (bind(listen_fd, (struct sockaddr*)&listen_addr, sizeof(listen_addr)) == -1) {
perror("bind");
return EXIT_FAILURE;
}
if (listen(listen_fd, 5) == -1) {
perror("listen");
return EXIT_FAILURE;
}
printf("Listening on %s:%d\n", inet_ntoa(listen_addr.sin_addr), ntohs(listen_addr.sin_port));
// 处理连接
while (true) {
struct sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
int conn_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &client_addr_len);
if (conn_fd == -1) {
perror("accept");
continue;
}
printf("Accepted connection from %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
if (!handle_request(conn_fd, client_addr)) {
close(conn_fd);
continue;
}
close(conn_fd);
}
return EXIT_SUCCESS;
}
```
这样,我们就完成了一个简单的计算服务器的设计,它能够通过自定义的协议包格式,接收客户端的请求并进行计算,然后返回响应包。
阅读全文