У меня сейчас есть клиентское приложение, которое работает, но оно однопоточное.
мои пакеты выглядят так: | "
"|" используется в качестве разделителя для моих данных.
всегда сопровождается 4 цифрами.
<данные> выглядит следующим образом: | <идентификатор транзакции> | <команда> | | | <контрольная сумма> |
мой код для создания пакетов:
_snprintf_s(data_buffer, WS_MAX_DATA_PACKET_SIZE,
WS_MAX_DATA_PACKET_SIZE - 1,
"%s%d%s%d%s%d%s%s%s%d%s",
WS_PACKET_SEP, pkt->transaction_id,
WS_PACKET_SEP, pkt->command,
WS_PACKET_SEP, pkt->bufsize,
WS_PACKET_SEP, pkt->buf,
WS_PACKET_SEP, pkt->checksum, WS_PACKET_SEP);
buf_len = strlen(data_buffer);
_snprintf_s(send_buffer, WS_MAX_DATA_PACKET_SIZE,
WS_MAX_DATA_PACKET_SIZE - 1, "%04d%s%s",
buf_len, WS_PACKET_SEP, data_buffer);
buf_len = strlen(send_buffer);
// Send buffer
bytes_sent = send(ConnectSocket, send_buffer, buf_len, 0);
Клиентский поток отправляет команду серверу, а затем вызывает функцию GetIncomingPackets (). В GetIncomingPackets () я вызываю recv () для получения 5 байтов, это должно быть длина остальной части пакета, я анализирую эти 5 байтов и проверяю, соответствуют ли они моему ожидаемому формату. Затем я конвертирую первые 4 байта в целое число x. Затем я снова вызываю recv (), чтобы получить больше x байтов, а затем анализирую их в моей структуре пакета.
Проблема возникает, когда я добавляю другой поток, чтобы сделать то же самое (отправлять и получать команды).
Я запускаю свое приложение, запускаю 2 потока и отправляю их для отправки разных команд и жду ответов. Когда потоки вызывают GetIncomingPackets (), возвращаемые данные являются недействительными. Первые 5 байтов, которые я ожидаю, иногда отсутствуют, и я просто получаю следующие 5 байтов, поэтому я не могу получить свой пакет .
Я даже добавил блок критической секции между 2 вызовами recv () в моем GetIncomingPackets (), чтобы протекторы не прерывали друг друга при получении полного пакета.
Без дополнительного кода для проверки ошибок, вот так выглядит функция
#define WS_SIZE_OF_LEN_PACKET 5
bool GetIncomingPackets(SOCKET sd, dev_sim_packet_t *pkt )
{
char len_str_buf[WS_SIZE_OF_LEN_PACKET + 1] = {0}; // + 1 for NULL char
char data_buf[WS_MAX_DATA_PACKET_SIZE + 1] = {0};
int ret = 0;
int data_len = 0;
EnterCriticalSection( &recv_critical_section );
nReadBytes = WS_RecvAll(sd, len_str_buf, WS_SIZE_OF_LEN_PACKET );
ret = WS_VerifyLenPacket(len_str_buf);
// Convert data packet lenght string received to int
data_len = WS_ConvertNumberFromString(len_str_buf, WS_SIZE_OF_LEN_PACKET );
// Get data from packet
nReadBytes = WS_RecvAll(sd, data_buf, data_len);
LeaveCriticalSection( &recv_critical_section );
ret = ParseMessager(data_buf, data_len, pkt);
}
Мой вопрос: что может быть причиной этой проблемы и как я могу ее исправить? Или есть лучшие способы сделать то, что я пытаюсь сделать. Причина, по которой я пытаюсь сделать его многопоточным, заключается в том, что мое приложение будет взаимодействовать с 2 другими источниками, и я хочу иметь поток для обработки каждого запроса, поступающего из любого источника.
спасибо заранее и не стесняйтесь задавать любые вопросы, если я не объяснил что-то хорошо.
Вот код для WS_RecvAll (). Буфер является статическим буфером, объявленным в GetIncomingPackets () следующим образом:
char data_buf[WS_MAX_DATA_PACKET_SIZE + 1] = {0}; // + 1 for NULL char
int WS_RecvAll(SOCKET socket_handle, char* buffer, int size)
{
int ret = 0;
int read = 0;
int i = 0;
char err_buf[100] = {0};
while(size)
{
ret = recv(socket_handle, &buffer[read], size, 0);
if (ret == SOCKET_ERROR)
{
printf("***ERROR***: recv failed, error = %d\n", WSAGetLastError());
return WS_ERROR_RECV_FAILED;
}
if (ret == 0) {
break;
}
read += ret;
size -= ret;
}
return read;
}