Linux下類似QQ聊天工具_第1頁
Linux下類似QQ聊天工具_第2頁
Linux下類似QQ聊天工具_第3頁
Linux下類似QQ聊天工具_第4頁
Linux下類似QQ聊天工具_第5頁
已閱讀5頁,還剩42頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、概述AbstractLinux作為免費開源操作系統(tǒng)廣泛應用于企業(yè)。Linux與UNIX有著深厚的淵源,而UNIX系統(tǒng)可謂“堅如磐石”,其穩(wěn)定性受到廣泛贊譽。近年來,越來越多的就業(yè)崗位被提供給了Linux開發(fā)人員。IM即時通訊軟件是近年來流行的通信方式,企業(yè)、個人等都在更多地使用IM進行溝通。通過計算機網(wǎng)絡,信息的傳遞變得十分方便。并非所有IM軟件都要想騰訊QQ那樣復雜、龐大,作為內(nèi)部溝通,只需功能齊全、操作方便即可。作為課程設計作品,在Linux下開發(fā)C/S式IM軟件,對于熟悉Linux、復習計算機網(wǎng)絡、進一步學習軟件開發(fā)都有十分積極的意義。As is open source software

2、, Linux has been widely used in corporations. These years, more and more jobs are offered to Linux developers, for Linux spoken highly of for its stability as UNIX. IM software has become the most widely used communication software both for business use and for personal use. Through internetworks -

3、including the Internet, Enterprise LAN, VPNs - information can be exchanged more conveniently and immediately. However, not all IM of C/S model is that complex as Tencent QQ. IM software inside an Enterprise LAN should be lighter and easier. As a product design of Linux, developing an IM software is

4、 helpful to reviewing key points of Linux, Internet, and software developing. 歡迎下載目 錄第1章 設計任務1.1. 設計任務概述1.1.1. 課題名稱Linux下的IM網(wǎng)絡聊天軟件1.1.2. 內(nèi)容摘要隨著嵌入式在生活中的應用越來越廣泛,嵌入式LINUX下的Socket網(wǎng)絡編程也越來越熱。為了加強對在Linux系統(tǒng)下進行編程的學習和實踐,運用計算機網(wǎng)絡、軟件工程等知識,我們選擇了Linux下網(wǎng)絡聊天工具作為課設題目。本系統(tǒng)主要功能在于實現(xiàn)多個客戶端一與服務器端之問的信息傳遞與文件傳輸功能。系統(tǒng)主要實現(xiàn)4人聊天室功能

5、:注冊與登錄系統(tǒng),公聊,私聊,文件傳輸。應用LINUX下的Socket網(wǎng)絡編程并使用TCP實現(xiàn)簡單聊天程序。編程過程中不斷用各種網(wǎng)絡調(diào)試工具進行調(diào)試程序,最終做成了簡單的在Linux下的聊天工具。關鍵詞:Linux Socket IM軟件1.2. 開發(fā)環(huán)境1.2.1. 硬件環(huán)境Intel x86 CPU架構(主頻1G Hz以上)512MB DDR2內(nèi)存支持800*600以上分辨率、16色以上的顯示設備1.2.2. 軟件環(huán)境Red Hat Enterprise Linux(或Fedora)VIM編譯器1.3. 要求在Linux下實現(xiàn)網(wǎng)絡聊天,包括公聊、一對多私聊等功能。實現(xiàn)客戶端之間經(jīng)網(wǎng)絡傳輸文

6、件。能保存聊天記錄。第2章 設計方案2.1. 系統(tǒng)結構2.1.1. 結構結構組成:注冊、登錄、聊天、文件傳輸。2.1.2. 結構圖聊天系統(tǒng)分為五大模塊2.2. 流程與模塊2.2.1. 執(zhí)行流程2.2.2. 各功能需要調(diào)用的模塊模塊需求注冊登錄聊天文件傳輸用戶注冊用戶登錄系統(tǒng)廣播上下線提示用戶私聊文件傳輸強制下線第3章 實現(xiàn)原理3.1. 注冊、登錄模塊3.1.1. 服務器端服務器端建立好socket,等待連接,當有客戶端連接服務器的時候,服務器接收連接,并接受客戶端發(fā)送過來的消息,恨據(jù)接收到的結構體所攜帶的協(xié)議來做相應的功能:服務器端啟動后如圖 31所示。圖 31l、注冊:如果協(xié)議為reg,則為

