download file with c++

windows 下TCP通信,采用多线程,server和client可以自由的发送和接受消息。同时client可以进行文件的下载,纯c++代码

//client
#include
#include
#include
#include
#include 
#define MAX_BUF 8*1024

using namespace std;
#pragma comment(lib,"ws2_32.lib")

enum MSG_TYPE {
	DOWNLOAD_START,
	DOWNLOAD_SURE,
	DOWNLOAD_END,
	DOWNLOAD,
	DOWNLOAD_STOP,
};

SOCKET sock=-1;
fstream *outfile=nullptr;

bool ConnectServer();
bool SendPacket(long type = DOWNLOAD, string packet = "");
void ReceiveMsgJudge(string buf);
void RecvData();
void Run();
void DownloadStart(string _name,long long speeh=100*1024);//speeh is 100k
void Downloading(string data);
void DownloadEnd();

int main(){
	thread RecvThread(RecvData);
	RecvThread.detach();
	thread SendThread(Run);
	SendThread.join();
	return 0;
}

bool ConnectServer(){
	WORD sockVersion = MAKEWORD(2, 2);
	WSADATA data;
	if (WSAStartup(sockVersion, &data) != 0)return false;
	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sock == INVALID_SOCKET) {
		cout << "Socket error" << endl;
		WSACleanup();
		return false;
	}
	sockaddr_in sock_in;
	sock_in.sin_family = AF_INET;
	sock_in.sin_port = htons(8888);
	sock_in.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	if (connect(sock, (sockaddr*)&sock_in, sizeof(sock_in)) == SOCKET_ERROR) {
		cout << "Connect error" << endl;
		WSACleanup();
		return false;
	}
	std::cout<<"connect succeed :\t"<<std::endl;
	return true;
}

bool SendPacket(long type, string packet) {
	long len = packet.size() + sizeof(type);
	char *sendBuf = new char[len];
	memset(sendBuf, 0, len);
	memcpy(sendBuf, &type, sizeof(long));
	memcpy(sendBuf + sizeof(type), packet.c_str(), packet.size());
	send(sock, sendBuf, len, 0);
	delete[] sendBuf;
	return true;
}

void ReceiveMsgJudge(string buf){
	long _type =0;
	memcpy(&_type, buf.c_str(), sizeof(long));
	string data = buf.substr(sizeof(long), buf.size() - sizeof(long));
	switch (_type) {
		case MSG_TYPE::DOWNLOAD_START: {
			std::cout << "recv download start beg :\t" << data << std::endl;
			outfile=new fstream("./download/"+data, ios::out|ios::binary);
			if (!outfile->good())SendPacket(DOWNLOAD_END, "false");
			else SendPacket(DOWNLOAD_SURE,"start");
			break;
		}
		case MSG_TYPE::DOWNLOAD: {
			Downloading(data);
			break;
		}
		case MSG_TYPE::DOWNLOAD_END: {
			std::cout << "recv download end :\t" << data << std::endl;
			DownloadEnd();
			break;
		}
		case MSG_TYPE::DOWNLOAD_STOP: {
			break;
		}
		case MSG_TYPE::DOWNLOAD_SURE: {
			break;
		}
		default: {
			std::cout << "test data:\t" << data << std::endl;
		}
	}
}

void RecvData(){
	string data;
	char recv_buf[MAX_BUF] = { 0 };
	while(1){
		int len = ::recv(sock, recv_buf, MAX_BUF, 0);
		if (len >0) {
			string data(recv_buf, len);
			ReceiveMsgJudge(data);
		}
		else {
			std::cout<<"socket close,try connect again :\t" <<std::endl;
			closesocket(sock);
			WSACleanup();
			ConnectServer();
		}
	}
}

void Run(){
	string command;
	while (1) {
		cin >> command;
		SendPacket(DOWNLOAD_START, command);
	}
}

void DownloadStart(string _name, long long speeh){
	string data = _name +">>"+ std::to_string(speeh);
	SendPacket(DOWNLOAD_START,data);
}

void Downloading(string data){
	if (outfile == nullptr) {
		SendPacket(DOWNLOAD_END);
		return;
	}
	std::cout<<"recv file  data :\t"<<outfile->tellp() <<std::endl;
	outfile->write(data.c_str(), data.size());
}

void DownloadEnd(){
	if (outfile == nullptr) {
		
	}
	else {
		if (outfile->is_open())outfile->close();
		delete outfile;
		outfile = nullptr;
		
	}
	std::cout<<"download write end\t" <<std::endl;
}

//server
 #include
#include
#include
#include
#include
#include
#define MAX_BUF 8*1024

using namespace std;
#pragma comment(lib,"ws2_32.lib")

enum MSG_TYPE {
	DOWNLOAD_START,
	DOWNLOAD_SURE,
	DOWNLOAD_END,
	DOWNLOAD,
	DOWNLOAD_STOP,
};

fstream* in_file = nullptr;
SOCKET server_socket = -1;
SOCKET client_socket = -1;

