Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

lab2 / client / main

.cpp
Скачиваний:
10
Добавлен:
01.02.2019
Размер:
7.64 Кб
Скачать
#include "includes.h"
#include "message.h"

#pragma warning (disable: 4996)

#define BUFFER_SIZE				512000

const char						*divider = "#ln";

SOCKET							clientSocket;

int								SendClientMessage(SOCKET *, message);
message							handleMessage(std::string);
int								onClientCommandText(message *);
int								typeMessage(std::string);
void							recvf();
void							sendf();

BOOL WINAPI						CtrlHandler(DWORD);

int main() {
	SetConsoleCP(1251);
	SetConsoleOutputCP(1251);
	WSADATA						ws;
	WORD						wVersionRequested;
	int							res;
	u_short						port;
	std::string					ip_address;

	std::cout << "Enter IP: ";
	std::getline(std::cin, ip_address);
	std::cout << "Enter PORT: ";
	std::cin >> port;
	std::cin.ignore(100, '\n');
	wVersionRequested = MAKEWORD(2, 2);
	res = WSAStartup(wVersionRequested, &ws);
	if (res) {
		std::cout << "WSAStartup was failed." << std::endl;
		std::cout << "Error: " << WSAGetLastError() << std::endl;
		WSACleanup();
		_getch();
		return -1;
	}
	clientSocket = socket(AF_INET, SOCK_STREAM, NULL);
	if (clientSocket == INVALID_SOCKET) {
		std::cout << "Failed to create client socket" << std::endl;
		std::cout << "Error: " << WSAGetLastError() << std::endl;
		WSACleanup();
		_getch();
		return -1;
	}
	SOCKADDR_IN saddr_in;
	saddr_in.sin_family = AF_INET;
	saddr_in.sin_port = htons(port);
	saddr_in.sin_addr.S_un.S_addr = inet_addr(ip_address.c_str());
	if (connect(clientSocket, (const SOCKADDR *)&saddr_in, sizeof(saddr_in)))
	{
		printf("Ошибка при подключении %d\n", WSAGetLastError());
		closesocket(clientSocket);
		WSACleanup();
		_getch();
		return -1;
	}
	printf("Соединение с %s (%d) успешно установлено\n", ip_address.c_str(), saddr_in.sin_addr.S_un.S_addr);
	SetConsoleCtrlHandler(CtrlHandler, TRUE);
	std::thread threadRecv(&recvf);
	std::thread threadSend(&sendf);
	threadSend.join();
	threadRecv.join();
	closesocket(clientSocket);
	WSACleanup();
	return 0;
}

void recvf() {
	char buffer[BUFFER_SIZE];
	int recvBytes;
	message recvMessage;
	while (1) {
		recvBytes = recv(clientSocket, buffer, BUFFER_SIZE, 0);
		if (recvBytes == SOCKET_ERROR) {
			std::cout << "Ошибка при получении сообщения (Error: " << WSAGetLastError() << ")" << std::endl;
			break;
		}
		buffer[recvBytes] = '\0';
		recvMessage = handleMessage(std::string(buffer));
		if (recvMessage.info.find("exit") != std::string::npos) break;
		if (recvMessage.type == FILE) {
			char *fileName = new char[recvMessage.text.length()];
			recvMessage.text.copy(fileName, recvMessage.text.length());
			fileName[recvMessage.text.length()] = '\0';
			std::ofstream f(fileName, std::ofstream::binary | std::ofstream::out);
			recvBytes = recv(clientSocket, buffer, BUFFER_SIZE, 0);
			buffer[recvBytes] = '\0';
			std::string text;
			for (int i = 0; i < recvBytes; i++) {
				text.push_back(buffer[i]);
			}
			recvMessage = handleMessage(text);
			f.write(recvMessage.text.c_str(), recvMessage.text.length());
			f.close();
			std::cout << "Получен файл " << fileName << std::endl;
			continue;
		}
		std::cout << "\r" << recvMessage << std::endl;
	}
}

