FIFO实例

24 篇文章 0 订阅
// msg.h
#include <stdio.h>
#include <stdlib.h>

#define PIPE_BUF 100
#define MAXMSGDATA (PIPE_BUF - 2*sizeof(long))
#define MSG_LEN_TYPE_SIZE (sizeof(struct mymsg) - MAXMSGDATA)

#define FIFO1 "./fifo_1"
#define FIFO2 "./fifo_2"
#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)

struct mymsg
{
	long msg_len;
	long msg_type;
	char msg_data[MAXMSGDATA];
};

ssize_t msg_send(int, struct mymsg*);
ssize_t msg_recv(int, struct mymsg*);

// msg.c
#include "msg.h"

ssize_t  msg_send(int fd, struct mymsg *pmsg)
{
	return (write(fd, pmsg, MSG_LEN_TYPE_SIZE + pmsg->msg_len));
}

ssize_t  msg_recv(int fd, struct mymsg *pmsg)
{
	size_t len;
	ssize_t n;

	if((n = read(fd, pmsg, MSG_LEN_TYPE_SIZE)) == 0)
	{
		return 0; // end of ile
	}
	else if(n != MSG_LEN_TYPE_SIZE)
	{
		perror("read len_type error.\n");
		exit(1);
	}

	if((len = pmsg->msg_len) > 0)
	{
		if((n = read(fd, pmsg->msg_data, len)) != len)
		{
			perror("read msg_data error.\n");
			exit(1);
		}
	}
	return len;
}

// client.c
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include "msg.h"


void client(int readfd, int writefd)
{
	size_t len;
	ssize_t n;
	struct mymsg msg;

	if(fgets(msg.msg_data, MAXMSGDATA, stdin) == NULL)
	{
		perror("client fgets error.");
		exit(1);
	}
	len = strlen(msg.msg_data);

	if(msg.msg_data[len-1] == '\n')
		len--;
	msg.msg_len = len;
	msg.msg_type = 1;

	msg_send(writefd, &msg);

	while((n = msg_recv(readfd, &msg)) > 0)
		write(1, msg.msg_data, n);
}

int main(int argc, char **argv)
{
	int readfd, writefd;

	writefd = open(FIFO2, O_WRONLY, 0);
	readfd = open(FIFO1, O_RDONLY, 0);

	client(readfd, writefd);

	close(readfd);
	close(writefd);

	unlink(readfd);
	unlink(writefd);

	return 0;
}

// server.c
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include "msg.h"


void server(int readfd, int writefd)
{
	ssize_t n;
	struct mymsg msg;
	FILE *fp;

	if((n = msg_recv(readfd, &msg)) == 0)
	{
		perror("read error in server");
		exit(1);
	}
	msg.msg_data[n] = '\0';
	
	if((fp = fopen(msg.msg_data, "r")) == NULL)
	{
		snprintf(msg.msg_data + n, sizeof(msg.msg_data) - n, ": cannot open %s\n", strerror(errno));
		n = strlen(msg.msg_data);
		msg_send(writefd, &msg);
	}
	else
	{
		while(fgets(msg.msg_data, MAXMSGDATA, fp) != NULL)
		{
			msg.msg_len = strlen(msg.msg_data);
			msg_send(writefd, &msg);
		}
		fclose(fp);
	}
}

int main(int argc, char **argv)
{
	int readfd, writefd;

	if(mkfifo(FIFO1, FILE_MODE) < 0 && errno != EEXIST)
	{
		perror("mkfifo 1 error.");
	}
	if(mkfifo(FIFO2, FILE_MODE) < 0 && errno != EEXIST)
	{
		perror("mkfifo 2 error.");
		unlink(FIFO1);
	}

	readfd = open(FIFO2, O_RDONLY, 0); //这里和lcient.c中的FIFO2,O_WRONLY对应,且该行需在下边的writefd = open(FIFO1, O_WRONLY, 0);之前。否则server和client将会一直阻塞
	if(readfd == -1)
	{
		printf("raed FIFO2 error\n");
		unlink(FIFO1);
		unlink(FIFO2);
		return -1;
	}
	writefd = open(FIFO1, O_WRONLY, 0);
	if(writefd == -1)
	{
		printf("write FIFO1 error\n");
		unlink(FIFO1);
		unlink(FIFO2);
		return -1;
	}
	server(readfd, writefd);

	return 0;
}
[test@localhost test]./server
[test@localhost test]./client
text.txt
服务端读取text.txt内容并发送至客户端,客户端输出在屏幕。
一般在使用管道时,信息是以字节流的形式传递的,没有边界。有时候应用希望对所传递的数据加上某种结构。当数据由变长消息构成,并且读出者必须知道这些消息的边界以判定何时已读出单个消息时,这种需求可能发生。一下列出3种常用技巧:
1.内带特殊终止序列:许多Unix应用程序使用换行符来分隔每个消息。写入进程给每个消息添加换行符,读出进程每次读出一行。FTP、SMTp、HTTP、NNTP等使用一个回车符跟一个换行符构成双字符序列来分隔文本记录;
2.显式长度:每个记录前冠以其长度。(如本例)
3.每次连接一个记录:应用通过关闭与其对方的连接来指示一个记录结束。这要求每个记录都需要创建一个新连接。
 

                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值