#include "Sockets.h" #include "SocketPort.h" #include "BluePad.h" #include "stdTools.h" #include //--------------------------------------------------------------------------- THSocket::THSocket() { parent = NULL; id = -1; sp = NULL; m_exe_thread_read = true; m_threadid_read = NULL; m_exe_thread_write = true; m_threadid_write = NULL; length_write = 0; memset(data_write, 0, sizeof(data_write)); len_read = 0; memset(data_read, 0, sizeof(data_read)); }; //--------------------------------------------------------------------------- THSocket::~THSocket() { //Останавливаю потоки и дожидаюсь их завершения m_exe_thread_read = false; m_threadid_read->join(); delete m_threadid_read; Sleep(10); m_exe_thread_write = false; Sleep(10); m_threadid_write->join(); delete m_threadid_write; //Закрываю и удаляю сокет sp->Close(); delete sp; sp = NULL; id = -1; } //--------------------------------------------------------------------------- //Для чтения данных из сокетов void THSocket::thread_func_read(void *pData) { THSocket* sock = (THSocket*)pData; char data[65500]; while (sock->m_exe_thread_read) { //Поток намертво не должен тормозиться иначе из него не выйдет (функция Read должна быть с таймаутом) int size = sock->sp->Read(data, sizeof(data)); //Если удалось что либо прочитать то переписываем м массив if (size > 0) { sock->parent->m_mutexList.lock(); for (int i = 0; i < size; i++) { if (sock->len_read + i >= sizeof(sock->data_read)) break; sock->data_read[sock->len_read + i] = data[i]; } sock->len_read += size; sock->parent->m_mutexList.unlock(); std::stringstream ss; ss << "--------------------------------------------------Read from soket = " << size; Utility::logrotate(sock->m_LogFilePath + Utility::sp3() + "log.txt", ss.str()); //TODO закоментить как отлажу } } //TODO закоментить как отлажу if (sock->m_SaveLog) { std::stringstream ss; ss << "========== END SOCK READ THREAD ID = " << sock->id << " =========="; Utility::logrotate(sock->m_LogFilePath + Utility::sp3() + "log.txt", ss.str()); } } //--------------------------------------------------------------------------- //Поток для записи данных в сокет void THSocket::thread_func_write(void *pData) { THSocket* sock = (THSocket*)pData; char data[65535]; int len = 0; while (sock->m_exe_thread_write) { //Переписываю данные для отправки на сервер в локальную переменную sock->parent->m_mutexList.lock(); for (int i = 0; i < sock->length_write; i++) { data[i] = sock->data_write[i]; } len = sock->length_write; sock->parent->m_mutexList.unlock(); if (len > 0) { //Отправляю данные в сокет int size = sock->sp->Write(data, len); //Сдвигаю данные на количество отправленных данных sock->parent->m_mutexList.lock(); for (int i = 0; i < sock->length_write - size; i++) { sock->data_write[i] = sock->data_write[i + size]; } sock->length_write -= size; sock->parent->m_mutexList.unlock(); std::stringstream ss; ss << "--------------------------------------------------Write to soket = " << size << " from = " << len; Utility::logrotate(sock->m_LogFilePath + Utility::sp3() + "log.txt", ss.str()); //TODO закоментить как отлажу } } //TODO закоментить как отлажу if (sock->m_SaveLog) { std::stringstream ss; ss << "========== END SOCK WRITE THREAD ID = " << sock->id << " =========="; Utility::logrotate(sock->m_LogFilePath + Utility::sp3() + "log.txt", ss.str()); } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- Sockets::Sockets(BluePad* bp) { m_bp = bp; m_LogFilePath = m_bp->m_LogFilePath; m_list = new TSimpleList(10, true); //Делаю владельцем чтобы список сам объекты удалял }; //--------------------------------------------------------------------------- Sockets::~Sockets() { delete m_list; }; //--------------------------------------------------------------------------- //создать новый сокет и запустить потоки на чтение и зипись //timeout - таймаут в секундах (только на что?) bool Sockets::openSoket(int id, std::string address, int port, int timeout) { bool result = true; SocketPort* sp = new SocketPort(); sp->Open(address.c_str(), port); if (sp->isOpen()) { //Добавляем созданный объект в массив THSocket* ths = new THSocket(); ths->m_LogFilePath = m_LogFilePath; ths->id = id; ths->sp = sp; ths->parent = this; ths->m_threadid_read = new std::thread(THSocket::thread_func_read, (void*)ths); ths->m_threadid_write = new std::thread(THSocket::thread_func_write, (void*)ths); m_mutexList.lock(); m_list->add(ths); m_mutexList.unlock(); std::stringstream ss; ss << "========== OPEN SOCK THREAD ID = " << id << " =========="; Utility::logrotate(m_LogFilePath + Utility::sp3() + "log.txt", ss.str()); } else { result = false; delete sp; } return result; } //--------------------------------------------------------------------------- //Закрыть удалить сокет и остановить связанные с ним потоки bool Sockets::closeSoket(int id) { TSimpleList* list = new TSimpleList(10,true); m_mutexList.lock(); for (int i = 0; icount(); i++) { if (m_list->get(i)->id == id) { list->add(m_list->get(i)); m_list->rem(i); i--; // break не ставить, могут быть одинаковые id } } m_mutexList.unlock(); delete list; //Не в мютексе а то повиснет из-за join при удалении return true; } //--------------------------------------------------------------------------- // Записать данные для последующей отправки в отдельном потоке bool Sockets::sendData(int id, char* data, int len) { std::lock_guard lock(m_mutexList); for (int i = 0; icount(); i++) { if (m_list->get(i)->id == id) { THSocket* ths = m_list->get(i); //Дописываем данные в конец массива для последующей отправки на сервер for (int i = 0; i < len; i++) { if (ths->length_write + i >= sizeof(ths->data_write)) break; ths->data_write[ths->length_write + i] = data[i]; } ths->length_write += len; break; } } return true; } //--------------------------------------------------------------------------- //Перебираем массив и проверяем есть ли данные для отправки и если есть то создаём объект данных который будет отправлен через последовательный порт в отдельном потоке DataToSend* Sockets::getDataToSend() { std::lock_guard lock(m_mutexList); DataToSend* result = NULL; for (int i = 0; icount(); i++) { if (m_list->get(i)->len_read > 0) { m_list->get(i)->len_read += 1; result = new DataToSend(); //Подготавливаю пакет 01: RECEIVE DATA для отправки полученных даных с сервера на пинпад result->mas[0] = 0x3E; // '>': start paket (ASCII symbol '>') result->mas[1] = 0x40; // EXTERNAL INTERNET COMMANDS result->mas[2] = 0x00; // 00 result->mas[3] = ((char*)&m_list->get(i)->len_read)[1]; //LH length of DATA (старший наиболее значащий байт) result->mas[4] = ((char*)&m_list->get(i)->len_read)[0]; //LL length of DATA result->mas[5] = 0x01; //SUBCMD: 01: RECEIVE DATA for (int j = 0; j < m_list->get(i)->len_read; j++) { result->mas[6+j] = m_list->get(i)->data_read[j]; } result->len = 6 + m_list->get(i)->len_read; result->calcCRC(); result->log_text = "getDataToSend()"; m_list->get(i)->len_read = 0; break; } } return result; } //---------------------------------------------------------------------------