在linux上写了一个聊天室,可以在同一台主机上聊天,可供学习娱乐,上代码
//服务器
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
struct user{
pid_t pid;//user information
int ID;//get from center
};
struct msg
{
int type;//0:connect request
//1:inter users comunicate
//2:disconnect note
//3:failed sending note
user source;
user dist;
char data[100];
};
int main(){
int fd,ret;
int ID_Alocator=1;//ID Alocator
int fds[10];//users fd list,0 refers to offline or unexit
memset(fds,0,sizeof(fds));
char data[100];
unlink("FIFO/shared");
ret=mkfifo("FIFO/shared",0777);
if(ret==-1){
printf("Makefifo error\n");
return -1;
}
fd=open("FIFO/shared",O_RDONLY);
if(fd==-1){
printf("Open shared error\n");
return -1;
}
msg m1;
while(1){
ret=read(fd,&m1,sizeof(m1));
if(ret==-1){
printf("Read error\n");
return -1;
}else if(ret==0){
printf("Users all offline,quit\n");
unlink("FIFO/shared");
return 0;
}
//deal with user request
if(m1.type==0){//connect
pid_t pidon=m1.source.pid;
printf("Connect request from process %d\n",pidon);
char userfifo[20];
sprintf(userfifo,"FIFO/fifo%d",pidon);
fds[ID_Alocator]=open(userfifo,O_WRONLY);
m1.source.ID=ID_Alocator;
printf("ID %d allocated\n",ID_Alocator);
write(fds[ID_Alocator],&m1,sizeof(m1));
ID_Alocator++;
}else if(m1.type==1){//comunicate
int sourceID=m1.source.ID;
int distID=m1.dist.ID;
printf("ID %d -> ID %d : ",sourceID,distID);
if(fds[distID]==0){
m1.type=3;
ret=write(fds[sourceID],&m1,sizeof(m1));
if(ret<0)printf("Write error\n");
printf("ID %d not exit or online\n",distID);
}
else{
ret=write(fds[distID],&m1,sizeof(m1));
if(ret<0)printf("Write error\n");
else printf("Success\n");
}
}else if(m1.type==2){//disconnect
int IDoff=m1.source.ID;
pid_t pidoff=m1.source.pid;
printf("ID %d offline\n",IDoff);
fds[IDoff]=0;
char userfifo[20];
sprintf(userfifo,"FIFO/fifo%d",pidoff);
unlink(userfifo);
}else{
printf("Unclear protocol\n");
}
}
}
用户代码
//用户
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
struct user{
pid_t pid;//user information
int ID;//get from center
};
struct msg
{
int type;
user source;
user dist;
char data[100];
};
int main(){
int ret,fd1,fd2;//fd1:write to center;fd2:read from center
char selffifo[20];
char data[100];
fd1=open("FIFO/shared",O_WRONLY);
if(fd1==-1){
printf("open shared error\n");
return -1;
}
pid_t pid;
pid=getpid();
sprintf(selffifo,"FIFO/fifo%d",pid);
unlink(selffifo);
ret=mkfifo(selffifo,0777);
if(ret==-1){
printf("mkfifo error\n");
return -1;
}
user myself;myself.pid=pid;
msg m1;m1.type=0;m1.source=myself;
ret=write(fd1,&m1,sizeof(m1));
if(ret==-1){
printf("write error\n");
return -1;
}
fd2=open(selffifo,O_RDONLY);
if(fd2==-1){
printf("make selffifo error\n");
return -1;
}
msg m2;
ret=read(fd2,&m2,sizeof(m2));
if(ret==-1){
printf("read error\n");
return -1;
}
else printf("get linked to center\n");
myself.ID=m2.source.ID;
m1.source=myself;
printf("And your ID is %d\n",myself.ID);
int status;//change read block
status=fcntl(fd2,F_GETFL,0);
status|=O_NONBLOCK;
fcntl(fd2,F_SETFL,status);
status=fcntl(STDIN_FILENO,F_GETFL,0);
status|=O_NONBLOCK;
fcntl(STDIN_FILENO,F_SETFL,status);
while(1){
void *p=gets(data);
if(p!=NULL){
if(data[0]=='q'){
m1.type=2;
ret=write(fd1,&m1,sizeof(m1));
break;
}
else if(data[0]>='0'&&data[0]<='9'&&data[1]==':'){
int distID=data[0]-'0';
user distu;distu.ID=distID;
m1.dist=distu;
m1.type=1;
memcpy(m1.data,data,sizeof(data));
ret=write(fd1,&m1,sizeof(m1));
if(ret==-1){
printf("write error\n");
return -1;
}
}
else{
printf("Invalid input\n");
}
}
int size=read(fd2,&m2,sizeof(m2));
if(size>0){
if(m2.type==1){
printf("[Receive]");
m2.data[0]=m2.source.ID+'0';
printf("%s\n",m2.data);
}else{
printf("[failed]ID %d is not online\n",m2.dist.ID);
}
}
}
}
执行效果
演示视频与源文件资源:https://github.com/FrosonC/LocalChatroom