设计一个本机聊天功能
利用共享内存
#ifndef _CHAT_H
#define _CHAT_H
struct Msg {
char name[20];
char msg[1024];
pthread_mutex_t mutex;
pthread_cond_t cond;
};
#endif
#include "head.h"
#include "chat.h"
struct Msg *share_memory = NULL;
int main() {
int shmid;
key_t key = ftok(".", 202110);
if ((shmid = shmget(key, sizeof(struct Msg), IPC_CREAT | 0666)) < 0) {
perror("shmget");
exit(1);
}
if ((share_memory = (struct Msg*)shmat(shmid, NULL, 0)) < 0) {
perror("shmat");
exit(1);
}
// 设置锁的属性,让这个锁可以在进程中使用
memset(share_memory, 0, sizeof(struct Msg));
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, 1);
printf("1\n");
pthread_mutex_init(&share_memory->mutex, &attr);
printf("2\n");
// 设置条件变量属性
pthread_condattr_t c_attr;
pthread_condattr_init(&c_attr);
pthread_condattr_setpshared(&c_attr, 1);
pthread_cond_init(&share_memory->cond, &c_attr);
perror("pthread_cond_init");
printf("123\n");
// 初始化
//pthread_cond_init(&share_memory->cond, &c_attr);
printf("***\n");
//pthread_mutex_init(&share_memory->mutex, &attr);
printf("234\n");
//memset(share_memory, 0, sizeof(struct Msg));
printf("Server has ready!\n");
while (1) {
pthread_mutex_lock(&share_memory->mutex);
printf("Server Get the mutex!\n");
pthread_cond_wait(&share_memory->cond, &share_memory->mutex);
printf("Server Wait the Signal\n");
printf("<%s> : %s.\n", share_memory->name ,share_memory->msg);
bzero(share_memory->msg, sizeof(share_memory->msg));
pthread_mutex_unlock(&share_memory->mutex);
}
shmdt(share_memory);
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
#include "head.h"
#include "chat.h"
struct Msg *share_memory = NULL;
int main(int argc, char **argv) {
key_t key;
int opt, shmid;
char name[20] = {0};
while ((opt = getopt(argc, argv, "n:")) != -1) {
switch (opt) {
case 'n':
strcpy(name, optarg);
break;
default:
fprintf(stderr, "Usage : %s -n name\n", argv[0]);
}
}
if ((key = ftok(".", 202110)) < 0) {
perror("ftok");
exit(1);
}
if ((shmid = shmget(key, sizeof(struct Msg), IPC_CREAT | 0666)) < 0) {
perror("shmid");
exit(1);
}
if ((share_memory = (struct Msg*)shmat(shmid, NULL, 0)) < 0) {
perror("shmat");
exit(1);
}
printf("name : %s\n", name);
while (1) {
char msg[1024] = {0};
scanf("%[^\n]", msg);
getchar();
if (!strlen(msg)) continue;
pthread_mutex_lock(&share_memory->mutex);
strcpy(share_memory->name, name);
strcpy(share_memory->msg, msg);
pthread_cond_signal(&share_memory->cond);
pthread_mutex_unlock(&share_memory->mutex);
printf("Send the Signal\n");
}
shmdt(share_memory);
return 0;
}
第一版本:
在写的时候遇到的问题:
- 在第一次运行服务端的时候,明明给权限加了0666 ,但是运行的时候还是出现段错误
问题在于shmat的时候,传值时,传入的是key 而不是shmid (nt 错误)
- 在运行客户端的时候,输入了内容,但是服务端没有显示
更nt 的错误,跳出的条件写反了
问题:
- 为啥在客户端先发信号再解锁?
首先担心的是发信号之后,服务端收到信号,但是加锁没有成功,但是因为在这里,加锁和发信号是临近的,所以发生率小
我们应该还考虑一点是如果先解锁,再发信号,有可能另外一个客户端抢了锁,导致信息错误。