Добавил:
farel
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:
#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;
}