这一篇给之前写的聊天室再加上文件传输:
以下是对文件操作的封装
FileOperator.h
#ifndef FILEOPERATOR_H #define FILEOPERATOR_H #include <stdio.h> #define WRITE_CREATE_MODE "a+b" #include <fcntl.h> #include <string> class FileOperator { public: FileOperator(); ~FileOperator(); bool Open(const char* fileName,const char* option); int WriteToFile(const std::string& buffer); int ReadFromFile(std::string& buffer); void Close(); private: FILE* filePtr; }; #endif
FileOperator.cpp
#include "FileOperator.h" #include <sys/sendfile.h> #include <memory.h> const int MAX_BUFFERLENGTH=512; FileOperator::FileOperator() :filePtr(NULL) {} FileOperator::~FileOperator() { Close(); } bool FileOperator::Open(const char* fileName,const char* option) { filePtr=fopen(fileName,option); return filePtr!=NULL; } int FileOperator::WriteToFile(const std::string& buffer) { int writeBytes=::fwrite(buffer.c_str(),sizeof(char),buffer.size(),filePtr); if(writeBytes<0) { perror("error from fwrite"); return -1; } else if(writeBytes==0) return 0; else return writeBytes; } int FileOperator::ReadFromFile(std::string& buffer) { char bufferArray[MAX_BUFFERLENGTH+1]; buffer.clear(); memset(bufferArray,0,MAX_BUFFERLENGTH+1); int numberRead=fread(bufferArray,sizeof(char),MAX_BUFFERLENGTH+1,filePtr); if(numberRead==-1) { perror("error in Socket::Receive"); return -1; } else if(numberRead==0) return 0; else { buffer=bufferArray; return numberRead; } } void FileOperator::Close() { if(filePtr!=NULL) fclose(filePtr); }
那怎么发送文件呢
void ClientSocket::SendFile(const std::string& fileName) { FileOperator fileOperator; fileOperator.Open(fileName.c_str(),"rb"); std::string buffer; int readBytes; Send("File"); while((readBytes = fileOperator.ReadFromFile(buffer))>0) { if(Send(buffer)<0) { perror("failed to send file"); break; } } }
接收文件
void ServerSocket::RecvFile(Socket* clientSocket) { std::string message; FileOperator fileOperator; //using IP address to name received file
fileOperator.Open(clientSocket->GetAddress().c_str(),WRITE_CREATE_MODE); int recvBytes; int writeBytes; while((recvBytes=Socket::Receive(*clientSocket,message))>0) { std::cout<<"message length: "<<message.size()<<"\n"; writeBytes=fileOperator.WriteToFile(message); std::cout<<"writeBytes: "<<writeBytes<<"\n"; if(writeBytes<recvBytes) { perror("write to file failed"); Socket::Send(*clientSocket,"Error when server receiving file."); return; } //if all bytes has been wrote if(recvBytes==0 || recvBytes!=MAXRECEIVE) break; } if(recvBytes >=0 ) Socket::Send(*clientSocket,"server has received your file.");
}
要注意的是发送文件时,如果文件较大,客户端很可能会阻塞,这个时候可以开一个新线程来发送文件。
不过,这个只是很简单的文件传输,复杂点的有空再慢慢研究。