目录摘要 (3)第一章课程设计要求 (4)一、设计任务 (3)1.1.1 课程设计内容 (3)1.1.2、课程设计的基本要求 (3)二、设计基本思路及相关理论 (3)1.2.1、TCP/IP协议 (3)1.2.2、客户机/服务器模型 (4)1.2.3、设计基本思路 (4)第二章设计概要 (5)2.1 功能设计 (5)2.2 程序系统功能模块 (6)2.3 功能分析 (7)2.3.1 功能流程图: (7)2.3.2 程序主要功能说明 (7)第三章调试分析与测试结果 (23)3.1服务器端与客户端 (23)3.2文件管理的过程 (26)第四章设计总结 (28)参考文献 (28)课程设计评分表 (30)摘要网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。
Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。
Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序。
要学Internet上的TCP/IP网络编程,必须理解Socket接口。
Socket接口设计者最先是将接口放在Unix操作系统里面的。
如果了解Unix系统的输入和输出的话,就很容易了解Socket了。
常用的Socket类型有两种:流式Socket (SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。
流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。
Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序。
要学Internet上的TCP/IP网络编程,必须理解Socket接口。
关键字:Socket、文件传输、多线程第一章课程设计要求一、设计任务1.1.1 课程设计内容文件传输协议的简单设计与实现:学会利用已有网络环境设计并实现简单应用层协议,掌握TCP/IP网络应用程序基本的设计方法和实现技巧,加深对客户/服务器的工作模式的认识。
用socket 编程接口编写程序,分别为客户程序(ftpclient.cpp)和服务器程序(ftpserver.cpp)和管理程序。
1.1.2、课程设计的基本要求○1.巩固和加深对计算机网络原理的理解,提高综合运用本课程所学知识的能力。
○2.培养选用参考书,查阅手册及文献资料的能力。
培养独立思考,深入研究,分析问题、解决问题的能力。
○3.通过实际分析设计、编程调试,掌握计算机网络通信的基本规程,以及协议的利用方法,体会体系结构分层的思路。
○4.能够按要求编写课程设计报告书,能正确阐述设计和设计结果、正确绘制系统和程序框图。
○5.通过课程设计,培养严谨的科学态度,严肃认真的工作作风,和团队协作精神。
二、设计基本思路及相关理论1.2.1、TCP/IP协议T CP/IP协议是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP协议组成。
TCP/IP 定义了电子设备如何连入因特网,以及数据如何在它们之间传输的标准。
协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求。
通俗而言:TCP负责发现传输的问题,一有问题就发出信号,要求重新传输,直到所有数据安全正确地传输到目的地。
TCP是面向连接的通信协议,通过三次握手建立连接,通讯完成时要拆除连接,由于TCP是面向连接的所以只能用于点对点的通讯。
TCP提供的是一种可靠的数据流服务,采用一种称为“滑动窗口”的方式进行流量控制。
TCP将它的信息送到更高层的应用程序,例如Telnet的服务程序和客户程序。
应用程序轮流将信息送回TCP层,TCP层便将它们向下传送到IP 层,设备驱动程序和物理介质,最后到接收方。
1.2.2、客户机/服务器模型网络应用层程序一般都是以客户机/服务器模型的方式工作的,而因特网便是客户机/服务器模型的一个典型应用。
在这种工作方式中,一个服务器程序先启动,并在一个熟知端口侦听对服务器的请求,当客户机应用程序需要某种服务时,须向提供这种服务的服务器发出请求,服务器在接收到请求后,向客户机发出响应请求信息。
这样客户机用用程序和服务器程序之间变建立了连接,此后可以进行数据通信。
通信任务完成后需要关闭它们之间的通信连接。
图1 客户机/服务器模型的工作流程1.2.3、设计基本思路设计程序使客户端连接的时候,服务器将会向客户端发回一条消息告知它的IP地址,然后关闭连接并继续接收端口的连接。
建立各个命令功能对应的函数,发送请求,等待服务器端的服务。
服务器端初始化WinSock,创建SOCKET,获取主机信息,并对客户端进行会话,发送回复讯息给客户端,响应完毕后关闭连接,释放WinSock。
模拟TCP/IP协议的工作模式,在双方工作的时候开设一个熟知端口(4523),进行数据的传送与接收。
模拟TCP工作机制,确定数据端口传送数据时,进行分组传送。
服务器从打开开始,保持监听控制端口,当用户登陆成功后,主动分配该用户服务线程。
在传送数据的时候,为了确保不影响原程序的工作,应独立分配线程。
本设计基本图如下:第二章设计概要2.1 功能设计本项目是为了实现基于Socket进行文件传输的功能。
项目的分析及设计要求如下:1)整个系统中分为服务器端(Server)和客户端(Client)2)服务器端可以对文件进行管理,包括上传,下载,删除文件,重命名等3)客服端可以实现文件的上传、下载以及查看服务器下默认目录的文件列表4)在程序中应用多线程来实现多个客户端同时对一个服务器端进行请求操作2.2 程序系统功能模块图2.12.3 功能分析2.3.1 功能流程图:图2.2 面向连接的客户机/服务器程序工作模型2.3.2 程序主要功能说明主要功能实现代码如下:1.服务器端//server.cpp#include <stdio.h>#include <stdlib.h>#include <WinSock2.h>#include <io.h>#define LISTENPORT 12345#pragma comment(lib,"Wsock32")#pragma comment(lib,"ws2_32")sendFile(SOCKET conSock){printf("Prapare to send file\n");char *sendBuf = new char[100];FILE *in;char infile[50] ;printf("选择要传输的文件");scanf("%[^\n]s",infile);if((in=fopen(infile,"rb"))==NULL){printf("Can't open the source file");exit(0);}printf("File name is %s\n", infile);// send file name to the clientsend(conSock, infile, sizeof(infile), 0);int handle = open(infile, 0x0001);long file_len = filelength(handle);long file_len_bak = file_len;printf("Size of the file is %d\n", file_len);// store the length of the file in sendBuffer int i;for (i = 0; file_len > 9; i++){sendBuf[i] = (file_len % 10);file_len = file_len / 10;}sendBuf[i] = file_len % 10;send(conSock, sendBuf, i + 1, 0);printf("Transmission started\n");Sleep(1);char ch;char chack;while (file_len_bak != 0){ch = fgetc(in);send(conSock, &ch, 1, 0);recv(conSock, &chack, 1, 0);file_len_bak--;printf(".");}ch = EOF;send(conSock, &ch, 1, 0);printf("\nTransmission finished");}int main(){WSADATA words;if(WSAStartup(MAKEWORD(2,2),&words)!=0){printf("Winsock init failed!\n");}SOCKET listenSock, conSock;sockaddr_in remoteAddr;int remoteAddrLen, int ServerAddrLen;listenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listenSock == INVALID_SOCKET){printf("ListenSocket create failed!\n");return 0;}sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(LISTENPORT);sin.sin_addr.S_un.S_addr = INADDR_ANY;ServerAddrLen = sizeof(sin);if (bind(listenSock, (sockaddr *)&sin, ServerAddrLen) == SOCKET_ERROR) {printf("Bind error!\n");return 0;}if (listen(listenSock, 2) == SOCKET_ERROR){printf("Can't listen!\n");return 0;}remoteAddrLen = sizeof(remoteAddr);while (TRUE){conSock = accept(listenSock, (sockaddr *)& remoteAddr, &remoteAddrLen);if (conSock == INVALID_SOCKET){printf("Accept failed!\n");continue;}else{printf("Accept a new connect : %s \r\n", inet_ntoa(remoteAddr.sin_addr));sendFile(conSock);}}closesocket(conSock);closesocket(listenSock);WSACleanup();return 1;}2.客户端//client.cpp#include <stdio.h>#include <stdlib.h>#include <WinSock2.h>#include <fstream>using namespace std;#define SERVERPORT 12345#pragma comment(lib, "Wsock32")#pragma comment(lib, "ws2_32")receiveFile(SOCKET consock){printf("Prepare to receive file\n");FILE *dest;char destfile[50];char recvBuff[100];// Receive name of the fileint namelen = recv(consock, recvBuff, 100, 0);memcpy(destfile, recvBuff, namelen);printf("Name of the file is %s \n", destfile);if((dest=fopen(destfile,"wb"))==NULL){printf("Can't open the dest file");exit(0);}// Receive size of the fileint flag_file_len = recv(consock, recvBuff, 100, 0); long file_len = 0;for (int i = 0; flag_file_len != 0; i++){long temp = recvBuff[i];for (int j = 0; j != i; j++){temp = temp * 10;}file_len = file_len + temp;flag_file_len--;}printf("Size of the file is %ld\n", file_len);printf("Ready to receive file\n");char ch;char chack = 1;int n;while ( recv(consock, &ch, 1, 0)){fputc(ch, dest);send(consock, &chack, 1, 0);file_len--;if (file_len == 0){break;}printf(".");}printf("\nTransmission finished\n");}int main(){WSADATA words;if(WSAStartup(MAKEWORD(2,2),&words)!=0){printf("Winsock init failed\n");}SOCKET conSock;conSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (conSock == INVALID_SOCKET){printf("Socket create failed\n");return 0;}sockaddr_in servAddr;servAddr.sin_family = AF_INET;servAddr.sin_port = htons(SERVERPORT);servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");if (connect(conSock, (sockaddr *)& servAddr, sizeof(servAddr)) == -1) {printf("Connect failed\n");return 0;}else{printf("Connect to server succeed\n");receiveFile(conSock);}closesocket(conSock);WSACleanup();return 1;}3.管理系统#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <string.h>#include <time.h>#define SYS_SIZE 0XFFFFF*100#define BLOCK_SIZE 512FILE *f;struct filsys{int s_nfree;long s_free[100];int s_ninode;int s_inode[96];}*p;struct index_block{int s_nfree;long s_free[96];}q;struct filelist{char name[14];int inode_num;}file;struct inode{int i_size;int block_amount;long i_addr[16];char create_time[25];}inode;struct fcb{char name[12];int inode_num;int used;int i_size;int block_amount;long i_addr[16];}fcb[5],*ptr;struct open_file_table{int offset;struct fcb* f_node;}table[5];struct fd{struct open_file_table* t_node;}fd[5];FILE* apply_room(char *sys_name){f = fopen(sys_name,"w+b"); //创建一个新的可读写的二进制文件 fseek(f,SYS_SIZE,SEEK_SET);fputc(EOF, f);fclose(f);return fopen(sys_name,"r+b"); //打开一个可读写的二进制文件}void myfree(long block_num){int i;if(p->s_nfree<100){p->s_free[p->s_nfree]=block_num;p->s_nfree++;}else{q.s_nfree=p->s_nfree;for(i=0;i<100;i++)q.s_free[i]=p->s_free[i];fseek(f,(block_num-1)*BLOCK_SIZE,SEEK_SET); fwrite(&q,sizeof(struct index_block),1,f); p->s_nfree=1;p->s_free[0]=block_num;}}long myalloc(){int i;long a;p->s_nfree--;if(p->s_nfree==0){a=p->s_free[0];fseek(f,(a-1)*BLOCK_SIZE,SEEK_SET);fread(&q,sizeof(struct index_block),1,f); p->s_nfree=q.s_nfree;for(i=0;i<100;i++)p->s_free[i]=q.s_free[i];return a;}else return p->s_free[p->s_nfree];}void init(){int j;long i;p->s_nfree=1;p->s_free[0]=0;p->s_ninode=96;for(i=0;i<96;i++)p->s_inode[i]=-1;for(i=22;i<=SYS_SIZE/BLOCK_SIZE;i++)myfree(i);j=p->s_nfree+1;while(j<100)p->s_free[j++]=0;fseek(f,0,SEEK_SET);fwrite(p,sizeof(struct filsys),1,f);}int ialloc(){int i=0;while(p->s_inode[i]>=0) i++;p->s_inode[i]=0;p->s_ninode--;return i;}int namei(char *name){int k=0;while(k<96){if(p->s_inode[k]!=-1){fseek(f,BLOCK_SIZE+k*16,SEEK_SET);fread(&file,sizeof(struct filelist),1,f); if(!strcmp(,name))return file.inode_num;}k++;};return -1;}int name_i(char *name){int k=0;do{if(fcb[k].used==1){if(!strcmp(fcb[k].name,name))return fcb[k].inode_num;}k++;}while(k<5);return -1;}void create(){int i,inode_num;long t;char name[12];printf("input file name:");scanf("%s",name);getchar();if(namei(name)!=-1) printf("file exited!\n");else{inode_num=ialloc();strcpy(,name);file.inode_num=inode_num;fseek(f,BLOCK_SIZE+inode_num*16,SEEK_SET);fwrite(&file,sizeof(struct filelist),1,f);inode.i_size=0;inode.block_amount=0;for(i=0;i<16;i++) inode.i_addr[i]=0;time(&t);strcpy(inode.create_time,ctime(&t));fseek(f,4*BLOCK_SIZE+inode_num*sizeof(struct inode),SEEK_SET); fwrite(&inode,sizeof(struct inode),1,f);p->s_inode[inode_num]=0;printf("create sucessfully!\n");}}void display(){int k;for(k=0;k<96;k++){if(p->s_inode[k]>=0){fseek(f,BLOCK_SIZE+k*16,SEEK_SET);fread(&file,sizeof(struct filelist),1,f);printf("%s ",);fseek(f,4*BLOCK_SIZE+file.inode_num*sizeof(structinode),SEEK_SET);fread(&inode,sizeof(struct inode),1,f);printf("size:? ",inode.i_size);printf("time:%s\n",inode.create_time);}};printf("\n");getchar();}void open_file(){ int i=0,j=0,k=0;int m,n;char name[12];printf("input file's name:");scanf("%s",name);getchar();n=namei(name);if(n==-1) printf("file not exits!\n");else if(p->s_inode[n]>0) printf("file have already been opened!\n"); else{while(fcb[i].used==1) i++;while(table[j].f_node) j++;while(fd[k].t_node) k++;fd[k].t_node=&table[j];table[j].f_node=&fcb[i];strcpy(fcb[i].name,name);fcb[i].inode_num=n;fcb[i].used=1;fseek(f,4*BLOCK_SIZE+n*sizeof(struct inode),SEEK_SET);fread(&inode,sizeof(struct inode),1,f);fcb[i].i_size=inode.i_size;fcb[i].block_amount=inode.block_amount;for(m=0;m<16;m++) fcb[i].i_addr[m]=inode.i_addr[m];p->s_inode[n]=k+100;printf("file is open!\n");}}void write_file(){ int sizeQ2;int k,block_amount,n,size=0,i=0;long block_num;char ch,name[12];printf("input file's name:");scanf("%s",name);getchar();n=name_i(name);if(n==-1) printf("file not exits or not open!\n");else{k=p->s_inode[n]-100;ptr=fd[k].t_node->f_node;while(i<ptr->block_amount){block_num=ptr->i_addr[i];myfree(block_num);i++;}block_amount=0;printf("input the context of the file:(end the file with '*')\n"); while((ch=getchar())!='*'&&block_amount<16){size++;if(sizeQ2==1){block_num=myalloc();inode.i_addr[block_amount]=ptr->i_addr[block_amount]=block_num;block_amount++;fseek(f,(block_num-1)*BLOCK_SIZE,SEEK_SET);}fputc(ch,f);}getchar();inode.i_size=ptr->i_size=size;inode.block_amount=ptr->block_amount=block_amount;fseek(f,4*BLOCK_SIZE+n*sizeof(struct inode),SEEK_SET);fwrite(&inode,sizeof(struct inode),1,f);}}void read_file(){int k,n,block_amount,size;int i=0;long block_num;char name[12],buf[512];printf("input file's name:");scanf("%s",name);getchar();n=name_i(name);if(n==-1) printf("file not exits or not open!");else{k=p->s_inode[n]-100;ptr=fd[k].t_node->f_node;size=ptr->i_size;block_amount=ptr->block_amount;for(i=0;i<block_amount;i++){block_num=ptr->i_addr[i];fseek(f,(block_num-1)*BLOCK_SIZE,SEEK_SET);if(size>512) {fread(buf,sizeof(char),512,f); size=size-512;} else{fread(buf,sizeof(char),size,f);buf[size]='\0';}printf("%s",buf);}}printf("\n");}void del_file(){ int n,i=0;long block_num;char name[12];printf("input file's name:");scanf("%s",name);getchar();n=namei(name);if(n==-1) printf("file not exits!\n");else if(p->s_inode[n]>0) printf("file is open now!Close it first\n"); else{p->s_inode[n]=-1;fseek(f,4*BLOCK_SIZE+n*sizeof(struct inode),SEEK_SET);fread(&inode,sizeof(struct inode),1,f);while(i<inode.block_amount){block_num=inode.i_addr[i];myfree(block_num);i++;}strcpy(,"");file.inode_num=0;fseek(f,BLOCK_SIZE+n*16,SEEK_SET);fwrite(&file,sizeof(struct filelist),1,f);printf("file is deleted\n");}}void close_file(){ int k,n;char name[12];printf("input file's name:");scanf("%s",name);getchar();n=name_i(name);if(n==-1) printf("file not exits or not open\n");else{k=p->s_inode[n]-100;fd[k].t_node->f_node->used=0;fd[k].t_node->f_node=NULL;fd[k].t_node=NULL;p->s_inode[n]=0;printf("file is closed!\n");}}void myexit(){ int i=0;char ch;while(fcb[i].used==0) i++;if(i<5){getchar();printf("some files are still open\n");printf("input 'q' to quit or other key to return:\n"); scanf("%c",&ch);if(ch=='q'){while(i<5){if(fcb[i].used==1) p->s_inode[fcb[i].inode_num]=0; i++;}fseek(f,0,SEEK_SET);fwrite(p,sizeof(struct filsys),1,f);exit(0);}getchar();}else{fseek(f,0,SEEK_SET);fwrite(p,sizeof(struct filsys),1,f);exit(0);}}void main(){int i;char ch,sys_name[15];p=(struct filsys *)malloc(sizeof(struct filsys));while(1){printf("1:Create a new file system\n");printf("2:open an existed file system\n");printf("choose:");if((ch=getchar())=='1'){printf("input file system's name:");scanf("%s",sys_name);getchar();f=apply_room(sys_name);init();break; //这里的break用来跳出while(1)的循环}else if(ch=='2'){printf("input file system's name:");scanf("%s",sys_name);getchar();f=fopen(sys_name,"r+b");fseek(f,0,SEEK_SET);fread(p,sizeof(struct filsys),1,f);break;}else{printf("wrong input!\n");getchar();}};for(i=0;i<5;i++){fcb[i].used=0;table[i].f_node=NULL;fd[i].t_node=NULL;}while(1){printf("--------------------------------------------------------------------\n");printf("1:create 2:open 3:write 4:read 5:close 6:delete 7:display 8:exit\n");printf("choose:");switch(getchar()-'0'){case 1:create();break;case 2:open_file();break;case 3:write_file();break;case 4:read_file();break;case 5:close_file();break;case 6:del_file();break;case 7:display();break;case 8:myexit();break;default:getchar(); printf("wrong input!\n"); break;}};free(p);fclose(f);}第三章调试分析与测试结果3.1服务器端与客户端需要传输的文件服务器和客户端建立连接的初始状态服务器传输文件及客户端接收文件的过程客户端接收到的文件3.2文件管理的过程文件管理创建的文件第四章设计总结这次课程设计可谓收获颇大,首先从一开始对编程只有肤浅的认识,到做完实验后有了一定程度的了解,并能够进行简单的程序设计和编写。