LINUX下網絡即時聊天程序_第1頁
LINUX下網絡即時聊天程序_第2頁
LINUX下網絡即時聊天程序_第3頁
LINUX下網絡即時聊天程序_第4頁
LINUX下網絡即時聊天程序_第5頁
已閱讀5頁,還剩8頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、LINUX下網絡即時聊天程序-LINUX下網絡即時聊天程序-13/13LINUX下網絡即時聊天程序-IP和端口,主進度監(jiān)聽和循環(huán)接鑒于TCP協(xié)議的簡略網絡聊天程序一、設計原理:即時通信(IM)是指能夠即時發(fā)送和接收互聯(lián)網信息等的業(yè)務。自1998年面世以來,特別是近幾年的快速發(fā)展,即時通信的功能日趨豐富,漸漸集成了電子郵件、博客、音樂、電視、游戲和搜尋等多種功能。即時通信不再是一個純真的聊天工具,它已經發(fā)展成集溝通、資訊、娛樂、搜尋、電子商務、辦公協(xié)作和公司客戶服務等為一體的綜合化信息平臺。本課題實現(xiàn)簡單的及時通信中的聊天服務。問題定義:本課題要解決的問題是供應用戶自由向此外一個不一樣的用戶發(fā)信

2、息的同時接收來自其余用戶的信息。可行性研究:要實現(xiàn)即時通信的聊天模塊,能夠在LINUX下搭建服務器,在供應給用戶客戶端程序??蛻舳撕头掌髦g經過TCP協(xié)議實此刻線聊天。需求剖析:(1)為了實現(xiàn)即時通信的聊天服務,聊天服務器一定能夠同時接入多個用戶,因此要支持并發(fā),同意同時在線客戶端數(shù)目起碼大于3個。(2)要求服務器能接收多個用戶的接入懇求同時辦理已經成立連結的用戶的操作。(3)接收用戶發(fā)過來的信息。(3)正確轉發(fā)信息抵達正確的用戶。(4)供應簡單的用戶操作指令比方顯示及時在線的用戶。(5).來自不一樣用戶的信息的轉發(fā)的同步控制(6)。給每個用戶一個獨一的ID。整體設計第一我們應當在設計LIN

3、UX平臺設計服務器而且C語言編程。在實現(xiàn)并行辦理時能夠使用多進度也能夠使用多線程,多線程能夠方便的實現(xiàn)不一樣連結間簡略的通信,系統(tǒng)開支小因此這里采用它。在連結的協(xié)議選擇上,由于傳遞數(shù)據量小,這里選擇面向連結靠譜傳輸?shù)腡CP協(xié)議,對比將套接字嵌入FILE留種,這里使用調用常用的tcp的套接字API(send,recv)讀寫緩沖區(qū)實現(xiàn)連結的方法.5.詳盡設計客戶端:第一用戶供應服務器IP和端口,而后創(chuàng)立套接字并連結到服務器,連結成功賜予操作界面。設計用戶登岸接口函數(shù),發(fā)送名字用于登岸辦理。主進度掛載隨時接收用戶鍵盤輸入,并調用SEND()函數(shù)辦剪發(fā)送和指令操作。創(chuàng)辦一個線程用于掛載堵塞的recv(

4、);將收到的信息打印。服務器:服務器創(chuàng)立通用的服務器套接字綁定受客戶端接入懇求。接入用戶后創(chuàng)立線程傳入套接字,并接收用戶的登岸。登岸辦理后講該線程綁定一個用戶ID,并創(chuàng)立一個線程用于掛載RECV();第一個線程辦理要發(fā)給本連結綁定用戶的轉發(fā)服務。同時設計在線用戶的更新和打印辦理。使用互斥鎖來解決寫入的同步控制問題,在改正全局變量時候鎖住,當轉發(fā)完成時,解鎖。6.編碼和單元測試編碼見代碼和流程圖。測試沒有截圖,提列測試出現(xiàn)的部分問題:(1)段錯誤(核心已轉儲),原由:字符串辦理函數(shù)字符串數(shù)組與字符串指針的調用問題。改良:數(shù)組一致?lián)Q字符串指針,分派空間。(2)初始值設定不是常量,原由初始化在mai

