System V訊息佇列實現的檔案伺服器(不跨網路)
阿新 • • 發佈:2018-11-07
可能是定時的部分有問題吧,導致客戶端無法接收資料,不過我感覺思想是沒錯的。。。先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); } }