1. 程式人生 > >System V訊息佇列實現的檔案伺服器(不跨網路)

System V訊息佇列實現的檔案伺服器(不跨網路)

可能是定時的部分有問題吧,導致客戶端無法接收資料,不過我感覺思想是沒錯的。。。先pull上吧,以後發現錯誤再改

參考資料:UNP卷二

message.h
#ifndef _MESSAGE_H
#define _MESSAGE_H

#include<stdio.h>
#include<sys/msg.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>

#define MAXLINE 100

#define RECEIVEKEY 1234
#define SENDKEY 456


struct message
{
	long len;
	int type;
	char data[MAXLINE];

};


//這裡面的mesg_send和mesg_recv都可以複用

ssize_t mesg_send(int,struct message *);
ssize_t mesg_recv(int,struct message *);

ssize_t mesg_send(int gid, struct message *mptr)
{
	return(msgsnd(gid,&(mptr->type),mptr->len,0));
	//這裡傳的是型別誒,並不是一個結構體,這樣比較節省空間
}

ssize_t mesg_recv(int gid,struct message *mptr)
{
	ssize_t n;
	n = msgrcv(gid,&(mptr->type),MAXLINE,mptr->type,0);
	mptr->len = n;
	return n;
}


#endif

客戶端
#include "message.h"

void client(int readgid,int writegid);

int 
main(int argc, char const *argv[])
{
	int readgid,writegid;

	readgid = msgget(RECEIVEKEY,IPC_CREAT|644);
	writegid = msgget(SENDKEY,IPC_CREAT|644);


	client(readgid,writegid);


	
	msgctl(readgid,IPC_RMID,0);
	msgctl(writegid,IPC_RMID,0);


	return 0;
}


void 
client(int readgid,int writegid)
{
	ssize_t length,n;
	struct message clientmsg,receivemsg;
	printf("please enter the pathname you want to send:\n");
	fgets(clientmsg.data,sizeof(clientmsg.data),stdin);
	length = strlen(clientmsg.data);
	//這裡strlen和sizeof有大不同
	//這一步總是忘記,因為fgets函式會讀入回車符
	if(clientmsg.data[length] == '\n')
		length --;
	clientmsg.len = length;
	clientmsg.type = 1;



	mesg_send(writegid,&clientmsg);

    //等待接收伺服器端訊息
	sleep(30);

	while((n = mesg_recv(readgid,&clientmsg)) > 0)
         fputs(clientmsg.data,stdout);

}

伺服器端
#include "message.h"

//錯誤一:客戶端沒有返回的顯示

//接收資料和返回資料不能用一個訊息佇列的~

void server(int readgid,int writegid);

int 
main(int argc, char const *argv[])
{
	int readgid,writegid;
	writegid = msgget(RECEIVEKEY,IPC_CREAT|644);
	//客戶端的寫與伺服器端的讀是一個訊息佇列,這個不能弄錯了~
	readgid = msgget(SENDKEY,IPC_CREAT|644);


	server(readgid,writegid);

	return 0;
}


void 
server(int readgid,int writegid)
{
	//要先接收資料吧,根據type來接收
	struct message servermsg;
	ssize_t n,pid;

	sleep(15);
	servermsg.type = 1;
	if((n = mesg_recv(readgid,&servermsg)) == 0)
		printf("pathname missing...\n");
	servermsg.data[n] = '\0';
    pid = open(servermsg.data,644|O_CREAT|O_EXCL);
	if(pid == -1)
	{
		//路徑所在的檔案存在
		read(pid,servermsg.data,MAXLINE);
		servermsg.len = strlen(servermsg.data);
		mesg_send(writegid,&servermsg);


	}
	else
	{
		//請求的檔案不存在
		snprintf(servermsg.data + n,sizeof(servermsg.data) -n ,":can't open,%s\n",strerror(errno));
		servermsg.len = strlen(servermsg.data);
		mesg_send(writegid,&servermsg);

	}


}