void sendf() {
	message mess;
	int res;
	while (1) {
		std::getline(std::cin, mess.text);
		res = onClientCommandText(&mess);
		if (res) {
			if (mess.type == FILE) {
				std::ifstream f(mess.text, std::ifstream::binary | std::ifstream::in);
				if (!f.is_open()) {
					std::cout << "Не удается открыть файл." << std::endl;
					continue;
				}
				f.seekg(0, std::ios::end);
				int length = f.tellg();
				f.seekg(0, std::ios::beg);
				if (length > BUFFER_SIZE - 1000) {
					std::cout << "Максимальный размер файла 512 КБ." << std::endl;
					continue;
				}
				if (res = SendClientMessage(&clientSocket, mess) == SOCKET_ERROR) break;
				char ch;
				mess.text.clear();
				while (true) {
					ch = f.get();
					if (f.eof()) break;
					mess.text.push_back(ch);
				}
				f.close();
				res = SendClientMessage(&clientSocket, mess);
				std::cout << "Файл отправлен." << std::endl;
				continue;
			}
			if (SendClientMessage(&clientSocket, mess) == SOCKET_ERROR) break;
			if (mess.info == "exit") break;
		}
		else std::cout << "Введена запрещенная последовательность символов #ln." << std::endl;
	}
}

int SendClientMessage(SOCKET *__client, message __mess) {
	std::string s;
	s = std::to_string(__mess.type) + divider + __mess.name + divider +
		__mess.info + divider + __mess.text + divider;
	int sendBytes;
	if ((sendBytes = send(*__client, s.c_str(), s.size(), NULL)) == SOCKET_ERROR) {
		std::cout << "Ошибка при отправке сообщения (" << WSAGetLastError() << ")" << std::endl;
		return SOCKET_ERROR;
	}
	return sendBytes;
}

message handleMessage(std::string __message) {
	int				dividerLength;
	message			newMessage;
	size_t			iter;
	size_t			last;
	dividerLength = strlen(divider);
	// Type message
	iter = 0;
	last = __message.find(divider);
	newMessage.type = std::stoi(__message.substr(0, last));
	// Name
	iter = last + dividerLength;
	last = __message.find(divider, iter);
	newMessage.name = __message.substr(iter, last - iter);
	// Info
	iter = last + dividerLength;
	last = __message.find(divider, iter);
	newMessage.info = __message.substr(iter, last - iter);
	// Text
	iter = last + dividerLength;
	last = __message.rfind(divider, iter);
	newMessage.text = __message.substr(iter, last - iter);
	last = newMessage.text.rfind(divider);
	while (true) {
		iter = newMessage.text.find(divider);
		if (iter == std::string::npos) break;
		else if (iter == last) {
			newMessage.text.replace(iter, dividerLength, "");
			break;
		}
		else newMessage.text.replace(iter, dividerLength, "  \n");
	}
	return newMessage;
}

int onClientCommandText(message *__mess) {
	size_t t, pos;
	t = __mess->text.find(divider);
	if (t != std::string::npos)
		return 0;
	for (int i = 0; i < __mess->text.length(); i++) {
		if (!isspace(__mess->text.at(i)) && !i) break;
		else if (isspace(__mess->text.at(i))) continue;
		else if (isspace(__mess->text.at(i - 1)) && isalpha(__mess->text.at(i)))
			__mess->text.erase(0, i);
	}
	t = __mess->text.find(' ');
	if (t == std::string::npos) {
		__mess->info = __mess->text.substr(0);
		__mess->type = typeMessage(__mess->info);
		return 1;
	}
	else {
		__mess->info = __mess->text.substr(0, t);
		__mess->type = typeMessage(__mess->info);
		pos = t+1;
		t = __mess->text.find(' ', pos);
		if (t == std::string::npos) {
			__mess->name = __mess->text.substr(pos);
			__mess->text.clear();
			if (__mess->info == "messAll")
				__mess->text.swap(__mess->name);
		}
		else {
			__mess->name = __mess->text.substr(pos, t - pos);
			__mess->text = __mess->text.substr(t+1);
			if (__mess->info == "messAll")
				__mess->text = __mess->name + " " + __mess->text;
		}
		return 1;
	}
}

int typeMessage(std::string __command) {
	if (__command == "messPr" || __command == "messAll")
		return MESS;
	else if (__command == "file") return FILE;
	else return INF;
}

BOOL WINAPI CtrlHandler(DWORD fwdCtrlType) {
	if (fwdCtrlType == CTRL_CLOSE_EVENT) {
		message disconnectMessage;
		disconnectMessage.type = INF;
		disconnectMessage.info = "exit";
		SendClientMessage(&clientSocket, disconnectMessage);
		closesocket(clientSocket);
		WSACleanup();
	}
	return 0;
}
Соседние файлы в папке client