寒假(一)

server/2025/2/5 15:52:38/

请使用消息队列实现2个终端之间互相聊天

终端一

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>#define MSG_SIZE 64
#define MSG_TYPE_1 1
#define MSG_TYPE_2 2typedef struct {long change;       // 消息类型(频道)char dup[MSG_SIZE]; // 消息内容
} msg_data;key_t key;      // 消息队列的键值
int msg_id;     // 消息队列的ID// 信号处理函数
void handler(int signum) {if (signum == SIGINT) {printf("\n程序退出,销毁消息队列...\n");msgctl(msg_id, IPC_RMID, NULL); // 销毁消息队列exit(0);}
}// 消息写入函数
void msg_w() {msg_data arr;while (1) {arr.change = MSG_TYPE_1; // 设置消息类型printf("请输入:");scanf("%s", arr.dup);    // 读取用户输入if (msgsnd(msg_id, &arr, strlen(arr.dup) + 1, 0) == -1) {perror("msgsnd");break;}}
}// 消息读取函数
void msg_r() {msg_data arr;while (1) {if (msgrcv(msg_id, &arr, sizeof(arr.dup), MSG_TYPE_2, 0) == -1) {perror("msgrcv");break;}printf("\b\b\b\b\b\b\b\b收到的消息为:%s\n", arr.dup);memset(arr.dup, 0, sizeof(arr.dup)); // 清空消息缓冲区}
}// 线程函数
void* pthread_main(void* arg) {msg_w();return NULL;
}// 清理函数
void cleanup() {printf("清理消息队列...\n");msgctl(msg_id, IPC_RMID, NULL);
}int main(int argc, const char *argv[]) {pthread_t pthread_id;// 注册信号处理函数signal(SIGINT, handler);// 注册清理函数atexit(cleanup);// 生成消息队列的键值key = ftok("1.txt", 1);if (key == -1) {perror("ftok");exit(1);}// 创建消息队列msg_id = msgget(key, IPC_CREAT | 0664);if (msg_id == -1) {perror("msgget");exit(1);}// 创建线程if (pthread_create(&pthread_id, NULL, pthread_main, NULL) != 0) {perror("pthread_create");exit(1);}pthread_detach(pthread_id); // 设置线程为分离状态// 主线程负责读取消息msg_r();return 0;
}

终端二

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <signal.h>
#include <pthread.h>#define MSG_TYPE_SEND 1   // 本终端发送的消息类型
#define MSG_TYPE_RECV 2   // 本终端接收的消息类型
#define MSG_BUFFER_SIZE 64
#define KEY_FILE_PATH "msgq_chat.key"
#define PROJECT_ID 12345typedef struct {long mtype;            // 消息类型char mtext[MSG_BUFFER_SIZE]; // 消息内容
} msg_data;static int msg_id = -1;// 信号处理函数:清理消息队列
void handle_signal(int signum) {if (signum == SIGINT) {printf("\n正在清理消息队列...\n");if (msg_id != -1) {msgctl(msg_id, IPC_RMID, NULL);}exit(EXIT_SUCCESS);}
}// 消息发送线程函数
void* send_thread(void *arg) {msg_data msg;while (1) {msg.mtype = MSG_TYPE_SEND;printf("[You] > ");if (fgets(msg.mtext, MSG_BUFFER_SIZE, stdin) == NULL) {perror("fgets");break;}// 去除换行符并计算真实长度size_t len = strcspn(msg.mtext, "\n");msg.mtext[len] = '\0';if (msgsnd(msg_id, &msg, len + 1, IPC_NOWAIT) == -1) { // 非阻塞发送perror("消息发送失败");usleep(100000); // 发送失败时等待100ms}}return NULL;
}// 消息接收处理
void receive_messages() {msg_data msg;while (1) {ssize_t ret = msgrcv(msg_id, &msg, MSG_BUFFER_SIZE, MSG_TYPE_RECV, 0);if (ret == -1) {perror("消息接收失败");break;}printf("\r[Other] > %s\n[You] > ", msg.mtext);fflush(stdout); // 确保立即刷新输出}
}int main() {// 生成唯一Keykey_t key = ftok(KEY_FILE_PATH, PROJECT_ID);if (key == -1) {perror("无法生成消息队列Key");exit(EXIT_FAILURE);}// 创建/获取消息队列msg_id = msgget(key, IPC_CREAT | 0666);if (msg_id == -1) {perror("无法创建消息队列");exit(EXIT_FAILURE);}// 注册信号处理signal(SIGINT, handle_signal);// 创建发送线程pthread_t tid;if (pthread_create(&tid, NULL, send_thread, NULL) != 0) {perror("无法创建发送线程");exit(EXIT_FAILURE);}pthread_detach(tid);// 主线程处理接收printf("--- 聊天室已启动 (Ctrl+C退出) ---\n");receive_messages();return EXIT_SUCCESS;
}


http://www.ppmy.cn/server/165172.html

相关文章

LVGL+FreeRTOS实战项目:智能健康助手(lcd篇)

1.8寸彩色TFT显示屏简介 接线图 我们选用的是分辨率为128*160的彩色显示屏&#xff0c;采用的SPI接口&#xff0c;通过我们STM32的SPI外设&#xff0c;来和我们的屏幕进行通信&#xff0c;以显示我们需要显示的图片。 软件部分 #include "lcd_driver.h"//液晶IO初始…

DNS缓存详解(DNS Cache Detailed Explanation)

DNS缓存详解 清空DNS缓存可以让网页访问更快捷。本文将从什么是DNS缓存、为什么清空DNS缓存、如何清空DNS缓存、清空DNS缓存存在的问题四个方面详细阐述DNS缓存清空的相关知识。 一、什么是DNS缓存 1、DNS缓存的定义&#xff1a; DNS缓存是域名系统服务在遇到DNS查询时自动…

计算机网络中常见高危端口有哪些?如何封禁高危端口?

保障网络安全&#xff0c;从封禁高危端口开始&#xff01; 在计算机网络中&#xff0c;端口是设备与外界通信的“大门”&#xff0c;但某些端口因常被黑客利用而成为高危入口。封禁这些端口是防御网络攻击的关键一步。本文将详解 10个常见高危端口&#xff0c;并提供多平台封禁…

JVM监控和管理工具

基础故障处理工具 jps jps(JVM Process Status Tool)&#xff1a;Java虚拟机进程状态工具 功能 1&#xff1a;列出正在运行的虚拟机进程 2&#xff1a;显示虚拟机执行主类(main()方法所在的类) 3&#xff1a;显示进程ID(PID&#xff0c;Process Identifier) 命令格式 jps […

2024年终总结来了

忘记发CSDN的年度总结了&#xff0c;今天补上吧 说实话&#xff0c;今年过得不是特别好&#xff0c;感觉遇到了瓶颈&#xff0c;人生变得迷茫起来。不知道大家有没有同样的感受 刚毕业的时候人生充满了憧憬&#xff0c;慢慢的随着年龄变大后&#xff0c;就会觉得一事无成&…

RGB565转BITMAP[C#---2]

这是楼主在开发C#上位机的时候遇到的另一个问题&#xff0c;怎么把RGB565转为BITMAP&#xff0c;在CSDN上搜索&#xff0c;要么是安卓平台的&#xff0c;要么是2011年的古早代码&#xff08;还没排版&#xff09;&#xff0c;还是靠自己和DEEPSEEK的智慧解决了(●’◡’●) 当然…

JavaScript前后端交互-AJAX/fetch

摘自千峰教育kerwin的js教程 AJAX 1、AJAX 的优势 不需要插件的支持&#xff0c;原生 js 就可以使用用户体验好&#xff08;不需要刷新页面就可以更新数据&#xff09;减轻服务端和带宽的负担缺点&#xff1a; 搜索引擎的支持度不够&#xff0c;因为数据都不在页面上&#xf…

PyTorch生态系统中的连续深度学习:使用Torchdyn实现连续时间神经网络

神经常微分方程&#xff08;Neural ODEs&#xff09;是深度学习领域的创新性模型架构&#xff0c;它将神经网络的离散变换扩展为连续时间动力系统。与传统神经网络将层表示为离散变换不同&#xff0c;Neural ODEs将变换过程视为深度&#xff08;或时间&#xff09;的连续函数。…