7、客戶端注冊,首先將發(fā)送過來的結構體,提取用戶名和密碼,然后需要對川戶名合法性檢驗,驗證之后如果用戶名合法則將川戶信已保存到文件中,合法性的規(guī)則包括川戶名不能重復和不能使用all等協(xié)議作為川戶名,并且川戶名和密碼都不能為空。如果注冊成功,服務器端發(fā)送一個消息給注冊的客戶端,同樣將消息保存在一個結構休里如果失敗,也給客戶端發(fā)送一個消息如“您榆入的用戶名小能為akk”或者“用戶名XX已經(jīng)存在”。注冊結果如圖 32所示。圖 322、登錄:如果協(xié)議為login,則將用戶名和密碼信息提取,再遍歷存放用戶信息文件里的用戶名和密碼直到驗證成功為止,如果驗證成功則對所有在線的川戶發(fā)送一條消息:“提示XX用戶登錄

8、成功”;如果失敗則只給登陽失敗的客戶端提示登錄失敗,并給出原囚,如“用戶名不存在”或者“用戶名或者密碼輸入錯誤”,并跳轉(zhuǎn)到相應的代碼執(zhí)行其他功能,成功則等特發(fā)送客戶端消息,失敗則關閉Socket并結束線程,如圖 33所示:圖 333、監(jiān)聽和踢出客戶端:通過六行和修改綁定的Socket和在線用戶隊列實現(xiàn)查看和踢出在線用戶,踢出用戶后向被踢出用戶發(fā)送相關信息,如圖 34、圖 35所示。圖 34圖 353.1.2. 客戶端客戶端的輸入和消息的顯示要使用2個終端,一個是Client,一個是Display。Client終端為輸入的界面。在這個界面里,新建一個線程來接受服務器端發(fā)來的消息,再添加時間信息,

9、并將這些信息寫入文件,然后給Display進程發(fā)送一個消息,Display進程接到消息,就去讀取文件并將這些數(shù)擬顯示在Display終端。打開客戶端Display終端界而,用lseek將內(nèi)部指t陣行向文件末尾,等待Client終端里的線秤將消息寫入文件。一旦有消息過來就去文件里讀取數(shù)據(jù)井打印在Display終端。打開客戶端Client終端界而,有3個菜單,包括注冊、登錄、退出。選擇相應項即可進幻相關操作,注冊和登錄如圖 32、圖 33所示。3.1.3. 協(xié)議服務器端和客戶端之間互相通信需要使用的協(xié)議:l、all$msg為給所有人發(fā)送消息。2、直接輸入view$獲得在線用戶列表。3、user$m

10、sg給用戶名為user的用戶發(fā)送私聊消息。4、trans$user$filenam將文件傳輸給who。5、reg為注冊。6、login為登錄。3.2. 聊天模塊3.2.1. 客戶端客戶端在登陸成功之后在發(fā)送消息之前可以先查看在線用戶列表,查看用戶列表使用view$,如所示。圖 36接著,可以使用user$msg的形式發(fā)送信息,這個消息是發(fā)送給user的?;蛘撸仁褂胾ser$來切換到發(fā)送消息,這個時候,你不需要加上協(xié)議,即可給user這個用戶發(fā)送消息,如圖 37、圖 38所示。圖 37圖 38當然,上述方法也可以實現(xiàn)一對多聊天。如所示。圖 39這些消息都加上協(xié)議user$msg來封裝成結構體,

11、再發(fā)送給服務器端。3.2.2. 服務器端如果是私聊,則根據(jù)客戶端要發(fā)送到哪個用戶,到鏈表里取得該用戶名的客戶端信息,服務器再發(fā)送給相應的接收信息的客戶端,接收信息的客戶終端就會光將信息保存到聊天記錄的文件里,并顯示收到的信息,并且信息前面會顯示相應的提示符。3.3. 文件傳輸模塊3.3.1. 客戶端如果某個客戶端想發(fā)送文件給其他客戶端,則直接使用命令trans$user$filename。trans為協(xié)議,user為用戶名,filename包括本地的路徑和文件名。如圖 310、圖 311所示。圖 310圖 3113.3.2. 服務器端當發(fā)送到服務器的時候,根據(jù)協(xié)議,先給接收的客戶端發(fā)送一條消息

