用winsock实现
ftp服务器
四川师范大学计算机科学学院
《网络编程与开发技术 程序设计》文档
FTP服务器客户端程序设计
专 业 软件工程
学生姓名 余恪平 曾强
班 级 2006级3 班
学 号 2006113052 2006113053
指导教师 冯朝胜老师
2008年12月8日
《
FTP服务器客户端程序设计》系统设计文档
1. 引言
1.1 编写目的
为了运用<<网络编程与开发技术>>所学知识和拓展我们在MFC中自己的编程能力,我们为此设计了“
FTP服务器客户端”。其一是实现在可视化界面下对多线程知识的实践,其二是运用网络编程知识实现文档上传和下载并实现同步。为了实现此程序除了学习必要的MFC知识外,我们还必须学习一些关于网络编程和多线程编程的知识。通过这次实践我们组成员对书本知识有更进一步了解,自学能力也增强不少。
1.2 项目背景
我们的系统基于vc开发平台下MFC可视化编程,为我们在学习了网络编程以后能够充分利用所学知识完成一些简单的功能,使自己得到一定的锻炼。运用所学知识和拓展我们自己的编程能力,我们为此设计了“
FTP服务器客户端”。
2. 整体设计
项目总体功能:实现
FTP服务器和客户端相互上传和下载文件并实现同步机制。
(1)
FTP服务器端:用户在启动服务器前,需要先点击按钮“选择可供下载的文件”,选择可以供客服端下载的文件后,列表框内会把可以下载的文件显示出来,然后点击按钮“开启服务器”,服务器端就处于监听阶段。服务器状态栏会显示:服务器已经开启。下面的信息栏会即使显示出某个客户端已经和服务器连接、服务器接收到上传来的文件或是某个客户端已经下载某个服务器的文件成功等信息。如果服务器端收到客户端上传的文件会在“客户端上传文件列表”中显示出来。此外,用户还可点击按钮“关闭服务器”关闭服务。点击按钮“帮助”查看相关服务器端使用说明。
(2)
FTP服务器客户端:用户可以在“服务器IP地址栏”中输入用户想要连接的服务器的IP地址,然后点击按钮“连接服务器”,如果连接成功,会弹出提示框“连接成功”,否则用户会一直弹出提示框“连接中。。”,如果连接成功,在 “可下载文件”列表中会列出服务器端允许用户下载的文件名称。在“可下载文件列表”中点击你要下载的文件名,然后点击按钮“下载选中文件”按钮,完成下载,下载成功后,“已下载文件列表”中会显示出已经成功下载的文件名。此外用户可以上传自己的文件到服务器端,只需要点击“选择上传文件”按钮,选择你想上传的文件名。在列表框“选择要上传的文件”中将会出现你选择你的你准备上传的文件,选择一个,点击按钮“上传选择文件”,如果上传文件成功,会得到提示框提示。
架构方案:在VC++6.0编译环境下,建立两个个MFC AppWinzard.exe并选择“对话框”,在MFC对话框环境下进行代码编写,实现
FTP服务器端和客户端的实现。
原理:
1.
FTP服务器端主要是运用方法: StartSock()、CreateSocket()、ConnectProcess(FileName)来完成服务器端的初始化,创建套接字和与客服端连接。
2.FTP客户端主要是运用方法:SartSock()、CreateSocket()、CallServer()、TCPSend()来实现客户端的初始化,建立套接字,呼叫服务器,想服务器发送数据。
系统整体框架图:
见下页
1. 详细设计说明
注:每一个函数功能已经通过注释的形式给出
(1)服务器端
#include "winsock.h"
#include "windows.h"
#include "stdio.h"
#include "ServerNewDlg.h"
#pragma comment(lib,"wsock32.lib")
#define RECV_PORT 2000 //端口号
#define SEND_PORT 3000 //端口号
#define MAX_FILESIZE 32*1024//限定文件最大值
#define MAX_FILE 10
#define MAX_CONNECT 10
SOCKET sock,comsock[10];//服务器和客户端套接字
sockaddr_in ServerAddr;//标
sockaddr_in ClientAddr;//
int threadcount=0;
HANDLE hThread[10];
DWORD ThreadID;
HWND hWnd;
CString ServerInfo;
CRITICAL_SECTION gCriticalSection;
DWORD listenThread(LPVOID lpV);
DWORD ComThreadUp(LPVOID lpVoid);
void ComThread(void* lpVoid);
DWORD Down_up();
struct Filedata
{
char Filename[30];
char ffdata[MAX_FILESIZE];
int len;
}DataPacket;
int Addrlen;
char **File_Name=new char * [10];
DWORD GetFile(char * fname)
{
FILE *fp;
int FileSize;
int i;
// char c;
int count,total=0;
char buffer[100];
char SendData[MAX_FILESIZE];
fp=fopen(fname,"r");
if (fp==NULL)
{
printf("Can not open this file!\n");
return(0);
}
i=0;
FileSize=0;
memset(SendData,0,MAX_FILESIZE);
while (!feof(fp))
{
count=fread(buffer,sizeof(char),100,fp);
if (ferror(fp))
{
printf("Read file error");
break;
}
FileSize+=count;
if (FileSize>MAX_FILESIZE)
{
printf("Your file is too big!\n");
fclose(fp);
return(0);
}
memcpy(&SendData[i],buffer,count);
i+=count;
}
fclose(fp);
SendData[i]='\0';
strcpy(DataPacket.Filename,fname);
memcpy(DataPacket.ffdata,SendData,FileSize);
DataPacket.len=FileSize;
printf("%s %d\n",DataPacket.Filename,DataPacket.len);
return(1);
}
DWORD TCSendPacket(struct Filedata Packet,SOCKET comsock)
{
int length;
length=send(comsock,(char*)&Packet,sizeof(DataPacket),0);
if (length<=0)
{
printf("Send Filedata error !\n");
closesocket(sock);
WSACleanup();
return (-1);
}
return(1);
}
DWORD StartSock()
{
WSADATA WSAData;
if(WSAStartup(MAKEWORD(2,2),&WSAData)!=0)//初始化套接字
{
printf("sock init fail! \n");
return (-1);
}
return (1);
}
DWORD CreateSocket()
{
sock=socket(AF_INET,SOCK_STREAM,0);//创建套接字
if(sock==SOCKET_ERROR)
{
printf("sock creat fail !\n");
WSACleanup();
return (-1);
}
ServerAddr.sin_family=AF_INET;//填充服务器地址
ServerAddr.sin_addr.s_addr=htonl(INADDR_ANY);
ServerAddr.sin_port=htons(RECV_PORT);
if(bind(sock,(struct sockaddr FAR *) &ServerAddr,sizeof(ServerAddr))==SOCKET_ERROR)//绑定套接字
{
printf("bind is the error");
return (-1);
}
return (1);
}
DWORD WriteFile(char *fname,char *fdata,int flen)
{
int i;
FILE *fp;
fp=fopen(fname,"w");//以写方式打开一个文件
if(fp==NULL)
{
printf("cannot open this fiel\n");
}
i=0;
for(i=0;i
GetDlgItem(IDC_EDIT_INFO);
CString strInfo;
pInfo->GetWindowText(strInfo);
strInfo+="客服端下载了文件:";
strInfo+=sendFileName;
strInfo+="\r\n";
pInfo->SetWindowText(strInfo);
}
LeaveCriticalSection(&gCriticalSection);
}
DWORD listenThread(LPVOID lpV)
{
for(threadcount++;1;)
{
//ServerInfo+="一个新的客服端连接到服务器.\n";
//::SendMessage(hWnd,WM_UPDATEVIEW, 0, 0);
comsock[threadcount] =accept(sock,(struct sockaddr FAR *)&ClientAddr, &Addrlen);
CEdit* pInfo=(CEdit*)AfxGetMainWnd()->GetDlgItem(IDC_EDIT_INFO);
CString strInfo;
pInfo->GetWindowText(strInfo);
strInfo+="一个新的客服端连接到服务器.";
strInfo+="\r\n";
pInfo->SetWindowText(strInfo);
for(int i=0;i<10;i++)
{
send(comsock[threadcount],File_Name[i],strlen(File_Name[i]),0);//一个新的客服端连接时,发送文件名到客服端,共10个
}
//为了检测服务器是上传还是下载,建立线程
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Down_up,NULL,0,0);
}
return 1;
}
DWORD ComThreadUp(LPVOID lpVoid)
{
SOCKET *lpSock=(SOCKET*)lpVoid;
for(;;)
{
memset(DataPacket.Filename,0,30);
memset(DataPacket.ffdata,0,MAX_FILESIZE);
if(recv((*lpSock),(char *)&DataPacket,sizeof(DataPacket),0)<=0)//接受数据
{
break;
}
WriteFile(DataPacket.Filename,DataPacket.ffdata,DataPacket.len);//写文件
CEdit* pInfo=(CEdit*)AfxGetMainWnd()->GetDlgItem(IDC_EDIT_INFO);
CString strInfo;
pInfo->GetWindowText(strInfo);
strInfo+="客服端上传一个文件.";
strInfo+=DataPacket.Filename;
strInfo+="\r\n";
pInfo->SetWindowText(strInfo);
//UpList.AddString(DataPacket.Filename);
// CServerNewDlg::m_up=(CString)DataPacket.Filename;
CEdit* pInfoUp=(CEdit*)AfxGetMainWnd()->GetDlgItem(IDC_EDIT_UP);
CString strInfoUp;
pInfoUp->GetWindowText(strInfoUp);
strInfoUp+=DataPacket.Filename;
strInfoUp+="\r\n";
pInfoUp->SetWindowText(strInfoUp);
/*ServerInfo+="客服端上传一个文件.\n";
char* ip=inet_ntoa(ClientAddr.sin_addr);
CString str;
str.Format("IP:%s, Port:%d\r\n",ip,ClientAddr.sin_port);
ServerInfo+=str;
::PostMessage(hWnd, WM_UPDATEVIEW, 0, 0);*/
return 1;
}
return 1;
}
DWORD Down_up()
{
char Kindbuffer[20];
recv(comsock[threadcount],(char*)Kindbuffer,sizeof(Kindbuffer),0);
//建立临界区,防止用时下载同一个文件
InitializeCriticalSection(&gCriticalSection);
if(Kindbuffer[0]=='1')
{
hThread[threadcount]=(void *)CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ComThread,\
(void*)&comsock[threadcount],0,&ThreadID);
}
else if(Kindbuffer[0]=='2')
{
hThread[threadcount]=(void *)CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ComThreadUp,\
(void*)&comsock[threadcount],0,&ThreadID);
}
//等待所有进程结束
WaitForSingleObject(hThread[threadcount],INFINITE);
return 1;
}
(2)服务器端
// P94Client.cpp : Defines the entry point for the console application.
//
//#include "stdafx.h"
#include "winsock.h"
#include "windows.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#pragma comment(lib,"wsock32.lib")
#define RECV_PORT 2000
#define SEND_PORT 3000
#define MAX_FILESIZE 32*1024
//传送数据的结构体
struct FileData
{
char Filename[30];
char ffdata[MAX_FILESIZE];
int len;
}DataPacket;
class client{
private:
sockaddr_in ServerAddr;
CString IP;
CString FileName;
public:
SOCKET sock;
DWORD StartSock();
DWORD CreateSocket();//创建套接字
void CallServer();
void SetFileName(CString FileName);
CString getFileName();
DWORD GetFile(char* fname);
DWORD TCSendPacket(struct FileData Packet);
void SetIp(CString IP);
DWORD WriteFile(char *fname,char *fdata,int flen);
};
void client::SetIp(CString IP){
this->IP=IP;
}
void client::SetFileName(CString FileName){
this->FileName=FileName;
}
CString client::getFileName(){
return this->FileName;
}
DWORD client::StartSock()
{
WSADATA WSAData;
if(WSAStartup(MAKEWORD(2,2),&WSAData)!=0)
{
AfxMessageBox("套接字初始化错误!!!");
return (-1);
}
this->ServerAddr.sin_family=AF_INET;
this->ServerAddr.sin_addr.s_addr=inet_addr(IP);
this->ServerAddr.sin_port=htons(RECV_PORT);
return (1);
}
///////////////////////////////////////
DWORD client::CreateSocket()//创建套接字
{
this->sock=socket(AF_INET,SOCK_STREAM,0);
if(sock==SOCKET_ERROR)
{
AfxMessageBox("创建套接字失败!!!");
WSACleanup(); //关闭网络环境
return (-1);
}
return (1);
}
void client::CallServer()
{
this->CreateSocket();
while(connect(this->sock,(struct sockaddr *) &this->ServerAddr,sizeof(this->ServerAddr))==SOCKET_ERROR)
{
AfxMessageBox("连接中......");
}
AfxMessageBox("连接成功.....");
}
DWORD client::GetFile(char* fname)
{
FILE *fp;
int FileSize1;
int i;
int count,total=0;
char UPbuffer[100];
char SendData[MAX_FILESIZE];
fp=fopen(fname,"r");
if (fp==NULL)
{
AfxMessageBox("Can not open this file!\n");
return(0);
}
i=0;
FileSize1=0;
memset(SendData,0,MAX_FILESIZE);
while (!feof(fp))
{
count=fread(UPbuffer,sizeof(char),100,fp);
if (ferror(fp))
{
AfxMessageBox("Read file error");
break;
}
FileSize1+=count;
if (FileSize1>MAX_FILESIZE)
{
AfxMessageBox("Your file is too big!\n");
fclose(fp);
return(0);
}
memcpy(&SendData[i],UPbuffer,count);
i+=count;
}
fclose(fp);
SendData[i]='\0';
strcpy(DataPacket.Filename,fname);
memcpy(DataPacket.ffdata,SendData,FileSize1);
DataPacket.len=FileSize1;
return(1);
}
DWORD client::TCSendPacket(struct FileData Packet)
{
int length;
length=send(sock,(char *)&Packet,sizeof(DataPacket),0);
if (length<0)
{
AfxMessageBox("Send Filedata error !");
closesocket(sock);
WSACleanup();
return (-1);
}
return(1);
}
DWORD client::WriteFile(char *fname,char *fdata,int flen)
{
int i;
FILE *fp;
fp=fopen(fname,"w");//以写方式打开一个文件
if(fp==NULL)
{
AfxMessageBox("cannot open this fiel\n");
}
for(i=0;i
2019-12-21 20:04:14
45KB
ftp服务器
1