1、局域网文件传输和聊天系统摘要:本课程设计包含了文件传输协议的简单设计与实现和两人聊天系统的设计与实现。学会利用已有网络环境设计并实现简单应用层协议,掌握TCP/IP网络应用程序基本的设计方法和实现技巧,加深对客户/服务器的工作模式的认识。初步练习基于TCP/IP网络编程的基本实现方法和思路,同时进一步熟悉计算机网络课程中基于IP层协议的工作机制。本设计完全用C语言编写,其中包括了具体设计任务,基本思路及所涉及的相关理论,设计流程图,调试过程中出现的问题及相应解决办法,核心程序,个人体会及建议等。关键词:IP层协议,TCP/IP网络编程1 具体设计任务计算机网络实验环境建立在TCP/IP 网络体
2、系结构之上。各计算机除了安装TCP/IP 软件外,还安装了TCP/IP 开发系统。实验室各计算机安装了VC+6.0,可对C语言进行编译,可为用户提供全网范围的进程通信功能。本实验要求利用这些功能,设计和实现一个简单的文件传送协议和两人聊天系统。2基本思路及所涉及的相关理论2.1基本思路 设计程序使客户端连接的时候,服务器将会向客户端发回一条消息告知它的IP地址,然后关闭连接并继续接收端口的连接。建立各个命令功能对应的函数,发送请求,等待服务器端的服务。服务器端确认IP地址,获取主机信息,并对客户端进行会话,发送回复讯息给客户端,响应完毕后关闭连接,释放。2.2 相关理论 文件传送是各种计算机网
3、络都实现的基本功能,文件传送协议是一种最基本的应用层协议按照客户/服务器的模式进行工作,提供交互式的访问,是INTERNET使用最广泛的协议之一。计算机网络实验环境建立在TCP/IP 网络体系结构之上。各计算机除了安装TCP/IP 软件外,还安装了TCP/IP 开发系统。实验室各计算机具备Windows环境中套接字socket 的编程接口功能,可为用户提供全网范围的进程通信功能。本设计利用这些功能,设计和实现一个简单的文件传送协议和两人聊天系统。用C语言可以简单的实现。3 设计流程图4 部分截图5 核心程序 #include #include #include #include #includ
4、e #include #pragma comment(lib,Ws2_32)#define M 512000 /每块传送文件的大小500k#define portNum 8888 /使用的端口号void LongToChar(long x,char a);/将long型整数转换成字符串long StrToLong(char str);/将字符串转换成long型整数void getW_name(char waddr,char wname); /获取文件名函数void sendFile(SOCKET ss); /服务端发送文件函数int receiveFile(SOCKET sc);/客户端接收文
5、件函数void chatting_client(SOCKET sc); /客户端聊天函数void chatting_server(SOCKET s_d); /服务端聊天函数int client(); /客户端主程序void server(); /服务端主程序void main()system(cls);system(color 0a);puts(n);puts( *);puts( * * );puts( * 欢迎使用局域网文件发送工具 *);puts( * * );puts( * * );puts( * * );puts( * 1. 客 户 端 * );puts( * * );puts( *
6、2. 服 务 端 * );puts( * * );puts( * 3. 结 束 * );puts( * * );puts( * * );puts( * 蓝天雄鹰 制作 * );puts( * 2012-6-20 * );puts( * 蓝鹰展翅气吞天下 * );puts( *n);puts(全屏(退出全屏)操作请按:ALT+ENTERn);printf(请输入你要选择的端代号(1-3):);char ch;char Num10;gets(Num);ch=Num0;while(ch =4 | ch =0)/检测用户选择的代码是否符合要求printf(n你的输入有误!请重新输入:);gets(Nu
7、m);ch=Num0;if(1=ch)client();else if(2=ch)server();else if(3=ch)exit(0);int client()system(color 0a);/修改DOS窗口颜色,是其成0A。WORD wVersion=MAKEWORD(1,1); WSADATA wsData; int nResult= WSAStartup(wVersion,&wsData); /启动WINSOCKETif(nResult !=0) printf(启动Winsock失败!n); SOCKET sc=socket(AF_INET,SOCK_STREAM,IPPROTO
8、_IP); /创建套接字if(sc=INVALID_SOCKET) printf(创建套接字失败!n); SOCKADDR_IN addrSc;addrSc.sin_family=AF_INET; addrSc.sin_port=htons(portNum); /保证字节顺序 char IP20;again:printf(请输入服务器的IP地址:);gets(IP);if( -1=inet_addr(IP) ) /循环检测IP地址是否合法printf(IP地址错误!n);goto again;addrSc.sin_addr.S_un.S_addr=inet_addr(IP); int b=0;
9、while(b5) /检测5次,如果服务器在此时间内启动,则进行连接nResult=connect(sc,(SOCKADDR*)&addrSc,sizeof(SOCKADDR); /套接字连接Sleep(DWORD)100);/延时1秒if(nResult=SOCKET_ERROR) printf( %d 次连接失败!n,b+1);elsebreak;b+;if(nResult=SOCKET_ERROR)printf(登陆超时,请重新登陆!n);goto again;char *buf=连接成功!; /向服务端验证连接成功nResult=send(sc,buf,strlen(buf)+1,0)
10、; if(nResult=SOCKET_ERROR) printf(5.套接字发送数据失败!n);return 0;char messM;nResult =recv(sc,mess,strlen(mess),0); /接受服务端的连接验证信息if(nResult = -1 ) /判断服务端是否关闭printf(n服务端已断开n);system(pause);exit(0);printf(%sn,mess);/ 功能菜单及操作 /tianle:system(cls); /清屏puts(nn);puts( *);puts( * * );puts( * 欢迎使用局域网文件发送工具 *);puts(
11、*(客 户 端) * );puts( * * );puts( * * );puts( * 请等待服务端的相应操作 * );puts( * * );puts( * * );puts( * 蓝天雄鹰 制作 * );puts( * 2012-6-20 * );puts( * 蓝鹰展翅气吞天下 * );puts( *n);puts(全屏(退出全屏)操作请按:ALT+ENTERn);char rMess100;nResult=recv(sc,rMess,strlen(rMess),0); /接收服务端发来的操作请求if(nResult=-1) /判断服务端是否关闭printf(n服务端已断开n);sys
12、tem(pause);goto tianle;printf(%sn,rMess);char ch;char str100;gets(str);ch=str0;while( ch!=Y & ch!=y & ch!=N & ch!=n ) /处理客户端的错误输入printf(输入有误,请重新输入(Y/N):);gets(str);ch=str0;send(sc,&ch,sizeof(char),0); /向服务端反馈选择,并执行相应操作if(strcmp(rMess,服务端向你传送文件,是否接受(Y/N):)=0 & (ch=Y | ch=y) )receiveFile(sc);if(strcmp
13、(rMess,服务端向你发起聊天,是否接受(Y/N):)=0 & (ch=Y | ch=y) )chatting_client(sc);if(ch=N | ch=n)printf(你拒绝了!n);system(pause);system(cls);goto tianle;nResult=closesocket(sc); /关闭套接字if(nResult=SOCKET_ERROR) printf(8.关闭套接字失败!n);return 0; void server()system(color 0a);/修改DOS窗口颜色为0AWORD wVersion=MAKEWORD(1,1); WSADAT
14、A wsData; int nResult= WSAStartup(wVersion,&wsData); /1、启动Winsockif(nResult !=0) printf(启动Winsock失败!n); SOCKET s=socket(AF_INET,SOCK_STREAM,IPPROTO_IP); /2.创建套接字if(s=INVALID_SOCKET) printf(创建套接字失败!n); SOCKADDR_IN addr; addr.sin_family=AF_INET; addr.sin_port=htons(portNum); /保证字节顺序 addr.sin_addr.S_un
15、.S_addr=htonl(INADDR_ANY);nResult=bind(s,(sockaddr*)&addr,sizeof(sockaddr); /3、套接字的绑定if(nResult=SOCKET_ERROR) printf(套接字的绑定失败!n); nResult=listen(s,5); /最多5个连接, 套接字的监听if(nResult=SOCKET_ERROR) printf(套接字的监听(服务器端)失败!n); SOCKADDR_IN addrClient;int len=sizeof(SOCKADDR);printf(n等待客户端的连接);int a=0;while(a5)
16、/开始的一个小动态图形for(int b=0;b=4 | ch tm_hour,local-tm_min,local-tm_sec,RMess);printf(n请输入信息:); /客户端用户输入消息gets(SMess);if(strcmp(SMess,exit)=0)send(sc,SMess,strlen(SMess)+1,0);printf(你已退出聊天程序!n);system(pause);break;/服务端显示自己的消息t=time(NULL); local=localtime(&t); printf(r%st%d:%d:%d n %sn,CName,local-tm_hour,
17、local-tm_min,local-tm_sec,SMess);send(sc,SMess,strlen(SMess)+1,0);void sendFile(SOCKET ss)char *str1=.确认成功.;send(ss,str1,strlen(str1)+1,0);/向客户端发送验证信息FILE *fp;long i;/文件分的的块数char fileAddr300;char fileName100;dmm:printf(请输入要传送的文件绝对地址(含文件名):);gets(fileAddr);if( (fp=fopen(fileAddr,rb) = NULL) /打开文件prin
18、tf(文件地址输入错误!n);goto dmm;getW_name(fileAddr,fileName);send(ss,fileName,strlen(fileName)+1,0); /发送文件名fseek(fp,0L,2);long fileLength=ftell(fp);/取得文件的长度fseek(fp,0L,0);char Length100;LongToChar(fileLength,Length);send(ss,Length,strlen(Length)+1,0);/发送文件大小到客户端if( 0 = fileLength%M )/对文件进行分块i=fileLength/M;e
19、lsei=fileLength/M+1;char messM;long readLength;/从文件读取的长度long sendLength;/发送文件的长度int k=1;/正在传送的模块号char *temp=开始接收文件;/向客户端开始传送,确认同步开始int nResult;nResult=recv(ss,mess,M,0);if(nResult = -1 ) /判断客户端是否关闭printf(n客户端已断开n);system(pause);return ;send(ss,temp,strlen(temp)+1,0);printf(%s,共 %ld 模块:n,mess,i);long
20、 total=0;while( k tm_hour,local-tm_min,local-tm_sec,SMess);send(s_d,SMess,strlen(SMess)+1,0);/在服务端显示客户端消息t=time(NULL); local=localtime(&t); receiveLength=recv(s_d,RMess,M,0);if(receiveLength=-1) /判断客户端是否关闭printf(客户端已断开n);system(pause);return ;if(strcmp(RMess,exit)=0)printf(n客户端已退出聊天程序,本程序也即将退出!n);system(pause);break;printf(n%st%d:%d:%dn %sn,CName,local-tm_hour,local-tm_min,local-tm_sec,RMess);void getW_name(char waddr,char wname)int i,k=0,j,w_len=strlen(waddr);for(i=w_len-1;i=0;i-)if(w