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

下載本文檔

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

文檔簡介

1、概述AbstractLinux作為免費開源操作系統廣泛應用于企業。Linux與UNIX有著深厚的淵源,而UNIX系統可謂“堅如磐石”,其穩定性受到廣泛贊譽。近年來,越來越多的就業崗位被提供給了Linux開發人員。IM即時通訊軟件是近年來流行的通信方式,企業、個人等都在更多地使用IM進行溝通。通過計算機網絡,信息的傳遞變得十分方便。并非所有IM軟件都要想騰訊QQ那樣復雜、龐大,作為內部溝通,只需功能齊全、操作方便即可。作為課程設計作品,在Linux下開發C/S式IM軟件,對于熟悉Linux、復習計算機網絡、進一步學習軟件開發都有十分積極的意義。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網絡聊天軟件1.1.2. 內容摘要隨著嵌入式在生活中的應用越來越廣泛,嵌入式LINUX下的Socket網絡編程也越來越熱。為了加強對在Linux系統下進行編程的學習和實踐,運用計算機網絡、軟件工程等知識,我們選擇了Linux下網絡聊天工具作為課設題目。本系統主要功能在于實現多個客戶端一與服務器端之問的信息傳遞與文件傳輸功能。系統主要實現4人聊天室功能

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

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

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

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

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

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

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

12、為trans標記:某某用戶給您發送了XX文件,Y接收N拒絕接收。如果客戶端按下N,則返回一條消息給服務器端,服務器端同時告訴發送的客戶端對方拒絕接收文件。發送端可以繼續做其他的事。如果接收的客戶端按下Y,并立即按受保存的路徑和文件名。輸入完后就可以接收文件了。客戶端返回一條消息給無誤器端,服務器端同時返回一條消息給發送的客戶端,告訴客戶端對方同意接收文件,這時候文件開始傳輸;發送完畢后,發送的客戶端會顯示傳輸完畢。傳輸的文件可以使任意的文們。不僅僅是文本,多媒體文件也可以。第4章 實現本設計由C語言實現,用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(創建消息隊列失敗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發給所有人:%snn,ctime(&timep),,recvmsg.msg); else if (strcmp(recvmsg.flag,sermsg) = 0) time (&t

24、imep); printf(%s服務器發給所有人:%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、); /創建線程發送文件 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發來的私聊消息:%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(創建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、接到服務器發來的信息:%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(創建文件失敗!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(接到服務器發來的信息:%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(創建消息隊列失敗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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論