C++语言利用socket的客户端和服务器之间传输文件
小标 2018-07-20 来源 : 阅读 4182 评论 0

摘要:本文主要向大家介绍了C++语言利用socket的客户端和服务器之间传输文件,通过具体的内容向大家展示,希望对大家学习C++语言有所帮助。

本文主要向大家介绍了C++语言利用socket的客户端和服务器之间传输文件,通过具体的内容向大家展示,希望对大家学习C++语言有所帮助。

//服务器的代码文件有 

/*

message.h

source.h

source.cpp

server.h

server.cpp

*/ 

//客户端的代码文件有 

/*

message.h   和服务器端一样

client.h

client.cpp

*/ 

//message.h 

#pragma once 

#include<iostream> 

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<iostream> 

#include<fstream> 

#include<vector> 

#include<io.h> 

#include<string> 

using namespace std; 

class Source 

public: 

    vector<string> catalogInfo; 

    void GetFiles(string path,string ext,vector<string> &files);//获取文件 

}; 

//server.h 

#pragma once 

#include<iostream> 

#include<winsock2.h> 

#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<iostream> 

#include<vector> 

#include<io.h> 

#include<string> 

#include"source.h" 

using namespace std; 

void Source::GetFiles(string path,string ext,vector<string> &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<iostream> 

#include<string> 

#include<fstream> 

#include<winsock2.h> 

#include"message.h" 

#include"server.h" 

#include"source.h" 

using namespace std; 

int main() 

    Server server; 

    if(!server.InitSock())   //初始化失败 

    { 

        cout<<"初始化失败"<<endl; ----------------------------------------------="" -------------------------------------------------------------="" _int64="" bool="" char="" const="" file="" i="0;" int="" message::msghead="" msghead="(Message::MsgHead" msghead-="" nrecv="=SOCKET_ERROR)" nrecvbuf="1024000;//设置为1000K" nsendbuf="1024000;//设置为1000K" nsize="sizeof(sockaddr_in);" pfile="fopen(fileName,"a+b");" return="" sd="=INVALID_SOCKET)" sdlisten="=INVALID_SOCKET)" server.sd="=INVALID_SOCKET)" slisten.sin_addr.s_addr="htonl(INADDR_ANY);" slisten.sin_family="AF_INET;" slisten.sin_port="htons(PORT);" sockaddr_in="" socket="" void="" winsocket="" word="" wr="MAKEWORD(2,2);" wsadata="">msgId) 

    { 

    case MSG_SEND_FILE:         //客户端向服务器发送文件 

        cout<<"客户端请求向服务器发送文件"<<endl; case="" char="" i="0;i<nSize;i++)" int="" message::msgcomplete="" message::msgfilename="" msg_download_file:="" msg_file_name:="" msgfilename="(Message::MsgFileName*)msgHead;" msgfilename-="" nsize="source.catalogInfo.size();" return="" sext=".jpg" source="" spath="E:\\图片" string="">fileName); 

            cout<<"收到发送来的文件名"<<filename<<endl; case="" filelength="msgFileLength-" message::msgfilelength="" msg_file_length:="" msgfilelength="(Message::MsgFileLength">fileLength; 

            cout<<"接收到文件的长度为"<<filelength<<endl; bool="" case="" char="" default:="" message::msgfilename="" msg_file:="" msgfilename="(Message::MsgFileName" msgfilename-="" return="" socket="">fileName); 

    cout<<"接收的文件名为"<<filename<<endl; _int64="" bool="" char="" file="" filelength="_ftelli64(pFile);" i="0;" int="" max_pack_size="" message::msgfilelength="" message::msgfilename="" msgfilelength.filelength="fileLength;" pfile="=NULL)" return="" socket="">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<<"发送失败"<<wsagetlasterror()<<endl; client.h="" iostream="" once="" pragma="" return=""> 

#include<fstream> 

#include<vector> 

#include<winsock2.h> 

