上海电力学院《基于网络的应用开发》课程设计报告(2014/2015学年第一学期)课题名称用NetBIOS会话通信的方式实现简单FTP服务器课题号八院(系)电子与信息工程学院专业通信工程班级2011112学生王坚学号20112246时间2014年12月1日~2014年12月5日一、课程设计任务1、简单FTP服务器包括服务器端和客户端,使用NetBIOS实现服务器端和客户端之间的通信,通信方式为会话通信;2、简单FTP服务器:只要求实现文件上传功能,文件大小限制自定;3、客户端:输入所要上传文件的名称,读入文件的内容并把它发送到服务器;4、服务器端:接收数据,并把接收到的数据写入文件;5、使用VC6.0的开发环境,构建工程为Win32ConsoleApplication类型。二、基本原理会话是一种面向连接的可靠通信方式。在进行会话通信之前,必须首先建立一个会话连接,客户及利用NCBCALL命令同一个已知的服务建立连接;而服务器则使用NCBLISTEN“侦听”进入的客户机连接。若两个命令中有一个成功,NetBIOS接口便会建立一个会话,并分别为会话双方赋予唯一的会话号。随后,通信双方便可利用该会话号进行会话通信,与数据报相比,会话通信可以确保数据的完整性、抵达顺序以及传输可靠性,等等。下图为会话通信的基本模型从图中不难看出,NetBIOS的会话通信的主要分为如下6个步骤:①初始化。通信双方分别执行NCBRESET命令,复位各自的NetBIOS。②添加名字。为了建立会话,通信双方应在各自的本地名字表中添加唯一名。③建立会话。会话建立过程由服务器和客户机协同完成,服务器方使用NCBLISTEN命令等待客户机的连接请求,客户机使用NCBCALL命令向服务器发起会话连接请求,一旦会话建立成功,双方的NetBIOS将各自返回一个本地会话号,以后通信双方就可使用会话号进行会话通信。④数据传输。会话建立后,双方便可利用NCBSEND和NCBRECV等会话命令进行会话通信。⑤拆除会话。当数据传输结束时,任何一方均可发出NCBHANGUP命令来拆除指定会话号上的会话连接,以及时释放系统资源。⑥删除名字。在会话通信进程结束时,双方还应删除各自本地名字表中的名字。三、方案设计在理解会话通信模型的基础上,按照会话程序设计的基本步骤,便能轻松地设计会话通信程序。会话双方用NCBLISTEN/NCBCALL命令得到本地会话号,然后用NCBSEND和NCBRECV等会话命令进行会话通信。服务器端:服务器进程使用NCBLISTEN命令侦听客户进程的连接请求,当客户进程的连接请求到来时,响应并建立会话,随后,服务器进程进入接收等待,每收到一个客户进程发来的数据,便将其显示,然后继续等待接收下一个数据。当客户进程拆除会话时,退出循环,等待下一次的连接请求。客户端:客户进程使用NCBCALL命令向指定服务器发出连接请求,会话建立后,紧接着设置接收。当收到服务器发来的Pleaseinputnametosend:和Pleaseinputmessagetosend:的消息后,用户通过键盘分别输入名称与内容,通过指定的会话链路将所有数据发送到服务器方,等到所有数据传送完,客户进程拆除会话,退出循环,结束本次会话。四、实验结果五、总结与心得体会通过本次设计我熟悉VC6.0程序的开发环境和NetBIOS的使用。运用VC6.0来完成基于NetBIOS的会话通信方式来实现简单FTP服务器。在这次实验中我开始不是很会这个程序但是在同组成员的帮助下了解了这个程序,结果不是很好但是我在中间收获了很多。六、附录:实验代码服务器端:#includestdio.h#includestdlib.h#includewindows.h#includestring.h#includenb30.h#includememory.h#pragmacomment(lib,netapi32.lib)#defineMAXSESSIONS254//最大会话数为254#defineMAXNAMES254//最大名字数为254UCHARLana_Enum(LANA_ENUM*lenum)//获取可用lana{NCBncb;UCHARucRc;memset(&ncb,0,sizeof(NCB));ncb.ncb_command=NCBENUM;ncb.ncb_buffer=(PUCHAR)lenum;ncb.ncb_length=sizeof(LANA_ENUM);ucRc=Netbios(&ncb);return(ucRc);}UCHARRestNCB(UCHARlana)//复位特定的网络适配器{NCBncb;UCHARucRc;memset(&ncb,0,sizeof(ncb));ncb.ncb_command=NCBRESET;ncb.ncb_callname[0]=MAXNAMES;ncb.ncb_callname[2]=MAXSESSIONS;ncb.ncb_lana_num=lana;ucRc=Netbios(&ncb);return(ucRc);}UCHARAddName(CHAR*Name,UCHAR*NameNum,UCHARlana)//添加名字{NCBncb;//LANA_ENUMlenum;memset(&ncb,0,sizeof(NCB));ncb.ncb_command=NCBADDNAME;ncb.ncb_lana_num=lana;strcpy((char*)ncb.ncb_name,Name);Netbios(&ncb);*NameNum=ncb.ncb_num;return(ncb.ncb_cmd_cplt);}UCHARHangupSession(UCHARSessionNum){NCBncb;UCHARucRc;memset(&ncb,0,sizeof(NCB));ncb.ncb_command=NCBHANGUP;ncb.ncb_lsn=SessionNum;ucRc=Netbios(&ncb);return(ucRc);}voidNetbiosListen(PNCBpncb,HANDLEhEvent,CHARSourName[],CHARDestName[]){memset(pncb,0,sizeof(NCB));pncb-ncb_command=NCBLISTEN|ASYNCH;strcpy((char*)pncb-ncb_name,SourName);strcpy((char*)pncb-ncb_callname,DestName);pncb-ncb_rto=0;pncb-ncb_sto=5;pncb-ncb_cmd_cplt=0xff;pncb-ncb_event=hEvent;Netbios(pncb);}voidSessionSend(PNCBpncb,UCHARNum,UCHAR*pBuffer,WORDLength){memset(pncb,0,sizeof(NCB));pncb-ncb_command=NCBSEND;pncb-ncb_lsn=Num;pncb-ncb_buffer=pBuffer;pncb-ncb_length=Length;Netbios(pncb);}voidSessionRecv(PNCBpncb,UCHARNum,HANDLEhEvent,UCHAR*pBuffer){memset(pncb,0,sizeof(NCB));pncb-ncb_command=NCBRECV|ASYNCH;pncb-ncb_lsn=Num;pncb-ncb_buffer=pBuffer;pncb-ncb_length=512;pncb-ncb_cmd_cplt=0xff;pncb-ncb_event=hEvent;//pncb-ncb_lana_num=lana;Netbios(pncb);}intmain(){NCBServerNncb;UCHARLocalName[16];UCHARNameNum,SessionNum;HANDLEhEvent;LANA_ENUMlenum;charbuff[512];if(Lana_Enum(&lenum)!=NRC_GOODRET){printf(LanaEnumError!\n);return0;}if(RestNCB(lenum.lana[0])!=0){printf(ResetNCBFALSE!\n);return0;}printf(Lana_numis:%d\n,lenum.lana[0]);printf(ResetNCBOK!\n);strcpy(LocalName,Server);if(AddName(LocalName,&NameNum,lenum.lana[0]))return0;printf(AddNameOK!\n);hEvent=CreateEvent(NULL,FALSE,FALSE,Server);if(hEvent==NULL)return0;printf(CreateEventOK!\n);for(;;){printf(READY!\n);NetbiosListen(&ServerNncb,hEvent,LocalName,*);//侦听客户连接请求;WaitForSingleObject(hEvent,0xffffffff);if(ServerNncb.ncb_cmd_cplt!=0)return0;printf(ListenOK!\n);SessionNum=ServerNncb.ncb_lsn;printf(SessionNumis:%d\n,ServerNncb.ncb_lsn);strcpy(buff,WelcometoServer!\n);SessionSend(&ServerNncb,SessionNum,(UCHAR*)buff,sizeof(buff));for(;;){memset(buff,0,512);SessionRecv(&ServerNncb,SessionNum,hEvent,(UCHAR*)buff);WaitForSingleObject(hEvent,0xffffffff);//printf(Recv:);if(ServerNncb.ncb_cmd_cplt==0){printf(收到的文件名字是:%s,长度为:%d字节\n,buff,strlen(buff));printf(\n);SessionSend(&ServerNncb,SessionNum,(UCHAR*)buff,sizeof(buff));continue;}elseif(ServerNncb.ncb_cmd_cplt==0){printf(收到的文件内容是:%s,长度为:%d字节\n,buff,strlen(buff));printf(\n);SessionSend(&ServerNncb,SessionNum,(UCHAR*)buff,sizeof(buff));continue;}elsebreak;}}}客户端:#includestdio.h#includestdlib.h#includewindows.h#includestring.h#includenb30.h#includememory.h#pragmacomment(lib,netapi32.lib)#defineMAXSESSIONS254//最大回话数为254#defineMAXNAMES254//最大名字数为254UCHARLana_Enum(LANA_ENUM*lenum)//获取可用lana{NCBncb;UCHARucRc;memset(&ncb,0,sizeof(NCB));ncb.ncb_command=NCBENUM;ncb.ncb_buffer=(PUCHAR)lenum;ncb.ncb_lengt