《网络编程》实验报告课程名称:网络编程实验项目名称:网络编程班级:实验室名称:专业:网络工程任课教师:黄梅根学号:姓名:基于TCP的网络文件传输实验报告一、实验目的1、熟悉TCP/IP协议的功能和网络操作2、编写小型的socket应用程序,初步了解windows环境下使用sockets编程,实现点对点文本传输。二、实验原理本程序是基于TCP/IP协议栈的网络编程,使用C语言,利用操作系统提供的套接字网络编程接口进行编写TCP协议是其中重要的传输协议,为应用层提供可靠的端到端的流传输服务.其中套接字取值sock_stream即为TCP的流传输服务Windowssocket包含了人们所熟悉的BerkeleySocket风格的函数库,也包含了一组针对windows的扩展库函数,以使程序员能充分的利用windows驱动消息机制进行编程。WindowsSockets的规范本意在于提供给应用开发者一套简单的API,并让个网络应用软件开发商遵守该协议。此外在一个特定的版本windows基础上,Windowssocket也定义了一个二进制借口(ABI),从此来保证WindowssocketAPI应用程序能够在任何符合Windowssocket协议的实现上工作。三、设计概述1、创建套接字服务进程和客户进程在实现通信前必须创建各自的套接字,然后才能用相应的套接字进行发送接收操作,服务进程总是先于客户端进程启动,服务器端进程和客户端进程创建套接字。Socket()函数实现代码如下:SOCKETserSocket=socket(AF_INET,SOCK_STREAM,0);//创建了可识别套接字2、地址绑定当调用socket()创建套接字后,服务器必须把套接字与自己的地址显式地建立联系,以便客户端向该IP地址和端口号的服务进程请求服务,这个过程是通过调用函数bind()实现的。bind()函数原型如下:intbind(SOCKETs,conststructsockaddrFAR*name,intnamelen);3、服务器套接字置为监听模式将服务器设置为监听工作方式后,使用API调用listen():intlisten(SOCKETs,intbacklog);第一个参数指定套接字。第二个参数指定了正在等待连接的最大队列长度。若无错误发生,则listen()函数返回0。4、建立连接,进行文件传输调用gets(path)获得传输文件的路径和存放文件路径,这个过程中还需调用send()函数和recv()函数,共同协调实现文件传送。四、源代码服务器端#includeWINSOCK2.H#includestdio.h#pragmacomment(lib,ws2_32.lib)#defineSIZE1024*8voidmain(){//创建套接字WORDmyVersionRequest;WSADATAwsaData;myVersionRequest=MAKEWORD(1,1);interr;err=WSAStartup(myVersionRequest,&wsaData);if(!err){printf(已打开套接字\n);}else{//进一步绑定套接字printf(嵌套字未打开!);return;}SOCKETserSocket=socket(AF_INET,SOCK_STREAM,0);//创建了可识别套接字//需要绑定的参数SOCKADDR_INaddr;addr.sin_family=AF_INET;addr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//ip地址addr.sin_port=htons(6000);//绑定端口bind(serSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR));//绑定完成listen(serSocket,5);//其中第二个参数代表能够接收的最多的连接数////////////////////////////////////////////////////////////////////////////开始进行监听//////////////////////////////////////////////////////////////////////////SOCKADDR_INclientsocket;intlen=sizeof(SOCKADDR);SOCKETserConn;charsendBuf[50];serConn=accept(serSocket,(SOCKADDR*)&clientsocket,&len);//如果这里不是accept而是conection的话。。就会不断的监听sprintf(sendBuf,welcome%stobejing,inet_ntoa(clientsocket.sin_addr));//找对对应的IP并且将这行字打印到那里//发送欢迎信息send(serConn,sendBuf,strlen(sendBuf)+1,0);FILE*fp;lable1:printf(客户端已打开\n请输入存放文件地址:\n);charpath[100]={0};inti=0;while(path[i]!='\0'){if(path[i]=='/')path[i]='\\';i++;}gets(path);if((fp=fopen(path,wb))==NULL){printf(文件未打开\n);gotolable1;}else{printf(文件已打开开始文件传输......\n);//发送开始标志send(serConn,开始传送,strlen(开始传送)+1,0);//得到文件大小chardatalength[20];longintlength=0;recv(serConn,datalength,21,0);length=atol(datalength);printf(得到文件大小:%d\n,length);//开始传送doublecent=0.0;charreceiveBuf[SIZE];longintx=0;while(1){x=x+SIZE;if(xlength){cent=(double)x*100.0/(double)length;printf(已接收:%4.2f%\n,cent);recv(serConn,receiveBuf,SIZE+1,0);fwrite(receiveBuf,1,SIZE,fp);}else{recv(serConn,receiveBuf,length+SIZE-x+1,0);printf(文件接收完毕\n);fwrite(receiveBuf,1,length+SIZE-x,fp);fclose(fp);break;}}}closesocket(serConn);//关闭WSACleanup();//释放资源的操作system(pause);}客户端#includeWINSOCK2.H#includestdio.h#pragmacomment(lib,ws2_32.lib)#defineSIZE1024*8voidmain(){FILE*fp;interr;intlength=0;SOCKETclientSocket;SOCKADDR_INclientsock_in;charreceiveBuf[100]={0};charip_addr[16]={127.0.0.1};WORDversionRequired;WSADATAwsaData;versionRequired=MAKEWORD(1,1);err=WSAStartup(versionRequired,&wsaData);//协议库的版本信息if(!err){printf(客户端嵌套字已经打开!\n);}else{printf(客户端的嵌套字打开失败!\n);return;//结束}clientSocket=socket(AF_INET,SOCK_STREAM,0);printf(请输入主机IP:\n);scanf(%s,ip_addr);//连接服务器clientsock_in.sin_addr.S_un.S_addr=inet_addr(ip_addr);clientsock_in.sin_family=AF_INET;clientsock_in.sin_port=htons(6000);connect(clientSocket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR));//开始连接recv(clientSocket,receiveBuf,101,0);printf(%s\n,receiveBuf);charpath[100]={0};gets(path);inti=0;do{printf(请输入文件地址:\n);gets(path);while(path[i]!='\0'){if(path[i]=='/')path[i]='\\';i++;}i=0;if((fp=fopen(path,rb))==NULL){i=1;printf(文件未打开\n);}}while(i);fseek(fp,0L,SEEK_END);length=ftell(fp);printf(待传送文件大小:%d\n,length);printf(文件已经打开等待主机消息......\n);//得到主机开始传送消息recv(clientSocket,receiveBuf,101,0);printf(%s\n,receiveBuf);if(strcmp(receiveBuf,开始传送)==0){//传送文件长度charsendBuf[20];ltoa(length,sendBuf,10);send(clientSocket,sendBuf,21,0);fseek(fp,0L,SEEK_SET);//传送文件longinty=0;doublecent;chartrans[SIZE];while(!feof(fp)){fread(trans,1,SIZE,fp);y=y+SIZE;if(ylength){cent=(double)y*100.0/(double)length;printf(已发送:%4.2f%\n,cent);send(clientSocket,trans,SIZE+1,0);}else{send(clientSocket,trans,length+SIZE-y+1,0);closesocket(clientSocket);WSACleanup();}}fclose(fp);}printf(文件发送完毕\n);system(pause);}五、实验结果及分析:客户端运行结果服务器端运行结果六、心得体会:网络编程的实验课虽然只有八次,但是我们充分了解了各种网络编程和winsock控件的知识,了解了TCP/IP协议的相关知识以及其中两个重要协议TCPUDP的特点与差异,进一步学习了文件传输等知识,创建套接字监听传输关闭等过程,直到最后写出C/S模式的文件传输程序感觉我们巩固了教材的内容实践的能力也得到了提高不足之处就是自己粗心大意,在写代码时候参数注解等经常注明的不够好,希望以后能养成良好的编程习惯