计算机网络课程设计报告网络连天程序的设计与实现)姓名:李坚学号: 06班级:计算机002指导老师:文宏湖南科技大学计算机科学与工程学院!2011年9月一、课程设计题目利用Windows Socket编程实现局域网的聊天程序,要求能实现消息的发送和接收,以及聊天软件的细节问题。
二、题目分析拿到题目之后先来了解windows socket连接的过程与相关的API 函数。
按照题目的要求,我简单的分析了下并做了初步的设计:利用tcp协议建立连接,这样服务器和客户端分离,服务端先启动并监听端口,客户端启动之后连接服务端建立连接,接着收发聊天信息。
当任意一方连接断开的时候给出适当的提示并结束程序。
)因为功能比较简单,所以设计起来还是比较容易的。
实际的操作中我遇到了很多新奇的问题并通过一些方案修改或者实现了最终的功能。
三、设计步骤1、熟悉网络编程概念以及一些基本知识2、在windows 的编程环境下熟悉了常用socket函数3、先整体再局部顺序设计程序4、调试并修改程序,使之实现设计要求5、测试程序,从中找出程序缺陷和可改进内容6、)7、重复修改和测试,以达到自己理想的功能8、程序评定测试9、撰写设计报告四、设计过程第一个版本并未实现收发同步,只是简单的阻塞式通信。
因为没有用到多线程,所以在程序监听网络数据写入时不能监听键盘输入,所以只能发一条后接一条,其中的问题可想而知。
第二个版本用多线程实现了同时收发问题,在连接建立后新建一个线程用来等待键盘输入,而主体线程等待网络输入,当网络输入错误时(连接断开),结束线程并作下一步处理。
这个版本就上个版本改进很多,主要可以即时在屏幕输出接收到的消息,同时也出现了另外一个缺陷:当键盘输入到一半时程序收到了网络的信息,这个时候程序的做法是直接输出这条信息,这导致我们键盘输入的信息被切断,很不人性化。
第三个版本,也就是目前评测的版本,这个版本利用临界值来锁定屏幕资源,让程序在同一时刻只能一个程序拥有屏幕控制权,这样保证了不会交叉显示。
另外我用自己的输入输出代替了原有的scanf 和printf,这样使读写更安全可靠。
同时改进的还有等待机制,在服务器启动之后立即监听本机6000端口,建立连接之后直接开辟线程等待输入。
而客户端启动时要输入目的机的ip地址,连接完成时打印欢迎信息并开始进入聊天。
聊天结束(断开)之后可以重新输入目的机器ip地址以建立新连接。
:五、调用顺序图六、《七、源代码1、共有文件(调试用文件)#include <>void getime(char *s_tim){time_t rawtime;struct tm * timeinfo;time ( &rawtime );timeinfo = localtime (&rawtime );]sprintf(s_tim,"%02d:%02d:%02d",timeinfo->tm_hour,timeinfo->tm_min,timeinfo->tm_sec);return ;}2、服务端#include <>#include <>#include <>)#include <>#include ""#pragma comment(lib,"")DWORD WINAPI gotsListen(LPVOID);DWORD WINAPI setsListen(LPVOID);void geta(char *s);void puta(char*,int);~void getime(char *);CRITICAL_SECTION g_cs;CRITICAL_SECTION t_cs;char bufer[1000];int buflen;bool linked;&void main(void){HANDLE gotHandle;HANDLE setHandle;WORD wVerR;WSADATA wsD;wVerR=MAKEWORD(1,1);@if(WSAStartup(wVerR,&wsD))return ;if(LOBYTE!=1||HIBYTE!=1){WSACleanup();return ;}*SOCKET scSr=socket(AF_INET,SOCK_STREAM,0);SOCKADDR_IN adrSr;=AF_INET;=htons(6000);bind(scSr,(SOCKADDR *)&adrSr,sizeof(SOCKADDR));/listen(scSr,5);SOCKADDR_IN adrCl;int len=sizeof(SOCKADDR);while(true){printf("bind[%d] success!\n",6000);SOCKET scCon=accept(scSr,(SOCKADDR *)&adrCl,&len);char s_adr[100];、strcpy(s_adr,inet_ntoa);linked=true;printf("link[%s] be created!\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 ;}DWORD WINAPI gotsListen(LPVOID lpParam){)char gots[1000];while(linked){// EnterCriticalSection(&g_cs);if(recv(*(SOCKET *)lpParam,gots,1000,0)==-1)break;// LeaveCriticalSection(&g_cs);puta(gots,1);}@linked=false;return 0;}DWORD WINAPI setsListen(LPVOID lpParam){while(linked){geta(bufer);// EnterCriticalSection(&g_cs);?send(*(SOCKET *)lpParam,bufer,strlen(bufer)+1,0);// LeaveCriticalSection(&g_cs);puta(bufer,0);}ExitThread(NULL);return 0;}@void puta(char *s,int sta){int i=1;char s_tim[16];getime(s_tim);switch(sta){case 0:EnterCriticalSection(&t_cs);while(i--)>printf("\b \b");printf("[local] %s\n %s\n",s_tim,s);LeaveCriticalSection(&t_cs);break;case 1: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;}};\void geta(char *s){char c;EnterCriticalSection(&t_cs);printf(">");bufer[buflen=0]='\0';LeaveCriticalSection(&t_cs);while(c=getch()){if(c>31&&c<127){¥EnterCriticalSection(&t_cs);s[buflen++]=c;s[buflen]='\0';printf("%c",c);LeaveCriticalSection(&t_cs);}else{switch(c){case 13:?EnterCriticalSection(&t_cs);while(buflen--)printf("\b \b");LeaveCriticalSection(&t_cs);return;case 8:EnterCriticalSection(&t_cs);if(buflen){…buflen--;printf("\b \b");s[buflen]='\0';}LeaveCriticalSection(&t_cs);break;}};}}3、客户端#include <>#include <>#include <>#include <>【#include ""#pragma comment(lib,"")DWORD WINAPI gotsListen(LPVOID);DWORD WINAPI setsListen(LPVOID);void geta(char *);&void puta(char*,int);void getime(char *);CRITICAL_SECTION t_cs;char bufer[1000];int buflen;—bool linked;void main(void){HANDLE gotHandle;HANDLE setHandle;char s_adr[10];WSADATA wsD;:if(WSAStartup(MAKEWORD(1,1),&wsD))return ;if!=MAKEWORD(1,1)){WSACleanup();return;}'SOCKET scSr=socket(AF_INET,SOCK_STREAM,0);while(true){printf("Ready to Connect:");scanf("%s",s_adr);SOCKADDR_IN adrSr;=AF_INET;【=htons(6000);linked=!connect(scSr,(SOCKADDR *)&adrSr,sizeof(SOCKADDR));if(linked){printf("link[%s] created success!\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);CloseHandle(gotHandle);CloseHandle(setHandle);DeleteCriticalSection(&t_cs);(}else{printf("Failed to connect %s,check it and try again!\n",s_adr);}closesocket(scSr);printf("\nlink[%s] be closed!\n",s_adr);}return ;}~DWORD WINAPI gotsListen(LPVOID lpParam){char gots[10000];while(linked){// puts("running");// EnterCriticalSection(&g_cs);]if(recv(*(SOCKET *)lpParam,gots,1000,0)==-1)break;// LeaveCriticalSection(&g_cs);puta(gots,1);}linked=false;ExitThread(NULL);return 0;}|DWORD WINAPI setsListen(LPVOID lpParam){while(linked){geta(bufer);// EnterCriticalSection(&g_cs);send(*(SOCKET *)lpParam,bufer,strlen(bufer)+1,0);// LeaveCriticalSection(&g_cs);puta(bufer,0);}{ExitThread(NULL);return 0;}void puta(char *s,int sta){int i=2;char s_tim[16];getime(s_tim);—switch(sta){case 0:EnterCriticalSection(&t_cs);while(i--)printf("\b \b");printf("[local] %s\n %s\n",s_tim,s);LeaveCriticalSection(&t_cs);break;)case 1: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;}};void geta(char *s){char c;EnterCriticalSection(&t_cs);printf(">");《bufer[buflen=0]='\0';LeaveCriticalSection(&t_cs);while(c=getch()){if(c>31&&c<127){EnterCriticalSection(&t_cs);s[buflen++]=c;s[buflen]='\0';printf("%c",c);—LeaveCriticalSection(&t_cs);}else{switch(c){case 13:EnterCriticalSection(&t_cs);while(buflen--)printf("\b \b");LeaveCriticalSection(&t_cs);return;case 8:EnterCriticalSection(&t_cs);if(buflen){buflen--;printf("\b \b");s[buflen]='\0';}LeaveCriticalSection(&t_cs);break;}}}}八、调试运行本实例在同一ip和不同分别做了测试,运行状况达到了预期的效果,下面是相关的几张运行截图:服务器以及客户端启动的画面建立连接之后提示信息以及命令提示符客户端向服务器发送信息下面来做一系列的测试查看程序防交叉输出的功能:1、连接之后服务端在写一些内容2、客户端发送了一条消息,服务端将消息插入,并继续等待输入端输入3、服务器继续编辑文本并发送(注意服务器在收到消息之后可以修改输入的内容)断开连接九、心得体会经过了两个星期的学习,这次课程设计基本圆满完成了,这次课程设计我收获了很多。