使用命名管道将图像帧从 C++ 服务器发送到 C# 客户端

Posted

技术标签:

【中文标题】使用命名管道将图像帧从 C++ 服务器发送到 C# 客户端【英文标题】:Send Image Frames from C++ Server to C# Client using Named Pipe 【发布时间】:2018-06-21 04:34:23 【问题描述】:

我是IPC 的菜鸟。我正在尝试将图像帧从我的C++ Server 发送到C# Client。我已经开始了解这一点,并制作了一个小的ClientServer,其中我的C++ Server 发送Hello。我看到了一个相关的问题,有人告诉我先将Image 转换为Byte Array,然后以与Hello Message 相同的方式发送,但我不能这样做。

我的基本客户端服务器代码

C++ 代码:

    Mat image = imread("IMG_0_10_34_45_2018_1.bmp");
uchar buffer[500][500];
for (int i = 0; i < image.rows; i++)

    for (int j = 0; j < image.cols; j++)
    
        buffer[i][j] = image.at<unsigned char>(i, j);
    

cout << "Server Creating Pipe\n";
HANDLE hPipe = ::CreateNamedPipe(_T("\\\\.\\pipe\\HyperPipe"),
    PIPE_ACCESS_DUPLEX,
    PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
    PIPE_UNLIMITED_INSTANCES,
    4096,
    4096,
    0,
    NULL);

cout << "Server Created Succesfully";
ConnectNamedPipe(hPipe, NULL);

cout << "Sending Message to Client";
DWORD bytesWritten = 0;
WriteFile(hPipe, buffer, sizeof(buffer) * sizeof(uchar), &bytesWritten, NULL);
CloseHandle(hPipe);
return 0;

和 C# 代码:

static void Main(string[] args)

    Console.WriteLine("Creating Client Pipe");
    NamedPipeClientStream pipe = new NamedPipeClientStream(".", "HyperPipe", PipeDirection.InOut);
    Console.WriteLine("Pipe Created Successfully, Connecting to Server");
    pipe.Connect();
    Console.WriteLine("Successfully, Connected to Server");
    using (StreamReader rdr = new StreamReader(pipe, Encoding.Unicode))
    
        System.Console.WriteLine("Message from Server: " + rdr.ReadToEnd());
    

    Console.ReadKey();

我还注意到,在我的C++ Server 中,我必须更改PIPE_TYPE to BYTEREADMODE to BYTE。我将OpenCV library 用于Image Processing,所以我可以轻松地使Byte Array 没有问题。

那么,谁能告诉我如何将Byte ArrayC++ 发送到C#。 或者如果可能的话,任何人都可以为我提供代码

提前致谢

更新: 没有错误出现,但在客户端,即C# Side,来自服务器的消息的输出是?????

【问题讨论】:

嗯,可能使用流而不是消息,因为它有点大? 是的,先生,我使用的是 BYTE 而不是 MESSAGE,但是如何传输字节数组? 不,我的意思是尝试PIPE_TYPE_BYTE 而不是PIPE_TYPE_MESSAGE。对不起,我应该是明确的 是的,我已经这样做了 太棒了!不要忘记,如果您自己找到了解决方案,请随时将其发布为您自己问题的答案。如果没有更好的答案,您可以接受它作为解决方案,从而获得声誉积分。祝你一切顺利 【参考方案1】:

要将字节数组从Server 发送到Client,即buffer,只需对WriteFile 函数进行小改动。

WriteFile(hPipe, buffer, sizeof(buffer) * sizeof(uchar), &bytesWritten, NULL);

此方法会将整个Byte Array 发送到Client 并且还更改了buffer

int _count = 0;
UINT8 _imageBuffer[110592];
for (int _imageRow = 0; _imageRow < _image.rows; _imageRow++)

    for (int _imageCol = 0; _imageCol < _image.cols; _imageCol++)
    
        buffer[_count] = image.at<uchar>(_imageRow, _imageCol);
        _count++;
    

我对缓冲区数组进行了硬编码,因为我知道我的相机只会发送110592 字节来创建一帧。

而在客户端只需使用Read 函数。

            int _imageRowSize = 288;
            int _imageColSize = 384;
            int _count = 0;
            byte[] buffer = new byte[_imageColSize * _imageRowSize];
            Image<Gray, UInt16> image = new Image<Gray, UInt16>(_imageColSize,_imageRowSize);
            Console.WriteLine("Creating Client Pipe");
            NamedPipeClientStream pipe = new NamedPipeClientStream(".", "HyperPipe", PipeDirection.InOut);
            Console.WriteLine("Pipe Created Successfully, Connecting to Server");
            pipe.Connect();
            Console.WriteLine("Successfully, Connected to Server");
            using (MemoryStream ms = new MemoryStream())
            
                while (true)
                
                    _count = 0;      
                    int read = pipe.Read(buffer, 0, buffer.Length);
                    for (int _imageRow = 0; _imageRow < 288; _imageRow++)
                    
                        for (int _imageCol = 0; _imageCol < 384; _imageCol++)
                        
                            try
                            
                                image.Data[_imageRow, _imageCol, 0] = (UInt16)(buffer[_count] * 255);
                            catch(Exception exception)
                            
                                Console.WriteLine(exception);
                            
                            _count++;
                        
                    
                    if (read <= 0)
                        break;
                    ms.Write(buffer, 0, read);
                
                       
            CvInvoke.Imshow("Image", image);
        

【讨论】:

以上是关于使用命名管道将图像帧从 C++ 服务器发送到 C# 客户端的主要内容,如果未能解决你的问题,请参考以下文章

命名管道:C# 服务器、C++ 客户端

使用命名管道的两种 C++ 到 C# 通信

从 VB6 到 WCF 的命名管道

使用名称管道将结构从 C# 应用程序传递到 C++ 服务器?

将数据从 C++ 发送到 C# [重复]

命名管道 C# 服务器 C++ .dll 客户端不工作?