5、n()開始前履行。改良:構造體分派在主函數(shù)里分派空間。(3)當recv()從緩沖器COPY的數(shù)據產生粘包。原由:沒有信息界限,解決:每次收發(fā)大小固定住。(4)連結封閉辦理。解決:設置套接字收發(fā)的標記位獲取退出原由,友善退出時套接字函數(shù)返回0。二、運轉方法說明、運轉結果運轉方法:linux下編譯服務器gccserver.cdie.c-lpthread-oserver.outLinux下編譯客戶端gccclient.cdie.c-lpthread-oclient.out服務器運轉server.out客戶端運轉client.out服務器運轉成功后有提示,客戶端運轉成功并登岸成功后有歡迎界面。用戶能夠

6、輸入LIST命令來獲取在線用戶列表。用戶能夠輸入CLOSE來退出程序。運轉結果:能達到設計要求,運轉速度正常。三、流程圖客戶端流程圖開始創(chuàng)立、設置套接字Connect();創(chuàng)立、設置套接字Nameland();Pthread_creat();接受鍵盤輸入能否輸入為”close”yesnoSend();定長數(shù)據Close(sock)履行threadmain()Recv()定長數(shù)據打印信息結束開始創(chuàng)立、設置套接字Bamd();Listrren();服務器流程圖Accept()While(1)創(chuàng)立clientsockPthread_craet();Close(serversock)結束履行threa

