服務端客戶端通訊,註冊,上線,下線,私聊,廣播
阿新 • • 發佈:2018-12-13
框架:C/S Client:向伺服器傳送請求訊息 1、註冊 2、驗證上線 3、傳送訊息:廣播訊息/私人訊息(******) 4、退出訊息(****) 多程序開發:父程序接收資訊 子程序:傳送訊息 Server: 1、接收使用者請求 註冊 上線 接收發送訊息請求並轉發 退出 總結: UDP:面向無連線,不安全,不可靠,無狀態的傳輸協議
伺服器實現註冊和上線的協議功能 :
#include<iostream> #include<sys/stat.h> #include<fcntl.h> #include<string.h> #include<sys/types.h> #include<sys/socket.h> #include<stdio.h> #include<map> #include<arpa/inet.h> using namespace std; #define PATH_MSG "./passwd" //功能1:新增節點(上線成功) //功能2:刪除節點(下線) //功能3:驗證上線 //功能4:判斷訊息功能 //功能5:註冊 //定義結構體:註冊 struct reg { char name[10]; char pwd[10]; }; //定義結構體: struct msg { char type;//訊息型別 L--上線 Q:下線 B:廣播訊息 C:聊天(私有) 註冊R: long ilen;//內容的長度 }; //前置宣告 void list(map<string,sockaddr_in> &online); //儲存到檔案中 bool saveMsg(struct reg cm) { bool state=false; //1開啟 int fd=open(PATH_MSG,O_CREAT|O_RDWR,0644); //2操作 if(fd<0) { perror("open fail"); return state; } //遍歷查詢 struct reg r; state=true; while(read(fd,&r,sizeof(r))>0) { if(strcmp(r.name,cm.name)==0) { state=false; break; } } //查詢不成功:則新增 if(state) { if(write(fd,&cm,sizeof(cm))!=sizeof(cm)) state=false; } //3關閉 close(fd); return state; } //註冊函式 void reg(int sock,struct sockaddr_in caddr) { //接收客戶端傳送的註冊資訊 struct reg r; if(recv(sock,&r,sizeof(r),0)==sizeof(r)) { if(saveMsg(r)) { sendto( sock,"ok",2,0,\ (sockaddr*)&caddr,\ sizeof(caddr) ); } } } //驗證---上線之前必須驗證 bool check(struct reg m) { bool state=false; //1對檔案遍歷 int fd=open(PATH_MSG,O_RDONLY); if(fd<0)//開啟失敗 return state; struct reg r; while(read(fd,&r,sizeof(r))>0) { if(!strcmp(r.name,m.name) && !strcmp(r.pwd,m.pwd)) { state=true; break; } } //3關閉檔案 close(fd); return state; } //上線 bool addOnline(struct reg m,struct sockaddr_in caddr,int sock,map<string,sockaddr_in> &online) { bool state=false; //判斷驗證是否通過 if(check(m)) { //將資料插入到線上列表中 online.insert(pair<string,struct sockaddr_in> (string(m.name),caddr)); //返回資訊 sendto(sock,"ok",2,0,(sockaddr*)&caddr,sizeof(caddr)); state=true; } //臨時列印線上人數 cout<<"線上人數:"<<online.size()<<endl; //顯示 list(online); return state; } //顯示線上列表: void list(map<string,sockaddr_in> &online) { map<string,sockaddr_in> ::iterator it; it=online.begin(); while(it!=online.end()) { cout<<"線上:"<<it->first<<endl; it++; } } int main() { //1建立套接字 int sock=-1,pid=-1; sock=socket(AF_INET,SOCK_DGRAM,0); if(sock<0) { perror("socket fail"); return -1; } //2繫結套接字 struct sockaddr_in addr; addr.sin_family =AF_INET; //地址型別 addr.sin_port =htons(7979); //埠 addr.sin_addr.s_addr =INADDR_ANY; //本機地址 if(bind(sock,(struct sockaddr*)&addr,sizeof(addr))<0) { perror("bind error"); return -1; } //4建立子程序 pid=fork(); if(pid>0)//父程序--接收訊息(並處理) { struct msg m; //type=L ilen=20 3="abc" int ilen; struct sockaddr_in caddr; //關聯容器---線上列表 map<string,struct sockaddr_in> online; socklen_t clen=sizeof(caddr); while(1) { //接收內容:不一定此msg的內容 abc ilen=recvfrom( \ sock,&m,sizeof(m),0, \ (struct sockaddr*)&caddr,&clen \ ); if(ilen<0)//網路出問題 { perror("recvfrom fail"); break; } else if(ilen!=sizeof(m)) continue; //判斷訊息的型別 switch(m.type) { case 'L'://上線 { cout<<"上線"<<endl; //接收發送的驗證資訊 struct reg r; if(recv(sock,&r,sizeof(r),0)==sizeof(r)) { addOnline(r,caddr,sock,online); } } break; case 'Q'://下線 cout<<"下線"<<endl; break; case 'B'://廣播 cout<<"廣播"<<endl; break; case 'C'://私信 cout<<"私信"<<endl; break; case 'R'://註冊 { cout<<"註冊"<<endl; //註冊函式 reg(sock,caddr); } break; default: ; } } } else if(pid==0)//子程序 { } else { perror("fork fail"); return -1; } //4關閉套接字 close(sock); }
實現客戶端向伺服器傳送訊息 :
#include<iostream> #include<sys/wait.h> #include<sys/types.h> #include<sys/socket.h> #include<arpa/inet.h> using namespace std; struct reg { char name[10]; char pwd[10]; }; struct msg { char type; long ilen; }; int main() { //1建立套接字 int sock=socket(AF_INET,SOCK_DGRAM,0); int pid; pid=fork(); if(pid>0) { //2傳送 msg struct sockaddr_in addr; addr.sin_family =AF_INET; addr.sin_port =htons(7979); addr.sin_addr.s_addr =inet_addr("127.0.0.1"); //傳送註冊資訊 struct msg m={'L',10}; sendto(sock,&m,sizeof(m),0,(struct sockaddr*)&addr,sizeof(addr)); struct reg r={"lxw","123456"}; sendto(sock,&r,sizeof(r),0,(struct sockaddr*)&addr,sizeof(addr)); //等待子程序結束 wait(NULL); } else if(pid==0) { char buf[100]=""; int ilen=0; while((ilen=recv(sock,buf,100,0))>0) { buf[ilen]='\0'; cout<<buf<<endl; } } //3關閉 close(sock); }