12、為trans標記:某某用戶給您發(fā)送了XX文件,Y接收N拒絕接收。如果客戶端按下N,則返回一條消息給服務器端,服務器端同時告訴發(fā)送的客戶端對方拒絕接收文件。發(fā)送端可以繼續(xù)做其他的事。如果接收的客戶端按下Y,并立即按受保存的路徑和文件名。輸入完后就可以接收文件了??蛻舳朔祷匾粭l消息給無誤器端,服務器端同時返回一條消息給發(fā)送的客戶端,告訴客戶端對方同意接收文件,這時候文件開始傳輸;發(fā)送完畢后,發(fā)送的客戶端會顯示傳輸完畢。傳輸?shù)奈募梢允谷我獾奈膫?。不僅僅是文本,多媒體文件也可以。第4章 實現(xiàn)本設計由C語言實現(xiàn),用VIM編譯。歡迎下載/*check.h*/#include #include #incl

13、ude #include #include #include #include #include #include #include #define MAXLEN 1024struct message char flag15; char name10; int size; char msgMAXLEN;int reg_check(struct message *recievemsg);int login_check(struct message *recievemsg);/*check.c*/#include check.hint reg_check(struct message *recie

14、vemsg) int fd; int read_size,write_size; struct message cmpmsg; if(strlen(recievemsg-name)10 |strlen(recievemsg-msg)20 ) return 1; if(strcmp(recievemsg-name,all)=0) return -1; if(strcmp(recievemsg-name,reg)=0) return -1; if(strcmp(recievemsg-name,login)=0) return -1; if(strcmp(recievemsg-name,trans)

15、=0) return -1; if(fd=open(user.txt,O_RDWR|O_CREAT|O_A,PPEND,0666)0) perror(open); printf(openn); return -2; do if(read_size=read(fd,&cmpmsg,sizeof(cmpmsg)name,)=0) close(fd); return -1; while(read_size = sizeof(struct message); if(write_size=write(fd,recievemsg,sizeof(struct message)0) pe

16、rror(write); close(fd); return -2; while(write_size!=sizeof(struct message) /write_size = 0-writesize; lseek(fd,-write_size,SEEK_CUR); write_size=write(fd,recievemsg,sizeof(struct message); printf(write file successn); close(fd); return 0;int login_check(struct message *recievemsg) int fd; struct me

17、ssage cmpmsg; int read_size; if(fd=open(user.txt,O_RDONLY)0) perror(open); return -2; do if(read_size=read(fd,&cmpmsg,sizeof(struct message)name,)=0)&(strcmp(recievemsg-msg,cmpmsg.msg)=0) close(fd); return 0; while(read_size0); close(fd); return -1;/*void main()struct message sendmsg;prin

18、tf(input name:n);gets();printf(input mima:n);gets(sendmsg.msg); printf(%dn,reg_check(&sendmsg); /printf(%dn,login_check(&sendmsg); */*client.c*/#include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAXLEN 102

19、4struct message char flag15; char name10; int size; char msgMAXLEN;struct msq long msg_type; char msg_text5;int qid = -1,fd = -1,sockfd,savefilefd=-1;char filefromname10;void handleQuit(int signal_no) if(fd 0) close(fd); close(sockfd); if(qid 0) if(msgctl(qid,IPC_RMID,NULL)0) printf(消息隊列無法關閉n); exit

20、(1); close(savefilefd); printf(程序正常退出n); raise(SIGQUIT);void cutStr(char str,char left, int n, char right,int m, char c) int i,k,j; for(i = 0 ; i n ;i+) if(stri = c) break; if(i = n) i = -1; else memset(left,0,strlen(left); for(k = 0 ; k i ; k+) leftk = strk; for(j = i+1 ; j m;j+) if(strj = 0) break

21、; rightj-i-1 = strj; lefti = 0; if(j 0) printf(filedata.msg= %sn,filedata.msg); send(sockfd,&filedata,sizeof(structmessage),0); else printf(讀取文件失敗,文件傳輸中止n); break; while (filedata.size 0); close(savefilefd); savefilefd = -1 ;void handlerecvmsg(int *sockfd) int connfd = *sockfd; int nread; char buf10

22、24; char str1024; struct message recvmsg; time_t timep; struct msq msg; if( fd =open(chatlog.txt,O_RDWR|O_CREAT|O_APPEND) 0) printf(打開聊天記錄文件失敗!); exit(1); / printf(%dn,fd); if(qid = msgget(2222,IPC_CREAT|0666) = -1) printf(創(chuàng)建消息隊列失敗n); exit(1); msg.msg_type = getpid(); strcpy(msg.msg_text,OK); while(

23、1) nread = recv(connfd,&recvmsg,sizeof(struct message),0); if(nread = 0) printf(與服務器斷開了連接n); close(fd); close(connfd); exit(0); else if (strcmp(recvmsg.flag,all) = 0) time (&timep); sprintf(str,%s%s發(fā)給所有人:%snn,ctime(&timep),,recvmsg.msg); else if (strcmp(recvmsg.flag,sermsg) = 0) time (&t

24、imep); printf(%s服務器發(fā)給所有人:%snn,ctime(&timep),recvmsg.msg); continue; else if (strcmp(recvmsg.flag,view) = 0) time (&timep); printf(%s當前在線客戶端:n%snn,ctime(&timep),recvmsg.msg); continue; else if (strcmp(recvmsg.flag,trans) = 0) pthread_t pid; if (strcmp(recvmsg.msg,agree) = 0) strcpy(filefromname,recvm

25、); /創(chuàng)建線程發(fā)送文件 pthread_create(&pid,NULL,(void *)handlesendfile,NULL); else if(strcmp(recvmsg.msg,disagree) = 0) printf(對方拒絕接收文件n); close(savefilefd); savefilefd = -1; else if(strcmp(recvmsg.msg,noexist) = 0) printf(該客戶端不存在n); close(savefilefd); savefilefd = -1; else strcpy(filefromname,recvmsg.

26、name); printf(%s向你請求傳名為%s文件,是否同意接受?agree(同意)|disagree(不同意)n,,recvmsg.msg); savefilefd = 0; continue; else if(strcmp(recvmsg.flag,transf) = 0) int n; if(strcmp(recvmsg.msg,end$) = 0) printf(文件傳輸結束n); close(savefilefd); savefilefd = -1; continue; else n=write(savefilefd,recvmsg.msg,recvmsg

27、.size); / printf(recvmsg.msg = %sn,recvmsg.msg); while(n 0) lseek(savefilefd,n,SEEK_CUR); n=write(savefilefd,recvmsg.msg,recvmsg.size); continue; else time (&timep); sprintf(str,%s%s發(fā)來的私聊消息:%snn,ctime(&timep),,recvmsg.msg); write(fd,str,strlen(str); msgsnd(qid,&msg,sizeof(struct msq),0);

28、 int main(int argc,char *argv) struct sockaddr_in server_addr; int port; int do_number; struct message a; char strMAXLEN; char bufMAXLEN; pthread_t pid; if(argc != 3) printf(請輸入服務器IP和端口n); exit(1); port = atoi(argv2); if(sockfd =socket(AF_INET,SOCK_STREAM,0) = -1) printf(創(chuàng)建socket失敗n); exit(1); signa

29、l(SIGINT,handleQuit); printf(-n); printf(|n); printf(| input a number to work |n); printf(|t1.loginttt |n); printf(|t2.registertt |n); printf(|t3.exitttt |n); printf(|n); printf(-n); scanf(%d,&do_number); gets(str); while(do_number != 1 & do_number != 2 &do_number != 3) printf(你輸入的不是上面的選項,請重新輸入:n);

30、scanf(%d,&do_number); gets(str); if(do_number=3) close(sockfd); printf(程序已退出!n); exit(0); bzero(&server_addr,sizeof(struct sockaddr_in); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr(argv1); server_addr.sin_port = htons(port); if(connect(sockfd,(struct sockaddr*)&server_a

31、ddr,sizeof(struct sockaddr) = -1) printf(與服務器無響應,請隔一段時間再連接n); exit(2); if(do_number =1) int n = 3; while(n) printf(請輸入你的用戶名:n); scanf(%s,); printf(請輸入密碼:n); scanf(%s,a.msg); strcpy(a.flag,login); /a.flag3 = 0; send(sockfd,&a,sizeof(a),0); printf(正在等待服務器應答.n); recv(sockfd,buf,MAXLEN,0); printf(

32、接到服務器發(fā)來的信息:%sn,buf); if(strcmp(buf,登錄成功!) = 0) /int i,j,k; pthread_create(&pid,NULL,(void*)handlerecvmsg,(void *)&sockfd); gets(str); strcpy(a.flag,all); while(1) memset(a.msg,0,strlen(a.msg); memset(str,0,strlen(str); gets(str); strcpy(buf,a.flag); cutStr(str,a.flag,15,a.msg,MAXLEN,$); printf(標志信息為

33、:%sn,a.flag); if(strcmp(a.flag,view) = 0) send(sockfd,&a,sizeof(a),0); strcpy(a.flag,buf); continue; else if (strcmp(a.flag,trans) = 0) & (savefilefd =0) / printf(f=%s,a=%s,s=%d,a.flag,a.msg,savefilefd); if (strcmp(a.msg,agree) = 0) & (savefilefd = 0) charsavefilename20; /charsavefileallname22; prin

34、tf(請輸入保存的文件名,文件將保存在當前目錄下!n); do gets(savefilename); savefilefd = open(savefilename,O_RDWR|O_CREAT|O_EXCL,0666); if(savefilefd = -1) printf(文件名可能存在請重新命名.n); while(savefilefd = -1); if(savefilefd 0) printf(創(chuàng)建文件失??!n); savefilefd = -1; else strcpy(,filefromname); send(sockfd,&a,sizeof(a),0); / pri

35、ntf(agree :%s,%s,%sn,a.flag,,a.msg); else memset(,0,strlen(); memset(str,0,strlen(str); cutStr(a.msg,,10,str,MAXLEN,$); if (str0 != 0 & 0 != 0) chartransfileallname22; sprintf(transfileallname,./%s,str); savefilefd = open(str,O_RDWR,0666); if(savefilefd 0) printf(打開文件失敗

36、!n); savefilefd = -1; else memset(a.msg,0,strlen(a.msg); strcpy(a.msg,str); send(sockfd,&a,sizeof(a),0); /printf(tansmit :%s,%s,%s,a.flag,,a.msg); else strcpy(a.msg,disagree); strcpy(,filefromname); send(sockfd,&a,sizeof(a),0); / printf(disagree :%s,%s,%s,a.flag,,a.msg); strcpy(a.f

37、lag,buf); continue; if (strcmp(a.flag,trans) = 0) strcpy(a.flag,buf); send(sockfd,&a,sizeof(a),0); else n-; printf(您還有%d次機會,之后將推出程序!n,n); close(sockfd); exit(3); /登陸 else if(do_number =2) /register int i =1 ; char username10; char password20; char password_t20; char temp20; printf(請輸入你的用戶名:n); scanf

38、(%s,username); while(i) printf(請輸入密碼:n); scanf(%s,password); printf(youpass : %sn,password); printf(請再次輸入密碼:n); scanf(%s,password_t); printf(passyou : %sn,password_t); if(strcmp(password,password_t) != 0) printf(輸入的密碼不一樣n); i = 1; else i = 0; strcpy(,username); strcpy(a.msg,password); strcpy(a

39、.flag,reg); /a.flag3 = 0; send(sockfd,&a,sizeof(a),0); printf(正在等待服務器應答.n); recv(sockfd,buf,MAXLEN,0); printf(接到服務器發(fā)來的信息:%sn,buf); close(sockfd); return 0; /*display.c*/ #include #include #include #include #include #include #include #include #include int qid,fd;struct msq long msg_type; char msg_tex

40、t5;void handlequit(int sign_no) close(fd); if(msgctl(qid,IPC_RMID,NULL) 0) printf(消息隊列無法關閉n); exit(1); printf(程序正常退出n); raise(SIGQUIT);int main() char buf1024; int n; struct msq msg; fd = open(chatlog.txt,O_RDONLY|O_CREAT); signal(SIGINT,handlequit); if(fd0) printf(打開文件失敗n); return -1; lseek(fd,0,SE

41、EK_END); if(qid = msgget(2222,IPC_CREAT|0666) = -1) printf(創(chuàng)建消息隊列失敗n); close(fd); return -1; while(1) if(msgrcv(qid,&msg,sizeof(msg),0,0) next = NULL; return L;void deletelist(LinkList L ,datatype e) int i=0; LinkList s,p; p = L; while ( (strcmp(,) != 0) & p-next != NULL) s=p; p = p

42、-next; if (p-next = NULL &(strcmp(,) != 0) return; else s-next = p-next; free(p); void insertend(LinkList L,datatype e) int i=0; LinkList s,p; p = L; while(p-next != NULL) p = p-next; i+; s = (LinkList)malloc(sizeof(LNode); s-data =e; s-next = p-next ; p-next =s;void DisplayList(LinkList L) L=L-next; int i = 1; while (L != NULL) printf(%d. %s n,i,L-); L = L-next; i+; /*void main()LinkList L;datatype res=0;L=CreateLinkList(); printf(aaaaan); DisplayList(L); printf(aaaaan); printf(n); insertend(L,500); pr

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論