7、dmain();傳入套接字用戶名登岸辦理線程指定id更新用戶名列表Pthread_crreat();While(1)If(ID=id)Send()轉發(fā)信息履行threadmain();傳入套接字和id線程指定idWhile(1)Recv()定長數(shù)據If(recv!=0判斷收到的信息依據不一樣內容進行封裝封裝信息,ID=idClose(clientsock)更新用戶列表服務器#include#include#include#include#include#include#include#include#includePractical.hpthread_mutex_tmutex=PTHREAD_

8、MUTEX_INITIALIZER;/定義一個靜態(tài)鎖char*rmessage;/目前遇到來自客戶端的源信息intcurrentID=6;char*clientlist5;/用戶組姓名void*ThreadMain(void*arg);/void*ThreadMain2(void*arg);/掛send掛堵塞rcvdtypedefstructThreadArgsintclntSock;/線程要辦理的連結intnameID;/用戶在用戶組的地點threadMessage;intmain(intargc,char*argv)if(argc!=2)/Testforcorrectnumberofarg

9、umentsDieWithUserMessage(Parameter(s),);char*servPort=argv1;/Firstarg:localportrmessage=(char*)malloc(120);memset(rmessage,0,120);intservSock=SetupTCPServerSocket(servPort);if(servSockclntSock=clntSock;pthread_tthreadID;intreturnValue=pthread_create(&threadID,NULL,ThreadMain,threadArgs);if(returnVal

10、ue!=0)DieWithUserMessage(pthread_create()failed,strerror(returnValue);/printf(withthread:%ldn,(longint)threadID);free(rmessage);close(servSock);return0;void*ThreadMain(void*threadArgs)char*sname=(char*)malloc(20);charrongname=thenameexisted;charrightname=landsuccess;inti=0;memset(sname,0,20);pthread

11、_detach(pthread_self();intclntSock=(threadMessage*)threadArgs)-clntSock;while(i!=5)/判斷用戶名能否存在ssize_tnameRcvd=recv(clntSock,sname,20,0);if(nameRcvd=0)DieWithSystemMessage(recv()failed);*(sname+nameRcvd)=0;for(i=0;i5;i+)if(clientlisti!=NULL)if(strcmp(sname,clientlisti)=0)if(send(clntSock,rongname,size

12、of(rongname),0)=0)DieWithSystemMessage(sendname()failed);printf(用戶名已經存在n);break;for(i=0;i5;i+)/指定用戶名在用戶組的地點if(clientlisti=NULL)break;if(send(clntSock,rightname,sizeof(rightname),0)nameID=i;pthread_tthreadID;intreturnValue=pthread_create(&threadID,NULL,ThreadMain2,threadArgs);if(returnValue!=0)DieWit

13、hUserMessage(pthread_create()failed,strerror(returnValue);while(1)if(clientlisti=NULL)break;if(i=currentID)/判斷是不是給本連結的信息,是就發(fā)出去ssize_tnumBytesSent=send(clntSock,rmessage,120,0);if(numBytesSentclntSock;nameid=(threadMessage*)threadArgs)-nameID;free(threadArgs);/Deallocatememoryforargumentwhile(1)ssize

14、_tnumBytesRcvd;inttotalRecv=0;/getchar();while(totalRecv120)numBytesRcvd=recv(clntSock,buffer+totalRecv,120-totalRecv,0);if(numBytesRcvd=0)break;/判斷客戶封閉if(numBytesRcvd0)DieWithSystemMessage(recv()failed);totalRecv+=numBytesRcvd;if(numBytesRcvd=0)break;printf(收到:%sn,buffer);/問題4:假定鎖被線程1用了,同時線程2堵塞在LOC

15、K,這時假如客戶在send2次信息過來,線程2下次調用recv會不會把2次send的數(shù)據和起來一次放進緩沖區(qū)里?if(pthread_mutex_lock(&mutex)!=0)printf(lockfailed);if(strcmp(buffer,list)=0)/編寫list命令charlocate3=n1:;strcpy(rmessage,服務器在線用戶列表);for(j=0;j5;j+)if(clientlistj!=NULL)strcat(rmessage,locate);strcat(rmessage,clientlistj);locate1+;currentID=nameid;c

16、ontinue;/分析遇到的信息,并編碼要傳達的信息b=buffer;y=strsep(&b,:);for(j=0;j5;j+)/對話時無功效戶名辦理if(clientlistj!=NULL)if(strcmp(y,clientlistj)=0)break;if(j=5)currentID=nameid;strcpy(rmessage,您要對話的用戶不存在);else/加入發(fā)送者名字currentID=j;strcpy(rmessage,clientlistnameid);strcat(rmessage,:);strcat(rmessage,b);printf(to:%sn,rmessage)

17、;辦理客戶退出并通知上一層線程printf(用戶%s已經退出n,clientlistnameid);/問題:一開始沒方法及時打印會等下次“收到”才打印?后邊測試又能夠?free(clientlistnameid);clientlistnameid=NULL;free(buffer);return(NULL);客戶端#include#include#include#include#include#include#include#include#includePractical.hvoid*ThreadMain(void*arg);/用來掛堵塞的rcvdstructThreadArgsintcln

18、tSock;/傳達給線程要辦理的套接字;intmain(intargc,char*argv)if(argc!=3)DieWithUserMessage(Parameter(s),);char*server=argv1;/Firstarg:serveraddress/namechar*echoString=(char*)malloc(120);char*service=argv2;intsock=SetupTCPClientSocket(server,service);/創(chuàng)立套接字并connectif(sockclntSock=sock;pthread_tthreadID;/創(chuàng)立線程intret

19、urnValue=pthread_create(&threadID,NULL,ThreadMain,threadArgs);if(returnValue!=0)DieWithUserMessage(pthread_createfailed,strerror(returnValue);printf(|獲取在線用戶列表登岸成功請按此格式聊天(用戶名/close命令退出)|n);:信息內容)|n|(信息最長100字符/使用list命令/掛sendfor(;)scanf(%s,echoString);if(strcmp(echoString,close)=0)break;ssize_tnumBytes

20、=send(sock,echoString,120,0);if(numBytesclntSock;free(threadArgs);while(1)inttotalRecv=0;while(totalRecv120)ssize_tnumBytesRcvd=recv(csock,buffer+totalRecv,120-totalRecv,0);if(numBytesRcvd=0)DieWithSystemMessage(recv()failed);totalRecv+=numBytesRcvd;fputs(收到信息來自:,stdout);/Setuptoprinttheechoedstring

21、fputs(buffer,stdout);/Printthebufferfputc(n,stdout);/Printafinallinefeedreturn(NULL);自寫的接口#include#include#include#include#include#include#include#includePractical.h#include#includestaticconstintMAXPENDING=5;/MaximumoutstandingconnectionrequestsvoidDieWithUserMessage(constchar*msg,constchar*detail)f

22、puts(msg,stderr);fputs(:,stderr);fputs(detail,stderr);fputc(n,stderr);exit(1);voidDieWithSystemMessage(constchar*msg)perror(msg);exit(1);intSetupTCPClientSocket(constchar*host,constchar*service)/Tellthesystemwhatkind(s)ofaddressinfowewantstructaddrinfoaddrCriteria;/Criteriaforaddressmatchmemset(&add

23、rCriteria,0,sizeof(addrCriteria);/ZerooutstructureaddrCriteria.ai_family=AF_UNSPEC;/v4orv6isOKaddrCriteria.ai_socktype=SOCK_STREAM;/OnlystreamingsocketsaddrCriteria.ai_protocol=IPPROTO_TCP;/OnlyTCPprotocol/Getaddress(es)structaddrinfo*servAddr;/HolderforreturnedlistofserveraddrsintrtnVal=getaddrinfo

24、(host,service,&addrCriteria,&servAddr);if(rtnVal!=0)DieWithUserMessage(getaddrinfo()failed,budong);intsock=-1;structaddrinfo*addr;for(addr=servAddr;addr!=NULL;addr=addr-ai_next)/Createareliable,streamsocketusingTCPsock=socket(addr-ai_family,addr-ai_socktype,addr-ai_protocol);if(sockai_addr,addr-ai_a

25、ddrlen)=0)break;/Socketconnectionsucceeded;breakandreturnsocketclose(sock);/Socketconnectionfailed;trynextaddresssock=-1;freeaddrinfo(servAddr);/Freeaddrinfoallocatedingetaddrinfo()returnsock;voidPrintSocketAddress(conststructsockaddr*address,FILE*stream)/Testforaddressandstreamif(address=NULL|strea

26、m=NULL)return;void*numericAddress;/PointertobinaryaddressBuffertocontainresult(IPv6sufficienttoholdIPv4)charaddrBufferINET6_ADDRSTRLEN;in_port_tport;/PorttoprintSetpointertoaddressbasedonaddressfamilyswitch(address-sa_family)caseAF_INET:numericAddress=&(structsockaddr_in*)address)-sin_addr;port=ntoh

27、s(structsockaddr_in*)address)-sin_port);break;caseAF_INET6:numericAddress=&(structsockaddr_in6*)address)-sin6_addr;port=ntohs(structsockaddr_in6*)address)-sin6_port);break;default:fputs(unknowntype,stream);return;/Unhandledtype/Convertbinarytoprintableaddressif(inet_ntop(address-sa_family,numericAdd

28、ress,addrBuffer,sizeof(addrBuffer)=NULL)fputs(invalidaddress,stream);/Unabletoconvertelsefprintf(stream,%s,addrBuffer);if(port!=0)/Zeronotvalidinanysocketaddrfprintf(stream,-%u,port);intSetupTCPServerSocket(constchar*service)/ConstructtheserveraddressstructurestructaddrinfoaddrCriteria;/Criteriafora

29、ddressmatchmemset(&addrCriteria,0,sizeof(addrCriteria);/ZerooutstructureaddrCriteria.ai_family=AF_UNSPEC;/AnyaddressfamilyaddrCriteria.ai_flags=AI_PASSIVE;/Acceptonanyaddress/portaddrCriteria.ai_socktype=SOCK_STREAM;/OnlystreamsocketsaddrCriteria.ai_protocol=IPPROTO_TCP;/OnlyTCPprotocolstructaddrinf

30、o*servAddr;/ListofserveraddressesintrtnVal=getaddrinfo(NULL,service,&addrCriteria,&servAddr);if(rtnVal!=0)DieWithUserMessage(getaddrinfo()failed,budong);intservSock=-1;structaddrinfo*addr;for(addr=servAddr;addr!=NULL;addr=addr-ai_next)/CreateaTCPsocketservSock=socket(addr-ai_family,addr-ai_socktype,

31、addr-ai_protocol);if(servSockai_addr,addr-ai_addrlen)=0)&(listen(servSock,MAXPENDING)=0)Printlocaladdressofsocketstructsockaddr_storagelocalAddr;socklen_taddrSize=sizeof(localAddr);if(getsockname(servSock,(structsockaddr*)&localAddr,&addrSize)0)DieWithSystemMessage(getsockname()failed);fputs(Bindingto,stdout);PrintSocketAddress(structsockaddr*)&localAddr,stdout);fputc(n,stdout);break;/Bindandlistensuccessfulclose(servSock);/CloseandtryagainFreeaddresslistallocatedbygetaddrinfo()freeaddrinfo(servAddr);returnservSo

溫馨提示

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

評論

0/150

提交評論