voice_broadcast/voice_guard.c
2025-06-03 04:49:29 +00:00

164 lines
3.9 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <signal.h>
#include <sys/wait.h>
#define PORT 9999
#define TIMEOUT 3
pid_t play_pid = 0;
// 启动播放
void start_playback()
{
if (play_pid == 0)
{
play_pid = fork();
if (play_pid == 0)
{
execl("./audio_play", "./audio_play", NULL);
perror("execl failed");
exit(1);
}
printf("播放进程已启动PID=%d\n", play_pid);
}
}
// 停止播放
void stop_playback()
{
if (play_pid > 0)
{
printf("停止播放,终止 PID=%d\n", play_pid);
kill(play_pid, SIGTERM);
waitpid(play_pid, NULL, 0);
play_pid = 0;
}
}
int main()
{
int listen_fd, conn_fd;
struct sockaddr_in addr;
char buffer[128];
time_t last_time = 0;
int playing = 0;
fd_set read_fds;
struct timeval tv;
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd < 0)
{
perror("socket error");
return 1;
}
int opt = 1;
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("bind error");
close(listen_fd);
return 1;
}
if (listen(listen_fd, 5) < 0)
{
perror("listen error");
close(listen_fd);
return 1;
}
printf("语音守护 TCP 服务器已启动,监听端口 %d...\n", PORT);
while (1)
{
printf("等待客户端连接...\n");
conn_fd = accept(listen_fd, NULL, NULL);
if (conn_fd < 0)
{
perror("accept error");
continue;
}
printf("客户端已连接\n");
last_time = 0;
playing = 0;
// 设置非阻塞模式
fcntl(conn_fd, F_SETFL, O_NONBLOCK);
while (1)
{
FD_ZERO(&read_fds);
FD_SET(conn_fd, &read_fds);
tv.tv_sec = 1;
tv.tv_usec = 0;
int ret = select(conn_fd + 1, &read_fds, NULL, NULL, &tv);
if (ret > 0 && FD_ISSET(conn_fd, &read_fds))
{
ssize_t len = read(conn_fd, buffer, sizeof(buffer) - 1);
if (len > 0)
{
buffer[len] = '\0';
if (strstr(buffer, "RUNNING"))
{
last_time = time(NULL);
if (!playing)
{
printf("收到心跳,启动播报...\n");
start_playback();
playing = 1;
}
}
}
else if (len == 0)
{
printf("客户端关闭连接\n");
break;
}
}
else if (ret == 0)
{
// 超时
if (playing && (time(NULL) - last_time > TIMEOUT))
{
printf("超时未收到心跳,停止播报...\n");
stop_playback();
playing = 0;
}
}
else
{
perror("select error");
break;
}
}
close(conn_fd);
// 断开连接时停止播放
if (playing)
{
printf("连接断开,停止播放\n");
stop_playback();
playing = 0;
}
}
close(listen_fd);
return 0;
}