欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C++利用socket的客户端和服务器之间传输文件

程序员文章站 2022-04-12 21:14:18
//服务器的代码文件有 /* message.h source.h source.cpp server.h server.cpp */ //...
//服务器的代码文件有  
/* 
message.h 
source.h 
source.cpp 
server.h 
server.cpp 
*/  
//客户端的代码文件有  
/* 
message.h   和服务器端一样 
client.h 
client.cpp 
*/  
//message.h  
#pragma once  
#include  
using namespace std;  
#define MAX_PACK_SIZE  10240   //数据包的长度  
#define MAX_FILE_NAME_LENGTH 256  //文件名的长度  
#define INVALID_MSG -1       //无效的消息  
#define MSG_FILE_LENGTH 1    //文件长度  
#define MSG_FILE_NAME 2    //文件名  
#define MSG_FILE   4     //文件内容  
#define MSG_READY   3     //准备好消息  
#define MSG_SEND_FILE 5  //发送文件  
#define MSG_DOWNLOAD_FILE 6  //下载文件  
#define MSG_COMPLETE 7     //完成信息  
class Message  
{  
public:  
    struct MsgHead     //头消息  
    {  
        int msgId;    //消息标识  
        MsgHead(int msg=INVALID_MSG):msgId(msg){};  
    };  
    struct MsgFileLength :public MsgHead  
    {  
        _int64 fileLength;   //文件长度  
        MsgFileLength():MsgHead(MSG_FILE_LENGTH){}  
    };  
    struct MsgFileName:public MsgHead  
    {  
        char fileName[MAX_FILE_NAME_LENGTH];  
        MsgFileName():MsgHead(MSG_FILE_NAME){}  
    };  
    struct MsgFile:public MsgHead  
    {  
        MsgFile():MsgHead(MSG_FILE){}  
    };  
    struct MsgReady:public MsgHead        //准备好消息  
    {  
        MsgReady():MsgHead(MSG_READY){}  
    };  
    struct MsgSendFile:public MsgHead  //发送文件消息  
    {  
        MsgSendFile():MsgHead(MSG_SEND_FILE){}  
    };  
    struct MsgDownLoadFile:public MsgHead     //下载文件消息  
    {  
        MsgDownLoadFile():MsgHead(MSG_DOWNLOAD_FILE){}  
    };  
    struct MsgComplete:public MsgHead  
    {  
        MsgComplete():MsgHead(MSG_COMPLETE){}  
    };  
};  
//source.h   获取指定文件加下的符合要求的文件  
#pragma once  
#include  
#include  
#include  
#include  
#include  
using namespace std;  
class Source  
{  
public:  
    vector catalogInfo;  
    void GetFiles(string path,string ext,vector &files);//获取文件  
};  
//server.h  
#pragma once  
#include  
#include  
#include"message.h"  
#pragma comment(lib,"Ws2_32.lib")  
#define PORT 10000  
using namespace std;  
class Server  
{  
public:  
    SOCKET sd;  
    _int64 fileLength;  
    char fileName[MAX_FILE_NAME_LENGTH];  
    bool InitSock();    //初始winsocket  
    SOCKET BindListen();  //绑定监听套接字  
    SOCKET AcceptConnection(SOCKET sd);  //接收客户端  
    bool ProcessConnection(SOCKET sd);  //传送数据  
    bool ReceiveFile(SOCKET sd);     //接收文件内容  
    bool RecvFileName(SOCKET sd);     //接收文件名  
    bool GetAndSendFileLength(SOCKET sd);    //获取文件长度  
    bool SendFileName(SOCKET sd);    //发送文件名  
    bool SendFile(SOCKET sd);      //发送文件  
    void CloseSocket();   //关闭套接字  
};  
//source.cpp  
#pragma once  
#include  
#include  
#include  
#include  
#include"source.h"  
using namespace std;  
void Source::GetFiles(string path,string ext,vector &files)  
{  
    long hFile=0;    //文件句柄  
    _finddata_t fileInfo; //文件信息  
    string pathName;  
    if((hFile=_findfirst(pathName.assign(path).append("\\*").c_str(),&fileInfo))!=-1) //判断路径是否有效并获取第一个文件  
    {  
        do  
        {  
            if(fileInfo.attrib & _A_SUBDIR)   //如果是子文件夹  
            {  
                if(strcmp(fileInfo.name,".")!=0 && strcmp(fileInfo.name,"..")!=0)  
                {  
                    GetFiles(pathName.assign(path).append("\\").append(fileInfo.name),ext,files);  
                }  
            }  
            else  
            {  
                string filePath;  
                filePath=pathName.assign(path).append("\\").append(fileInfo.name);  
                char fileDrive[_MAX_DRIVE];  
                char fileDir[_MAX_DIR];  
                char fileName[_MAX_FNAME];  
                char fileExt[_MAX_EXT];  
                _splitpath(filePath.c_str(),fileDrive,fileDir,fileName,fileExt);  //分解路径获取磁盘区路径文件名后缀  
                                if(strcmp(fileExt,ext.c_str())==0)  
                {  
                    files.push_back(filePath);  
                }  
            }  
        }while(_findnext(hFile,&fileInfo)==0);  
        _findclose(hFile);  
    }  
}  
//server.cpp  
#pragma once  
#include  
#include  
#include  
#include  
#include"message.h"  
#include"server.h"  
#include"source.h"  
using namespace std;  
int main()  
{  
    Server server;  
    if(!server.InitSock())   //初始化失败  
    {  
        cout<<"初始化失败"<msgId)  
    {  
    case MSG_SEND_FILE:         //客户端向服务器发送文件  
        cout<<"客户端请求向服务器发送文件"<fileName);  
            cout<<"收到发送来的文件名"<fileLength;  
            cout<<"接收到文件的长度为"<fileName);  
    cout<<"接收的文件名为"<fileLength)  
        {  
            nSize=(int)(fileLength-i);  
        }  
        else  
        {  
            nSize=MAX_PACK_SIZE-1;  
        }  
        fread(buff,sizeof(char),nSize,pFile);  
        int nSend;  
        nSend=send(sd,buff,nSize,0);  
        if(nSend==SOCKET_ERROR)  
        {  
            cout<<"发送失败"<  
#include  
#include  
#include  
#pragma comment(lib,"Ws2_32.lib")  
using namespace std;  
#define SERVER_IP "127.0.0.1"  
#define PORT  10000  
class Client  
{  
public:  
    _int64 nFileLength;  
    char fileName[_MAX_FNAME+_MAX_EXT];  
    SOCKET sd;  
    bool InitSock();   //初始化winsock  
    u_long ResolveAdress(char *serverIp);    //解析服务器地址  
    SOCKET ConnectServer(u_long serverIp,int port);//连接服务器  
    bool ProcessConnection(SOCKET sd);    //客户端服务器交互  
    void CloseSocket();         //释放套接字  
    bool SendFileLength(SOCKET sd,char *filePath);  //发送文件长度  
    bool SendFile(SOCKET sd,char *filePath);    //发送文件  
    bool RecvCatalogInfo(SOCKET sd);     //接收目录信息  
    bool SendDownLoadFileName(SOCKET sd);  //发送要下载的文件名  
    bool ReceiveFileLength(SOCKET sd);    //接收文件长度  
    bool ReceiveFileName(SOCKET sd);   //接收文件名  
    bool ReceiveFile(SOCKET sd);      //接收文件  
    //void DoWork();       //主体函数  
};  
//client.cpp  
#define _CRT_SECURE_NO_WARNINGS  
#pragma once  
#include  
#include  
#include  
#include"client.h"  
#include"message.h"  
using namespace std;  
int main()  
{  
    Client client;  
    if(!client.InitSock())  
    {  
        cout<<"初始socket失败"<h_addr_list[0]);  
        }  
    }  
    if(nAddr==INADDR_NONE)  
    {  
        cout<<"解析主机地址失败"<>n;  
        switch(n)  
        {  
        case 1:  
            {  
                //向服务器发送传送文件消息  
                Message::MsgSendFile msgSendFile;  
                if(send(sd,(char *)&msgSendFile,sizeof(Message::MsgSendFile),0)==SOCKET_ERROR)  
                {  
                    cout<<"发送消息失败"<>filePath;  
                char fileDrive[_MAX_DRIVE];  
                char fileDir[_MAX_DIR];  
                char fileName[_MAX_FNAME];  
                char fileExt[_MAX_EXT];  
                _splitpath(filePath,fileDrive,fileDir,fileName,fileExt);  //将文件路径解析  
                Message::MsgFileName msgFileName;  
                strcat(fileName,fileExt);  
                strcpy(msgFileName.fileName,fileName);  
                if(send(sd,(char *)&msgFileName,sizeof(Message::MsgFileName),0)==SOCKET_ERROR)  //发送文件名  
                {  
                    cout<<"发送文件名出错"<nFileLength)  
        {  
            nSize=(int)(nFileLength-i);  
        }  
        else  
        {  
            nSize=MAX_PACK_SIZE-1;  
        }  
        fread(buff,sizeof(char),nSize,pFile);  
        int nSend;  
        nSend=send(sd,buff,nSize,0);  
        if(nSend==SOCKET_ERROR)  
        {  
            cout<<"发送失败"<msgId==MSG_COMPLETE)      //判断消息是否是标准消息  
        {  
            cout<<"目录信息发送完成"<>fileName;  
    Message::MsgFileName msgFileName;  
    strcpy(msgFileName.fileName,fileName);  
    if(send(sd,(char *)&msgFileName,MAX_PACK_SIZE,0)==SOCKET_ERROR)  
    {  
        cout<<"发送下载文件名出错"<fileLength;  
    cout<<"接收到文件长度"<fileName);  
    cout<<"接收到文件名"<