Я использую IPC (межпроцессное взаимодействие) для отправки данных между двумя программами на C++. Для IPC я использую базовый код TCP/IP Winsock2.
В основном идея состоит в том, что я отправляю кадры 3D-данных между двумя приложениями, одно обрабатывает данные с помощью GPU/CUDA, а другое отображает их с помощью сторонней библиотеки (PCL). Мои приложения очень богаты данными (например, 30 кадров в секунду, 4 МБ на кадр), но, насколько я знаю, это не должно быть проблемой для IPC.
Поэтому, когда обработка каждого кадра на графическом процессоре завершается, я конвертирую данные кадров (координаты X, Y, Z типа float; R, G, B типа uint8_t каждый) в байты и отправляю их один за другим.
Делая это, я заметил нечто странное. В моем коде у меня есть 9 команд send() одна за другой.
- 1ste : Отправка одного символа, который действует как имя кадра.
- 2de : одно целое число с количеством поступающих 3D-точек.
- 3-5th: значения RGB
- 6-8th: значения XYZ
- 9-е: Конец проверки связи, чтобы закрыть приложение просмотра.
Весь этот процесс занимает ~ 30 мс. Что мне показалось странным, так это то, куда уходила большая часть времени. После определения времени каждого события я получил следующее:
- 1-й этап: 20 мс (1 байт данных)
- 2de : ‹1 мс (4 байта данных)
- 3-5: 2 мс (921600 байт данных)
- 6-8: 3 мс (3686400 байт данных)
- 9-й: 1 мс (1 байт данных)
Почему для первой команды отправки требуется так много времени, даже если это всего 1 байт данных, а затем остальные данные завершаются в рекордно короткие сроки. Между каждым запуском этого цикла существует задержка около 20 мс, ожидающая завершения кода графического процессора. Переходит ли TCP-соединение в спящее состояние, и если да, то могу ли я его как-то отключить.
Код сокета TCP:
SOCKET Create_Server_Socket(PCSTR IP, PCSTR port)
{
struct addrinfo *result = NULL, *ptr = NULL, hints;
int iResult;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the local address and port to be used by the server
iResult = getaddrinfo(NULL, port, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return 1;
}
SOCKET ListenSocket = INVALID_SOCKET;
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) {
printf("Listen failed with error: %ld\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
SOCKET ClientSocket;
ClientSocket = INVALID_SOCKET;
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
return (ClientSocket);
}
Рассматриваемый код:
iResult = send(ConnectSocket, (char*)&name, sizeof(char), 0); //Takes >20ms to complete
iResult = send(ConnectSocket, (char*)&points, 4, 0);
iResult = send(ConnectSocket, (char*)Red_t, sizeof(uint8_t) * depth_width *depth_height, 0);
iResult = send(ConnectSocket, (char*)Green_t, sizeof(uint8_t) * depth_width *depth_height, 0);
iResult = send(ConnectSocket, (char*)Blue_t, sizeof(uint8_t) * depth_width *depth_height, 0);
iResult = send(ConnectSocket, (char*)z_t, sizeof(uint16_t) * depth_width *depth_height, 0);
iResult = send(ConnectSocket, (char*)x_t, sizeof(float) * depth_width *depth_height, 0)
iResult = send(ConnectSocket, (char*)y_t, sizeof(float) * depth_width *depth_height, 0);
iResult = send(ConnectSocket, "a", sizeof(char), 0);
Я работаю над Windows 10 (т.е. Winsock2 lib).
Заранее спасибо!