string GetFileName(string data) {
	regex pa("\\\\{1,}");
	data=std::regex_replace(data, pa, "/");
	std::cout<<" :\t"<<data <<std::endl;
	data = data.substr(data.find_last_of("/") + 1);
	return data;
}
bool SendPacket(long type = DOWNLOAD, string packet = "");
void DownloadStart(string buf);
void DownloadEnd(string data="");
void Downloading();
void ReceiveMsgJudge(string buf);
void RunServer();
void Run();


int main(int argc, char* argv[]) {
	thread RecvThread(RunServer);
	RecvThread.detach();
	thread SendThread(Run);
	SendThread.join();
	return 0;
}

bool SendPacket(long type, string packet) {
	long len = packet.size() + sizeof(type);
	char *sendBuf = new char[len];
	memset(sendBuf, 0, len);
	memcpy(sendBuf, &type, sizeof(long));
	memcpy(sendBuf + sizeof(type), packet.c_str(), packet.size());
	send(client_socket,sendBuf,len,0);
	delete [] sendBuf;
	return true;
};

void DownloadStart(string buf) {
	if (in_file != nullptr) {
		SendPacket(DOWNLOAD_END, "true");
	}
	else {
		string file_name = buf;
		in_file = new fstream(file_name, ios::in|ios::binary);
		file_name = GetFileName(file_name);
		if (in_file->good()) {
			SendPacket(DOWNLOAD_START, file_name);
		}
		else {
			DownloadEnd("open file fail");
		}
	}

}

void DownloadEnd(string data) {
	if (in_file != nullptr) {
		if (in_file->is_open())in_file->close();
		delete in_file;
		in_file = nullptr;
	}
	std::cout << "download read end ,result is :\t" <<data<< std::endl;
	SendPacket(DOWNLOAD_END,data);

}

void Downloading() {
	if (in_file == nullptr) {
		SendPacket(DOWNLOAD_END);
		return;
	}
	char readBuf[MAX_BUF-sizeof(long)] = { 0 };
	while (!in_file->eof()) {
		memset(readBuf, 0, MAX_BUF - sizeof(long));
		in_file->read(readBuf, MAX_BUF - sizeof(long));
		string data(readBuf, in_file->gcount());
		SendPacket(DOWNLOAD, data);
		Sleep(500);
		//std::cout<<"send len :\t"<tellg() <

	}
	DownloadEnd("Server send all");
	SendPacket(DOWNLOAD_END);

}

void ReceiveMsgJudge(string buf) {
	long _type = 0;
	memcpy(&_type, buf.c_str(), sizeof(long));
	string data = buf.substr(sizeof(long), buf.size() - sizeof(long));
	switch (_type) {
		case MSG_TYPE::DOWNLOAD_START: {
			std::cout<<"recv download start :\t"<<data <<std::endl;
			DownloadStart(data);
			break;
		}
		case MSG_TYPE::DOWNLOAD: {
			break;
		}
		case MSG_TYPE::DOWNLOAD_END: {
			DownloadEnd("recv client download end");
			break;
		}
		case MSG_TYPE::DOWNLOAD_STOP: {
			break;
		}
		case MSG_TYPE::DOWNLOAD_SURE: {
			Downloading();
			break;
		}
		default: {
			std::cout << "test data:\t" << data << std::endl;
		}
	}
}

void RunServer() {
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);
	server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	sockaddr_in sockAddr;
	sockAddr.sin_family = AF_INET;
	sockAddr.sin_port = htons(8888);
	sockAddr.sin_addr.S_un.S_addr = INADDR_ANY;

	//bind
	if (::bind(server_socket, (sockaddr*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR) {
		cout << "Bind error" << endl;
		printf("error=%d\n", WSAGetLastError());
		WSACleanup();
		return ;
	}

	//listen number max is 1
	if (listen(server_socket, 1) == SOCKET_ERROR) {
		cout << "Listen error" << endl;
		WSACleanup();

		return ;
	}
	//accept client
	sockaddr_in client_sin;
	int len = sizeof(client_sin);
	client_socket = accept(server_socket, (sockaddr*)&client_sin, &len);
	if (client_socket == INVALID_SOCKET) {
		WSACleanup();
		return;
	}
	else {
		//std::cout<<"start recv :\t"<
		//start recv
		char recvBuf[MAX_BUF] = { 0 };
		while (1) {
			int num = recv(client_socket, recvBuf, MAX_BUF, 0);
			if (num > 0) {
				string data(recvBuf, num);
				ReceiveMsgJudge(data);
			}
			else {
				cout << "Client leave" << endl;
				closesocket(client_socket);
				client_socket = accept(server_socket, (sockaddr*)&client_sin, &len);
				std::cout<<"have client accept :\t" <<std::endl;
			}
		}

	}


}

void Run(){
	string command;
	while (1) {
		cin >> command;
		SendPacket(9, command);
	}
}


你可能感兴趣的:(c++学习)