精品文档。1欢迎下载计算机网络课程设计报告网络连天程序的设计与实现姓名:李坚学号:0855010206班级:计算机002指导老师:文宏湖南科技大学计算机科学与工程学院2011年9月精品文档。2欢迎下载一、课程设计题目利用WindowsSocket编程实现局域网的聊天程序,要求能实现消息的发送和接收,以及聊天软件的细节问题。二、题目分析拿到题目之后先来了解windowssocket连接的过程与相关的API函数。按照题目的要求,我简单的分析了下并做了初步的设计:利用tcp协议建立连接,这样服务器和客户端分离,服务端先启动并监听端口,客户端启动之后连接服务端建立连接,接着收发聊天信息。当任意一方连接断开的时候给出适当的提示并结束程序。因为功能比较简单,所以设计起来还是比较容易的。实际的操作中我遇到了很多新奇的问题并通过一些方案修改或者实现了最终的功能。三、设计步骤1、熟悉网络编程概念以及一些基本知识2、在windows的编程环境下熟悉了常用socket函数3、先整体再局部顺序设计程序4、调试并修改程序,使之实现设计要求5、测试程序,从中找出程序缺陷和可改进内容6、重复修改和测试,以达到自己理想的功能7、程序评定测试精品文档。3欢迎下载8、撰写设计报告四、设计过程第一个版本并未实现收发同步,只是简单的阻塞式通信。因为没有用到多线程,所以在程序监听网络数据写入时不能监听键盘输入,所以只能发一条后接一条,其中的问题可想而知。第二个版本用多线程实现了同时收发问题,在连接建立后新建一个线程用来等待键盘输入,而主体线程等待网络输入,当网络输入错误时(连接断开),结束线程并作下一步处理。这个版本就上个版本改进很多,主要可以即时在屏幕输出接收到的消息,同时也出现了另外一个缺陷:当键盘输入到一半时程序收到了网络的信息,这个时候程序的做法是直接输出这条信息,这导致我们键盘输入的信息被切断,很不人性化。第三个版本,也就是目前评测的版本,这个版本利用临界值来锁定屏幕资源,让程序在同一时刻只能一个程序拥有屏幕控制权,这样保证了不会交叉显示。另外我用自己的输入输出代替了原有的scanf和printf,这样使读写更安全可靠。同时改进的还有等待机制,在服务器启动之后立即监听本机6000端口,建立连接之后直接开辟线程等待输入。而客户端启动时要输入目的机的ip地址,连接完成时打印欢迎信息并开始进入聊天。聊天结束(断开)之后可以重新输入目的机器ip地址以建立新连接。精品文档。4欢迎下载五、调用顺序图六、源代码1、共有文件soc.h(调试用文件)#includetime.hvoidgetime(char*s_tim){time_trawtime;structtm*timeinfo;time(&rawtime);timeinfo=localtime(&rawtime);sprintf(s_tim,%02d:%02d:%02d,timeinfo-tm_hour,timeinfo-tm_min,timeinfo-tm_sec);return;}2、服务端server.cpp#includestdio.h#includeWinsock2.h#includewindows.h#includeconio.h#includesocs.h服务端SocketBlindAcceptRecvSendClosePrintListenSocket客户端ConnectRecvPrintSendClose精品文档。5欢迎下载#pragmacomment(lib,ws2_32.lib)DWORDWINAPIgotsListen(LPVOID);DWORDWINAPIsetsListen(LPVOID);voidgeta(char*s);voidputa(char*,int);voidgetime(char*);CRITICAL_SECTIONg_cs;CRITICAL_SECTIONt_cs;charbufer[1000];intbuflen;boollinked;voidmain(void){HANDLEgotHandle;HANDLEsetHandle;WORDwVerR;WSADATAwsD;wVerR=MAKEWORD(1,1);if(WSAStartup(wVerR,&wsD))return;if(LOBYTE(wsD.wVersion)!=1||HIBYTE(wsD.wVersion)!=1){WSACleanup();return;}SOCKETscSr=socket(AF_INET,SOCK_STREAM,0);SOCKADDR_INadrSr;adrSr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);adrSr.sin_family=AF_INET;adrSr.sin_port=htons(6000);bind(scSr,(SOCKADDR*)&adrSr,sizeof(SOCKADDR));listen(scSr,5);SOCKADDR_INadrCl;intlen=sizeof(SOCKADDR);while(true){精品文档。6欢迎下载printf(bind[%d]success!\n,6000);SOCKETscCon=accept(scSr,(SOCKADDR*)&adrCl,&len);chars_adr[100];strcpy(s_adr,inet_ntoa(adrCl.sin_addr));linked=true;printf(link[%s]becreated!\n,s_adr);InitializeCriticalSection(&t_cs);gotHandle=CreateThread(NULL,0,&gotsListen,&scCon,0,NULL);setHandle=CreateThread(NULL,0,&setsListen,&scCon,0,NULL);while(linked){Sleep(10);}TerminateThread(setHandle,NULL);CloseHandle(gotHandle);CloseHandle(setHandle);DeleteCriticalSection(&t_cs);closesocket(scCon);printf(\nlink[%s]closed!\n,s_adr);}closesocket(scSr);return;}DWORDWINAPIgotsListen(LPVOIDlpParam){chargots[1000];while(linked){//EnterCriticalSection(&g_cs);if(recv(*(SOCKET*)lpParam,gots,1000,0)==-1)break;//LeaveCriticalSection(&g_cs);puta(gots,1);}linked=false;return0;}DWORDWINAPIsetsListen(LPVOIDlpParam){while(linked){geta(bufer);//EnterCriticalSection(&g_cs);send(*(SOCKET*)lpParam,bufer,strlen(bufer)+1,0);精品文档。7欢迎下载//LeaveCriticalSection(&g_cs);puta(bufer,0);}ExitThread(NULL);return0;}voidputa(char*s,intsta){inti=1;chars_tim[16];getime(s_tim);switch(sta){case0:EnterCriticalSection(&t_cs);while(i--)printf(\b\b);printf([local]%s\n%s\n,s_tim,s);LeaveCriticalSection(&t_cs);break;case1:EnterCriticalSection(&t_cs);i+=buflen;while(i--)printf(\b\b);printf([NET]%s\n%s\n,s_tim,s);printf(%s,bufer);LeaveCriticalSection(&t_cs);break;}};voidgeta(char*s){charc;EnterCriticalSection(&t_cs);printf();bufer[buflen=0]='\0';LeaveCriticalSection(&t_cs);while(c=getch()){if(c31&&c127){EnterCriticalSection(&t_cs);s[buflen++]=c;s[buflen]='\0';printf(%c,c);LeaveCriticalSection(&t_cs);精品文档。8欢迎下载}else{switch(c){case13:EnterCriticalSection(&t_cs);while(buflen--)printf(\b\b);LeaveCriticalSection(&t_cs);return;case8:EnterCriticalSection(&t_cs);if(buflen){buflen--;printf(\b\b);s[buflen]='\0';}LeaveCriticalSection(&t_cs);break;}}}}3、客户端client.cpp#includestdio.h#includeWinsock2.h#includewindows.h#includeconio.h#includesocs.h#pragmacomment(lib,ws2_32.lib)DWORDWINAPIgotsListen(LPVOID);DWORDWINAPIsetsListen(LPVOID);voidgeta(char*);voidputa(char*,int);voidgetime(char*);CRITICAL_SECTIONt_cs;charbufer[1000];intbuflen;boollinked;精品文档。9欢迎下载voidmain(void){HANDLEgotHandle;HANDLEsetHandle;chars_adr[10];WSADATAwsD;if(WSAStartup(MAKEWORD(1,1),&wsD))return;if(wsD.wVersion!=MAKEWORD(1,1)){WSACleanup();return;}SOCKETscSr=socket(AF_INET,SOCK_STREAM,0);while(true){printf(ReadytoConnect:);scanf(%s,s_adr);SOCKADDR_INadrSr;adrSr.sin_addr.S_un.S_addr=inet_addr(s_adr);adrSr.sin_family=AF_INET;adrSr.sin_port=htons(6000);linked=!connect(scSr,(SOCKADDR*)&adrSr,sizeof(SOCKADDR));if(linked){printf(link[%s]createdsuccess!\n,s_adr);InitializeCriticalSection(&t_cs);gotHandle=CreateThread(NULL,0,&gotsListen,&scSr,0,NULL);setHandle=CreateThread(NULL,0,&setsListen,&scSr,0,NULL);while(linked){Sleep(10);}TerminateThread(setHandle,NULL);TerminateThread(gotHandle,NULL);Clos