#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<iostream> 

#include<vector> 

#include<winsock2.h> 

#include"client.h" 

#include"message.h" 

using namespace std; 

int main() 

    Client client; 

    if(!client.InitSock()) 

    { 

        cout<<"初始socket失败"<<endl; bool="" char="" else="" ent="=NULL)" ent-="" hostent="" naddr="=INADDR_NONE)" return="" saremote="=INVALID_SOCKET)" socket="" u_long="" word="" wr="MAKEWORD(2,2);" wsadata="">h_addr_list[0]); 

        } 

    } 

    if(nAddr==INADDR_NONE) 

    { 

        cout<<"解析主机地址失败"<<endl; -------------------------------------------------="" ---------------------------------------------------------="" bool="" const="" int="" loop:cin="" nrecvbuf="1024000;//设置为1000K" nsendbuf="1024000;//设置为1000K" return="" saserver.sin_addr.s_un.s_addr="serverIp;" saserver.sin_family="AF_INET;" saserver.sin_port="htons(port);" sd="=INVALID_SOCKET)" sockaddr_in="" socket="" u_long="">>n; 

        switch(n) 

        { 

        case 1: 

            { 

                //向服务器发送传送文件消息 

                Message::MsgSendFile msgSendFile; 

                if(send(sd,(char *)&msgSendFile,sizeof(Message::MsgSendFile),0)==SOCKET_ERROR) 

                { 

                    cout<<"发送消息失败"<<endl; a="" char="" cin="" f:="" return="">>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<<"发送文件名出错"<<wsagetlasterror()<<endl; 2:="" 3:="" _int64="" bool="" case="" char="" default:="" file="" goto="" i="0;" int="" max_pack_size="" message::msgdownloadfile="" message::msgfile="" message::msgfilelength="" msgfilelength.filelength="nFileLength;" nfilelength="_ftelli64(pFile);" pfile="fopen(filePath,"r+b");" return="" socket="">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<<"发送失败"<<endl; bool="" char="" flag="1;" int="" message::msghead="" msghead="(Message::MsgHead" msghead-="" return="" socket="">msgId==MSG_COMPLETE)      //判断消息是否是标准消息 

        { 

            cout<<"目录信息发送完成"<<endl; bool="" char="" cin="" else="" flag="=0)" return="" socket="">>fileName; 

    Message::MsgFileName msgFileName; 

    strcpy(msgFileName.fileName,fileName); 

    if(send(sd,(char *)&msgFileName,MAX_PACK_SIZE,0)==SOCKET_ERROR) 

    { 

        cout<<"发送下载文件名出错"<<wsagetlasterror()<<endl; bool="" char="" message::msgfilelength="" msgfilelength="(Message::MsgFileLength" nfilelength="msgFileLength-" return="" socket="">fileLength; 

    cout<<"接收到文件长度"<<nfilelength<<endl; bool="" char="" message::msgfilename="" msgfilename="(Message::MsgFileName" msgfilename-="" return="" socket="">fileName); 

    cout<<"接收到文件名"<<filename<<endl; _int64="" bool="" char="" file="" i="0;" int="" nrecv="=SOCKET_ERROR)" pfile="fopen(fileName,"a+b");" pre="" return="" socket="" void="">

</filename<<endl;></nfilelength<<endl;></wsagetlasterror()<<endl;></endl;></endl;></wsagetlasterror()<<endl;></endl;></endl;></endl;></winsock2.h></vector></iostream></winsock2.h></vector></fstream></wsagetlasterror()<<endl;></filename<<endl;></filelength<<endl;></filename<<endl;></endl;></endl;></winsock2.h></fstream></string></iostream></string></string></io.h></vector></iostream></winsock2.h></iostream></string></string></string></io.h></vector></fstream></iostream></iostream>

本文由职坐标整理并发布,了解更多内容,请关注职坐标编程语言C/C+频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 4
看完这篇文章有何感觉?已经有4人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程