Коммуникационный сервер-клиент C ++ - PullRequest
0 голосов
/ 02 августа 2020

Пишу сетевую программу на C ++. Как это работает:

  1. Сервер передает видео для клиента в реальном времени.
  2. Клиент получает видеоданные.

Я пытался установить до отправки и получения сообщений (прямо во время потоковой передачи). Для этого я запустил видео в отдельном потоке.

Сообщения от клиента к серверу без проблем доходят до сервера. Но если отправлять сообщения с сервера клиенту, то сначала меняется само видео, а отображается какая-то фигня.

Как это работает (нет) введите описание изображения здесь

Я так понимаю, это связано с тем, что клиент постоянно получает сообщения (см.). Но возможно ли как-то решить эту проблему?

Код сервера

#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;
}
...