当前位置: 首页 > article >正文

寒假(一)

请使用消息队列实现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 2

typedef 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 12345

typedef 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() {
    // 生成唯一Key
    key_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.kler.cn/a/532496.html

相关文章:

  • 【数据结构-Trie树】力扣648. 单词替换
  • 手写单例模式
  • SmartPipe完成新一轮核心算法升级
  • 注解(Annotation)
  • 网站快速收录:如何优化网站音频内容?
  • 基于Spring Security 6的OAuth2 系列之八 - 授权服务器--Spring Authrization Server的基本原理
  • 安培定律应用于 BH 曲线上的工作点
  • visual studio安装
  • Java Stream实战_函数式编程的新方式
  • 具身智能-强化学习-强化学习基础-马尔可夫
  • 【暴力搜索】有效的数独
  • python给文件夹和文件进行zip加密压缩
  • JavaWeb学习笔记——1.27
  • 网络爬虫学习:借助DeepSeek完善爬虫软件,增加停止任务功能
  • 基于FPGA的BT656编解码
  • Android项目中使用Eclipse导出jar文件
  • 机器学习在地震预测中的应用
  • 两晋南北朝 侨置州郡由来
  • 混合办公模式下,如何用 SASE 消除安全隐患?
  • 架构师成长(一)之计算机系统知识
  • 正则表达式超详细讲解
  • 9 Ezpop 【POP链构造】(未完)
  • Spirng+SpringMVC+Maven+Mybatis+MySQL项目搭建
  • Rust错误处理:从灭火器到核按钮的生存指南
  • python找不到etree怎么解决
  • Using HPC for Computational Fluid Dynamics 笔记