Как мне преобразовать этот блокирующий режим ввода-вывода в перекрывающийся режим ввода-вывода на языке c в Windows?

Я учусь делать сокет-программирование и многопоточное программирование на C на Windows. Я разработал проект, в котором будет три типа узлов для резервного копирования (сервер, клиент и узел хранения). Я создал следующее, чтобы иметь один сервер и несколько клиентов и узлов хранения. Сервер должен создать два вида потоков на основе типа клиента, запрашивающего услугу (чтобы быть явным обычным клиентом или узлом хранения). Я использую блокирующий режим ввода / вывода. Структура кода выглядит следующим образом:

Сервер:

int main()
{
//initialization and other things
while ((new_socket = accept(srv_sock, (struct sockaddr *)&client, &c)) != INVALID_SOCKET)
    {
        _beginthreadex(0, 0, handle_client, &new_socket, 0, 0);
    }
}

uint32_t __stdcall handle_client(void *data)
{
    SOCKET* sock = (SOCKET*)data;
    SOCKET client_sock = *sock;
//other 
    recv_size = recv(client_sock, header_buf, HDR_LEN, 0);
//fixed length header

if (!strncmp(connect_with, "storageNode", strlen(connect_with)))
//check if client is a normal client or a storage node
    {
        _beginthreadex(0, 0, handle_storage_node, sock, 0, 0);
        return 0;
    }
else
    {
        //continue with request from normal client
    }
}

uint32_t __stdcall handle_storage_node(void *data)
{
    SOCKET* sock_SN = (SOCKET*)data;
    SOCKET str_node_sock = *sock_SN;
//continue with request from storage node
}

Основная причина, среди прочего, для меня, чтобы захотеть изменить его на перекрывающийся ввод-вывод, заключается в том, что иногда (вероятно, один раз в тысячу раз) сообщение от обычного клиента заканчивается как сообщение от узла хранения, и наоборот. Я думаю, что причина в том, что winsock не является строго потокобезопасным. Плюс как новичок я хочу научиться делать это по-другому. Итак, какой должна быть эквивалентная структура для реализации перекрывающегося ввода-вывода? И как мне остановить доставку сообщений не в ту ветку?

PS: - Я новичок, успокойся!

1 ответ

Ваша проблема не в режиме перекрытия или нет. Дело в том, что ваша программа действует на недействительных данных.

В таких строках

_beginthreadex(0, 0, handle_client, &new_socket, 0, 0);

Вы передаете адрес переменной в стеке новому потоку. Этот адрес будет за пределами итерации цикла while. И, скорее всего, будет использоваться для хранения следующего дескриптора сокета, когда в следующий раз успешно выполнится accept.

Чтобы это исправить, вы можете выделить в куче каждый экземпляр сокета и передать эту функцию вашему рабочему потоку.

Перекрытое большинство просто все усложнит. Если вы не знаете, зачем вам это нужно, вам нет смысла его использовать.

Другие вопросы по тегам