fifo实现本地简单聊天程序
来源:互联网 发布:安卓简单捕鱼源码 编辑:程序博客网 时间:2024/04/30 08:51
最近做了一个小练习,要求如下:
1.设计协议
2.客户端只写公共管道,向服务端发信息
3.客户端只读私有管道,接收信息。
4.服务端维护用户登录列表
详细如图:
1.server
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>#include "protocl.h"#include "list.h"int main(void){ int status; //判断创建公有管道是否成功 int fd; //打开公有管道的文件描述符 int n; //用以保存读到的字节数 int fd_client; //打开私有管道的文件描述符 char name[MAXLINE] = {0}; //保存客户端名 char buf[MAXLINE] = {0}; //用以存放要写入管道或终端的提示信息 PROC proc; //协议,数据量大可以用堆 struct list *ls = create_list(); //创建链表,维护登录用户名列表 if ((status = mkfifo(SER_FIFO, 0644)) < 0) sys_err("mkfifo server"); if ((fd = open(SER_FIFO, O_RDONLY)) < 0) sys_err("open SER_FIFO"); while(1) { if ((n = read(fd, &proc, sizeof(PROC))) > 0) { if (proc.id == 1) { //收到的是登录包 insert_list(ls, 0, proc.src); //插入到登录列表 sprintf(buf, "%s is login\n", proc.src); write(STDOUT_FILENO, buf, strlen(buf)); if (mkfifo(proc.src, 0644) < 0) //为登录用户创建私有会话管道 sys_err("mkfifo client"); if ((fd_client = open(proc.src, O_WRONLY)) < 0) sys_err("open client fifo"); /* 给客户发送1号回执包,告诉登录成功 */ memset(&proc, 0, sizeof(PROC)); proc.id = 1; strcpy(proc.data, CONNECT); write(fd_client, &proc, sizeof(PROC)); close(fd_client); } if (proc.id == 2) { //会话包,转发 if ((fd_client = open(proc.dest, O_WRONLY)) < 0) { if (errno == 2) { //没有这个文件,用户不在线 fd_client = open(proc.src, O_WRONLY); memset(&proc, 0, sizeof(PROC)); proc.id = 3; //向发送端回发3号包 ,提示用户不在线 strcpy(proc.data, "the user is offline\n"); write(fd_client, &proc, sizeof(PROC)); close(fd_client); } else { sys_err("open fd_client"); } } write(fd_client, &proc, sizeof(PROC)); close(fd_client); } if (proc.id == 4) { //退出登录包 fd_client = open(proc.src, O_WRONLY); // memset(&proc, 0, sizeof(PROC)); proc.id = 4; strcpy(proc.data, "exit success\n"); write(fd_client, &proc, sizeof(PROC)); close(fd_client); unlink(proc.src); sprintf(buf, "%s is logout\n", proc.src); write(STDOUT_FILENO, buf, strlen(buf)); delete_node(ls, proc.src); traverse(ls); if (empty_list(ls) == 0) break; } } } free(ls); close(fd); unlink(SER_FIFO); exit(0);}
2.client
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include "protocl.h"int main(void){ int fd, fd_client; //用来保存打开公有管道和私有管道的文件描述符 int n; //保存读到的字节数 char buf[MAXLINE]; //保存一些用来写到终端上的提示信息 char name[MAXLINE]; //保存客户端用户名 PROC proc_client; //封装的协议 printf("enter your user name(1 character): "); scanf("%s", name); /* 设置非阻塞读标准输入 */ int flags = fcntl(STDIN_FILENO, F_GETFL, 0); if (fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK) < 0) sys_err("fcntl"); if ((fd = open(SER_FIFO, O_WRONLY)) < 0) sys_err("open"); /* 登录 */ proc_client.id = 1; strcpy(proc_client.src, name); write(fd, &proc_client, sizeof(proc_client)); sleep(1); //保证服务端收到以后建立私有管道 if ((fd_client = open(name ,O_RDONLY | O_NONBLOCK)) < 0) //非阻塞读私有管道 sys_err("open"); while(1) { memset(&proc_client, 0, sizeof(PROC)); if ((n = read(fd_client, &proc_client, MAXLINE)) > 0) { if (proc_client.id == 1 || proc_client.id == 3) { write(STDOUT_FILENO, proc_client.data, strlen(proc_client.data)); } if (proc_client.id == 2) { memset(buf, 0, MAXLINE); sprintf(buf, "%s:%s", proc_client.src, proc_client.data); write(STDOUT_FILENO, buf, strlen(buf)); memset(buf, 0, MAXLINE); } if (proc_client.id == 4) { write(STDOUT_FILENO, proc_client.data, strlen(proc_client.data)); break; } } if ((n = read(STDIN_FILENO, buf, MAXLINE)) > 0) { if (strncmp(buf, "exit", 4) == 0) { proc_client.id = 4; strcpy(proc_client.src, name); write(fd, &proc_client, sizeof(PROC)); } else /* send message */ { memset(&proc_client, 0, sizeof(PROC)); proc_client.id = 2; strcpy(proc_client.src, name); strncpy(proc_client.dest, buf, 1); strcpy(proc_client.data, buf+2); write(fd, &proc_client, sizeof(PROC)); memset(buf, 0, MAXLINE); } } sleep(1); } close(fd); close(fd_client); exit(0);}
3.协议
#ifndef __PROTOCL__#define __PROTOCL__typedef struct _PROTOCL{ int id; char src[4]; char dest[4]; char data[1024];}PROC;void sys_err(char *); #define MAXLINE 1024#define SER_FIFO "SER_FIFO"#define CONNECT "\###################################################\n\# you have connect with the server successfully! #\n\# use format<user:message> to send message #\n\# use <exit> to exit #\n\###################################################\n"#endif
4.链表
#ifndef __LIST_H__#define __LIST_H__struct list{ char name[4]; struct list *next;};struct list *create_list();void traverse(struct list *ls);struct list *insert_list(struct list *ls, int n, char *str);int delete_node(struct list *ls, char *str);int empty_list(struct list *ls);#endif
好了,开始运行一下吧:
0 0
- fifo实现本地简单聊天程序
- 一个简单的聊天程序--命名管道FIFO
- UDP实现简单聊天程序
- python实现简单聊天程序
- websocket实现简单聊天程序
- 4.1本地聊天室fifo简单实现2015/7/27
- 用命令管道来实现简单的本地聊天小程序
- 命名管道(FIFO)聊天程序
- fifo 简单实现
- 简单的网络聊天程序,MFC实现
- android客户端简单的聊天程序实现
- Linux TCP实现简单聊天程序
- Android客户端简单的聊天程序实现
- android 客户端简单的聊天程序实现
- C#实现简单聊天程序的方法
- 应用:Python实现简单聊天程序
- 利用TCP实现简单聊天程序
- MFC实现简单点对点聊天程序
- (function(){})()与!function(){}()
- JPA 缓存
- POJ 1556 The Doors(判断线段相交 && 最短路)
- 本地编译MTK6582的步骤4
- ubuntu12.04下安装Docker
- fifo实现本地简单聊天程序
- Java集合之HashMap
- Adapter的使用步骤和baseAdapter的使用以及inflater的一些运用
- 本地编译 全志a33 的步骤
- Objective-C 【完整OC项目-购票系统-系统分析-代码实现】
- 【SSH快速进阶】——struts2调用action的三种方式
- 【Java数据结构基础】对象与指针关系
- 接口IIC_SPI_URAT_USB_can
- 最小美观程度