Пишу сетевую программу на C ++. Как это работает:
- Сервер передает видео для клиента в реальном времени.
- Клиент получает видеоданные.
Я пытался установить до отправки и получения сообщений (прямо во время потоковой передачи). Для этого я запустил видео в отдельном потоке.
Сообщения от клиента к серверу без проблем доходят до сервера. Но если отправлять сообщения с сервера клиенту, то сначала меняется само видео, а отображается какая-то фигня.
Как это работает (нет) введите описание изображения здесь
Я так понимаю, это связано с тем, что клиент постоянно получает сообщения (см.). Но возможно ли как-то решить эту проблему?
Код сервера
#include "server.h"
int Server::open()
{
WORD DLLVersion = MAKEWORD(2, 1);
if (WSAStartup(DLLVersion, &wsaData) != 0)
{
std::cout << "Error" << std::endl;
exit(1);
}
int sizeofaddr = sizeof(addr);
addr.sin_addr.s_addr = inet_addr(addrss);
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
server = socket(AF_INET, SOCK_STREAM, NULL);
bind(server, (SOCKADDR*)&addr, sizeof(addr));
listen(server, SOMAXCONN);
std::cout << "Listening..." << std::endl;
client = accept(server, (SOCKADDR*)&addr, &sizeofaddr);
if (client == 0) {
std::cout << "Error #2\n";
}
else {
std::cout << "Client Connected!\n";
}
}
int Server::sendData(const char *buffer, int len)
{
return send(client, buffer, len, NULL);
}
int Server::recvData(char *buffer, int len)
{
return recv(client, buffer, len, NULL);
}
int Server::close()
{
closesocket(server);
std::cout << "Server is closed" << std::endl;
return 0;
}
Сервер основной
#include "server.h"
#include "opencv2/core/core.hpp"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2\video\background_segm.hpp"
#include <opencv2\video\tracking.hpp>
#include <Windows.h>
#include <thread>
#include <string>
#define FRAME_WIDTH 640
#define FRAME_HEIGHT 480
#define CLIENT_CLOSE_CONNECTION_SYMBOl '#'
cv::Mat cameraFeed;
int height, width, IM_HEIGHT, IM_WIDTH, imgSize;
bool is_client_connection_close(const char *msg)
{
for (int i = 0; i < strlen(msg); ++i)
{
if (msg[i] == CLIENT_CLOSE_CONNECTION_SYMBOl)
{
return true;
}
}
return false;
}
void VideoSender(Server server)
{
cv::VideoCapture cap(0);
while (true)
{
cv::Mat frame, image;
if (!cap.read(cameraFeed))
{
std::cout << "Video dont work" << std::endl;
break;
}
height = cameraFeed.rows;
width = cameraFeed.cols;
IM_HEIGHT = FRAME_HEIGHT;
IM_WIDTH = FRAME_WIDTH;
resize(cameraFeed, cameraFeed, cv::Size(IM_WIDTH, IM_HEIGHT));
imgSize = cameraFeed.total()*cameraFeed.elemSize();
server.sendData(reinterpret_cast<char*>(cameraFeed.data), imgSize);
imshow("Video_sending", cameraFeed);
char button = cv::waitKey(10);
if (button == 'q')
{
std::cout << "Stop sending video data..." << std::endl;
cap.release();
cv::destroyWindow("Video_sending");
server.close();
break;
}
}
}
int main(int argc, char* argv[])
{
Server server;
server.open();
std::thread th_video(VideoSender, server);
while (true)
{
//sending message
std::string msg1;
std::getline(std::cin, msg1);
int msg_size1 = msg1.size();
server.sendData((char*)&msg_size1, sizeof(int));
server.sendData(msg1.c_str(), msg_size1);
//receive_message
int msg_size;
server.recvData((char*)&msg_size, sizeof(int));
char *msg = new char[msg_size + 1];
msg[msg_size] = '\0';
server.recvData(msg, msg_size);
std::cout << "Message from client: " << msg
<< " (size: " << msg_size << ")"
<< std::endl;
delete[] msg;
}
system("pause");
return 0;
}
Код клиента
#include "client.h"
int Client::open()
{
WORD DLLVersion = MAKEWORD(2, 1);
if (WSAStartup(DLLVersion, &wsaData) != 0) {
std::cout << "Error" << std::endl;
exit(1);
}
int sizeofaddr = sizeof(addr);
addr.sin_addr.s_addr = inet_addr(addrs);
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
server = socket(AF_INET, SOCK_STREAM, NULL);
if (connect(server, (SOCKADDR*)&addr, sizeof(addr)) != 0) {
std::cout << "Error: failed connect to server.\n";
return 1;
}
std::cout << "Connected!\n";
}
int Client::sendData(const char * buffer, int len)
{
return send(server, buffer, len, NULL);
}
int Client::recvData(char *buffer, int len)
{
return recv(server, buffer, len, NULL);
}
int Client::close()
{
closesocket(server);
std::cout << "Server is closed" << std::endl;
return 0;
}
Клиент основной
#include "client.h"
#include "opencv2/core/core.hpp"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2\video\background_segm.hpp"
#include <opencv2\video\tracking.hpp>
#include <Windows.h>
#include <string>
#include <thread>
#pragma warning(disable: 4996)
#define FRAME_WIDTH 640
#define FRAME_HEIGHT 480
int imgSize;
int bytes = 0;
bool running = true;
int msg_size;
void VideoReceiver(Client client)
{
while (running)
{
int IM_HEIGHT = FRAME_HEIGHT;
int IM_WIDTH = FRAME_WIDTH;
cv::Mat img = cv::Mat::zeros(FRAME_HEIGHT, FRAME_WIDTH, CV_8UC3);
imgSize = img.total()*img.elemSize();
const int ah = 921600;
char sockData[ah];
for (int i = 0; i < imgSize; i += bytes)
if ((bytes = client.recvData(sockData + i, imgSize - i)) == 0)
std::cout << "WTF" << std::endl;
int ptr = 0;
for (int i = 0; i < img.rows; ++i)
for (int j = 0; j < img.cols; ++j)
{
img.at<cv::Vec3b>(i, j) = cv::Vec3b(sockData[ptr + 0], sockData[ptr + 1], sockData[ptr + 2]);
ptr = ptr + 3;
}
cv::namedWindow("Reveived_video", cv::WINDOW_AUTOSIZE);
imshow("Reveived_video", img);
char button = cv::waitKey(10);
if (button == 'q')
{
std::cout << "Stop reveiving video data..." << std::endl;
cv::destroyWindow("Reveived_video");
client.close();
break;
}
}
}
void message_sendind(Client client)
{
while (true)
{
//receiv message
int msg_size;
client.recvData((char*)&msg_size, sizeof(int));
char *msg = new char[msg_size + 1];
msg[msg_size] = '\0';
client.recvData(msg, msg_size);
std::cout << "Message from server: " << msg
<< " (size: " << msg_size << ")"
<< std::endl;
delete[] msg;
//sending message
//std::string msg1;
//std::getline(std::cin, msg1);
//int msg_size1 = msg1.size();
//client.sendData((char*)&msg_size1, sizeof(int));
//client.sendData(msg1.c_str(), msg_size1);
}
}
int main(int argc, char* argv[])
{
Client client;
client.open();
std::thread th_video(VideoReceiver, client);
while (true)
{
//receiv message
int msg_size;
client.recvData((char*)&msg_size, sizeof(int));
char *msg = new char[msg_size + 1];
msg[msg_size] = '\0';
client.recvData(msg, msg_size);
std::cout << "Message from server: " << msg
<< " (size: " << msg_size << ")"
<< std::endl;
delete[] msg;
//sending message
std::string msg1;
std::getline(std::cin, msg1);
int msg_size1 = msg1.size();
client.sendData((char*)&msg_size1, sizeof(int));
client.sendData(msg1.c_str(), msg_size1);
}
system("pause");
return 0;
}