210 lines
6.0 KiB
C
210 lines
6.0 KiB
C
|
|
#include <stdio.h>
|
|||
|
|
#include <stdlib.h>
|
|||
|
|
#include <string.h>
|
|||
|
|
#include <time.h>
|
|||
|
|
#include <math.h>
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Windows专用网络头文件
|
|||
|
|
#include <winsock2.h>
|
|||
|
|
#include <ws2tcpip.h>
|
|||
|
|
#include <windows.h>
|
|||
|
|
#pragma comment(lib, "ws2_32.lib") // 链接Winsock库
|
|||
|
|
|
|||
|
|
#define PORT 8082
|
|||
|
|
#define BUFFER_SIZE 4096
|
|||
|
|
#define MAX_SHIPS 10
|
|||
|
|
|
|||
|
|
// 船舶数据结构体
|
|||
|
|
typedef struct {
|
|||
|
|
char mmsi[20];
|
|||
|
|
double latitude;
|
|||
|
|
double longitude;
|
|||
|
|
double speed;
|
|||
|
|
int course;
|
|||
|
|
int heading;
|
|||
|
|
int nav_status;
|
|||
|
|
char timestamp[30];
|
|||
|
|
char ship_name[50];
|
|||
|
|
int ship_type;
|
|||
|
|
double draught;
|
|||
|
|
char destination[50];
|
|||
|
|
char eta[30];
|
|||
|
|
} VDESData;
|
|||
|
|
|
|||
|
|
// 生成随机浮点数 (min, max)
|
|||
|
|
double rand_range(double min, double max) {
|
|||
|
|
return min + (double)rand() / RAND_MAX * (max - min);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取当前时间戳
|
|||
|
|
void get_current_timestamp(char *buffer) {
|
|||
|
|
time_t now = time(NULL);
|
|||
|
|
struct tm *t = localtime(&now);
|
|||
|
|
strftime(buffer, 30, "%Y-%m-%d %H:%M:%S", t);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 生成未来时间戳
|
|||
|
|
void get_future_timestamp(char *buffer, int days) {
|
|||
|
|
time_t now = time(NULL);
|
|||
|
|
now += days * 24 * 3600; // 添加天数
|
|||
|
|
struct tm *t = localtime(&now);
|
|||
|
|
strftime(buffer, 30, "%Y-%m-%d %H:%M:%S", t);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 创建一批船舶数据
|
|||
|
|
void create_vdes_data_batch(VDESData *batch, int count) {
|
|||
|
|
for (int i = 0; i < count; i++) {
|
|||
|
|
// 生成随机MMSI (336295959 - 336295969)
|
|||
|
|
snprintf(batch[i].mmsi, 20, "%d", 336295959 + rand() % 11);
|
|||
|
|
|
|||
|
|
batch[i].latitude = round(rand_range(30.5, 31.0) * 1000000) / 1000000.0;
|
|||
|
|
batch[i].longitude = round(rand_range(122.0, 123.0) * 1000000) / 1000000.0;
|
|||
|
|
batch[i].speed = round(rand_range(0, 30) * 10) / 10.0;
|
|||
|
|
batch[i].course = rand() % 360;
|
|||
|
|
batch[i].heading = rand() % 360;
|
|||
|
|
batch[i].nav_status = rand() % 9;
|
|||
|
|
|
|||
|
|
get_current_timestamp(batch[i].timestamp);
|
|||
|
|
|
|||
|
|
char ship_num[10];
|
|||
|
|
snprintf(ship_num, 10, "%d", 1000 + rand() % 9000);
|
|||
|
|
strcpy(batch[i].ship_name, "船舶_");
|
|||
|
|
strcat(batch[i].ship_name, ship_num);
|
|||
|
|
|
|||
|
|
batch[i].ship_type = 1 + rand() % 99;
|
|||
|
|
batch[i].draught = round(rand_range(1.0, 15.0) * 10) / 10.0;
|
|||
|
|
|
|||
|
|
char port_num[10];
|
|||
|
|
snprintf(port_num, 10, "%d", 1 + rand() % 100);
|
|||
|
|
strcpy(batch[i].destination, "港口_");
|
|||
|
|
strcat(batch[i].destination, port_num);
|
|||
|
|
|
|||
|
|
get_future_timestamp(batch[i].eta, 1 + rand() % 7);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 将船舶数据转换为JSON字符串
|
|||
|
|
void vdes_data_to_json(VDESData *data, char *json, int index, int is_last) {
|
|||
|
|
char buffer[1024];
|
|||
|
|
snprintf(buffer, 1024,
|
|||
|
|
"{"
|
|||
|
|
"\"mmsi\":\"%s\","
|
|||
|
|
"\"latitude\":%.6f,"
|
|||
|
|
"\"longitude\":%.6f,"
|
|||
|
|
"\"speed\":%.1f,"
|
|||
|
|
"\"course\":%d,"
|
|||
|
|
"\"heading\":%d,"
|
|||
|
|
"\"nav_status\":%d,"
|
|||
|
|
"\"timestamp\":\"%s\","
|
|||
|
|
"\"ship_name\":\"%s\","
|
|||
|
|
"\"ship_type\":%d,"
|
|||
|
|
"\"draught\":%.1f,"
|
|||
|
|
"\"destination\":\"%s\","
|
|||
|
|
"\"eta\":\"%s\""
|
|||
|
|
"}%s",
|
|||
|
|
data->mmsi, data->latitude, data->longitude, data->speed,
|
|||
|
|
data->course, data->heading, data->nav_status, data->timestamp,
|
|||
|
|
data->ship_name, data->ship_type, data->draught, data->destination,
|
|||
|
|
data->eta,
|
|||
|
|
is_last ? "" : ",");
|
|||
|
|
|
|||
|
|
strcat(json, buffer);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int main() {
|
|||
|
|
// 初始化Winsock
|
|||
|
|
WSADATA wsaData;
|
|||
|
|
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
|||
|
|
perror("WSAStartup failed");
|
|||
|
|
exit(EXIT_FAILURE);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
srand(time(NULL)); // 初始化随机种子
|
|||
|
|
|
|||
|
|
SOCKET server_fd, new_socket; // Windows下使用SOCKET类型
|
|||
|
|
struct sockaddr_in address;
|
|||
|
|
char opt = '1'; // Windows下需要char类型
|
|||
|
|
int addrlen = sizeof(address);
|
|||
|
|
char buffer[BUFFER_SIZE] = {0};
|
|||
|
|
|
|||
|
|
// 创建socket文件描述符
|
|||
|
|
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
|
|||
|
|
perror("socket failed");
|
|||
|
|
WSACleanup();
|
|||
|
|
exit(EXIT_FAILURE);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 设置socket选项 (Windows下只使用SO_REUSEADDR)
|
|||
|
|
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == SOCKET_ERROR) {
|
|||
|
|
perror("setsockopt");
|
|||
|
|
closesocket(server_fd);
|
|||
|
|
WSACleanup();
|
|||
|
|
exit(EXIT_FAILURE);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
address.sin_family = AF_INET;
|
|||
|
|
address.sin_addr.s_addr = INADDR_ANY;
|
|||
|
|
address.sin_port = htons(PORT);
|
|||
|
|
|
|||
|
|
// 绑定socket到端口
|
|||
|
|
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
|
|||
|
|
perror("bind failed");
|
|||
|
|
closesocket(server_fd);
|
|||
|
|
WSACleanup();
|
|||
|
|
exit(EXIT_FAILURE);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 开始监听
|
|||
|
|
if (listen(server_fd, 3) < 0) {
|
|||
|
|
perror("listen");
|
|||
|
|
closesocket(server_fd);
|
|||
|
|
WSACleanup();
|
|||
|
|
exit(EXIT_FAILURE);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
printf("VDES数据模拟器正在运行,监听端口 %d...\n", PORT);
|
|||
|
|
|
|||
|
|
// 接受客户端连接
|
|||
|
|
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (int*)&addrlen)) == INVALID_SOCKET) {
|
|||
|
|
perror("accept");
|
|||
|
|
closesocket(server_fd);
|
|||
|
|
WSACleanup();
|
|||
|
|
exit(EXIT_FAILURE);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
printf("客户端已连接\n");
|
|||
|
|
|
|||
|
|
while (1) {
|
|||
|
|
// 随机等待时间 (1-5秒)
|
|||
|
|
int sleep_time = 1 + rand() % 5;
|
|||
|
|
Sleep(sleep_time * 1000); // Windows下使用Sleep(毫秒)
|
|||
|
|
|
|||
|
|
// 随机生成1-10条船舶数据
|
|||
|
|
int ship_count = 1 + rand() % MAX_SHIPS;
|
|||
|
|
VDESData ships[ship_count];
|
|||
|
|
create_vdes_data_batch(ships, ship_count);
|
|||
|
|
|
|||
|
|
// 转换为JSON数组
|
|||
|
|
char json[BUFFER_SIZE] = "[";
|
|||
|
|
for (int i = 0; i < ship_count; i++) {
|
|||
|
|
vdes_data_to_json(&ships[i], json, i, (i == ship_count - 1));
|
|||
|
|
}
|
|||
|
|
strcat(json, "]");
|
|||
|
|
|
|||
|
|
printf("生成 %d 条船舶数据:\n%s\n", ship_count, json);
|
|||
|
|
|
|||
|
|
// 发送数据
|
|||
|
|
if (send(new_socket, json, strlen(json), 0) == SOCKET_ERROR) {
|
|||
|
|
perror("send failed");
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
printf("数据已发送\n");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 清理资源
|
|||
|
|
closesocket(new_socket);
|
|||
|
|
closesocket(server_fd);
|
|||
|
|
WSACleanup();
|
|||
|
|
return 0;
|
|||
|
|
}
|