linux环境下的多人聊天程序设计

STEP 1:老师给出了原始的程序,是功能不完善的,也就是让我们把发信息的用户名和时间啥的显示出来,这样不是比较合理嘛;原程序是可以实现传text的,就是没有用户名而已。

先跑一下(切换到你放这三文件的目录哦~):gcc -o chat chat.c 回车

然后:./chat 回车

再开一个终端:telnet 127.0.0.1 9999 回车

username:1 回车

再开一个终端:telnet 127.0.0.1 9999 回车

username:2 回车

tell 1 hello 回车

然后1那个终端就收到消息啦,也可以chat hello everyone 回车

这样相当于群聊,所有人都能收到消息,不指定某人。

STEP 2:改代码(加代码)

经我阅读代码后,决定修改chat.h里的tell_someone这个函数先,

看114行writen(chater[index].sock_fd ,new_data_p,n)==-1

就是说把new_data_p这个字符串写到套接字里,执行完这条语句之后其他人的终端就会显示出new_data_p了,所以我们把username加到这个字符串里就可以,主要用的是strcat和strcpy函数。

在tell_someone这个函数里,data_p就是原本要发送的消息(我们就是改造成username : data_p),chater[slot_index].user_id是发送者的username,new_data_p就是我们新构建的字符串,构造它的过程就是106~109行。

其中我犯得错误是一开始把new_data_p定义成了char *类型,然后把chater[slot_index].user_id的值赋给它了,后来我发现这是这指针类型,如果这样赋值,相当于把chater[slot_index].user_id的指针赋值给了new_data_p,那么new_data_p和chater[slot_index].user_id相当于公用一个地址了,那么也就是说我们如果修改new_data_p的值,实质上是那个地址里存的值改了,chater[slot_index].user_id是指向那个地址的,那么间接地就修改了chater[slot_index].user_id的值,也就是修改了username啊!那么我们再找原来的username为1或者2,就找不着了,而且它实际变成了new_data_p(想想一下一个用户名叫   "1 :hello  回车"  是不是醉了……);然后就把它定义成char[]了,这样就是取值而不是取地址了,然后用strcat把username、 : 、data_p一步步往new_data_p里加,其中strcat(a,b),指的是把b加到a的末尾,所以要保证a有足够的空间还能容纳b哦!~

STEP 3:修改chat_all和tell_someone是一样的,一共就改了三个地方,自己看看代码吧~如果想加上系统时间啥的,同理~


话说这个原理,还是大二上java实验时候学到的……很意外地从老师和同学(三儿)那得到的思路,挺好的~就是把自己的用户名和要发送的消息一起发给对方的做法~挺好的~觉得好有哲理哦~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
环境下可以使用消息队列机制实现多人聊天程序。服务器端需要实现各用户之间聊天的消息转发,对各用户进行消息提醒;客户端需要从服务器端接收消息并将消息发送给其他客户端。下面是一个简单的实现过程: 1. 创建消息队列 使用msgget函数创建一个消息队列,返回一个消息队列标识符。 2. 服务器端 (1)创建一个线程池,用于处理客户端的连接请求。 (2)接收客户端的连接请求,将客户端的信息存储到一个链表中。 (3)接收客户端发送的消息,将消息添加到消息队列中。 (4)从消息队列中读取消息,并将消息转发给其他客户端。 3. 客户端 (1)连接服务器端,并将自己的信息发送给服务器端。 (2)接收服务器端发送的消息,并将消息发送给其他客户端。 下面是一个简单的示例代码,仅供参考: ```c // 服务器端 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <sys/msg.h> #include <sys/ipc.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define PORT 8888 #define MAX_CLIENTS 10 #define MAX_MSG_SIZE 1024 typedef struct { long type; char text[MAX_MSG_SIZE]; } message; typedef struct { int fd; char name[20]; } client_info; int msgid; client_info clients[MAX_CLIENTS]; int num_clients = 0; void *handle_client(void *arg) { int fd = *(int *)arg; char name[20]; recv(fd, name, sizeof(name), 0); printf("%s connected\n", name); clients[num_clients].fd = fd; strcpy(clients[num_clients].name, name); num_clients++; message msg; while (1) { recv(fd, msg.text, sizeof(msg.text), 0); msg.type = 1; msgsnd(msgid, &msg, sizeof(msg.text), 0); } } void *handle_messages(void *arg) { message msg; while (1) { msgrcv(msgid, &msg, sizeof(msg.text), 1, 0); for (int i = 0; i < num_clients; i++) { if (clients[i].fd != -1) { send(clients[i].fd, msg.text, sizeof(msg.text), 0); } } } } int main() { int sockfd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = INADDR_ANY; bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)); listen(sockfd, MAX_CLIENTS); msgid = msgget(IPC_PRIVATE, 0666); pthread_t tid[MAX_CLIENTS + 1]; pthread_create(&tid[MAX_CLIENTS], NULL, handle_messages, NULL); for (int i = 0; i < MAX_CLIENTS; i++) { clients[i].fd = -1; } while (1) { int fd = accept(sockfd, NULL, NULL); pthread_create(&tid[num_clients], NULL, handle_client, &fd); } return 0; } ``` ```c // 客户端 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/msg.h> #include <sys/ipc.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define PORT 8888 #define MAX_MSG_SIZE 1024 typedef struct { long type; char text[MAX_MSG_SIZE]; } message; int msgid; void *handle_messages(void *arg) { message msg; while (1) { msgrcv(msgid, &msg, sizeof(msg.text), getpid(), 0); printf("%s\n", msg.text); } } int main() { int sockfd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)); char name[20]; printf("Enter your name: "); scanf("%s", name); send(sockfd, name, sizeof(name), 0); msgid = msgget(getpid(), 0666); pthread_t tid; pthread_create(&tid, NULL, handle_messages, NULL); message msg; while (1) { scanf("%s", msg.text); msg.type = 1; msgsnd(msgid, &msg, sizeof(msg.text), 0); } return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值