简体   繁体   English

如何使用Win RPC发送终止的char数组(用于将映像从客户端上传到服务器)

[英]how to use win RPC to send terminated char array(use to upload image from client to server)

My project let me use C++ Windows RPC to upload image from client to server. 我的项目允许我使用C ++ Windows RPC将图像从客户端上传到服务器。 I do not use WIN RPC before, So I tried some examples include send basic "Hello world" Message to server, but the huge issue is the function can't send unsigned char* include '\\0'. 我以前没有使用WIN RPC,所以我尝试了一些示例,包括向服务器发送基本的“ Hello world”消息,但是最大的问题是该函数无法发送未签名的char *包括'\\ 0'。 I appreciate someone can give me some suggestion to solve this problem. 我感谢有人可以给我一些解决此问题的建议。


I use opencv 3.2 to read image to Mat, and I can get Mat data and use memcpy to copy the Mat.data then create a new image in local client. 我使用opencv 3.2将图像读取到Mat,可以获取Mat数据并使用memcpy复制Mat.data,然后在本地客户端中创建新图像。 But when I send Mat.data to server, the first of characters in the Mat.data is '\\0'. 但是,当我将Mat.data发送到服务器时,Mat.data中的第一个字符为'\\ 0'。 All the Mat.data don't send to server. 所有的Mat.data都不会发送到服务器。

My MIDL core code(I have defined uuid and version) is 我的MIDL核心代码(我已经定义了uuid和版本)是

void Output(
    [in, out, size_is(1048576), string] unsigned char szString[]
);
void Output1(
    [in, string] unsigned char* szString1
);

My Client core code(It has include all require header) is 我的客户核心代码(已包含所有require标头)为

Mat I = imread("U:\\normal.jpg", IMREAD_ANYDEPTH);
if (I.empty())
{
    std::cout << "!!! Failed imread(): image not found" << std::endl;
    // don't let the execution continue, else imshow() will crash.
}
if (!I.data) {
    std::cout << "can't open or find image" << std::endl;
    //return -1;
}
Mat out;
I.convertTo(I, CV_32F);
I = (I.reshape(0, 1)); // to make it continuous
char tr[512*512*4];
memcpy_s(tr, 512 * 512 * 4, I.data, 512*512 * 4);
//snprintf(tr, 512*512*4,"%s", I.data);
out = Mat(512,512, CV_32F, &tr[0]);
namedWindow("Display window", CV_WINDOW_AUTOSIZE);// Create a window for display.
imshow("Display window", out);
waitKey(5000);

..... .....

RpcTryExcept
{
    std::clog << "Calling Open" << std::endl;
    output((unsigned char* )tr);
    //output1((unsigned char* )tr);
}

Server side is pretty same with client, I use break point in server to debug, but server side can't get the unsigned char array. 服务器端与客户端非常相似,我使用服务器中的断点进行调试,但服务器端无法获取未签名的char数组。 I think it's because my function in MIDL just can send the char array, which is end by a null terminated('\\0') string? 我认为这是因为MIDL中的函数只能发送char数组,该数组以null结尾的('\\ 0')字符串结尾吗? I tried set the array length or the size of the char pointer but still can't transmit '\\0' unsigned char to server. 我尝试设置数组长度或char指针的大小,但仍然无法将'\\ 0'无符号char传输到服务器。

From the MSDN explanation, when you sending array to stub you need to specify length_is also in your midl code. 根据MSDN的说明,将数组发送到存根时,还需要在midl代码中指定length_is。

The [ size_is] attribute indicates the upper bound of the array while the [ length_is] attribute indicates the number of array elements to transmit. [size_is]属性指示数组的上限,而[length_is]属性指示要传输的数组元素的数量。 In addition to the array, the remote procedure prototype must include any variables representing length or size that determine the transmitted array elements (they can be separate parameters or bundled with the string in a structure). 除了数组之外,远程过程原型还必须包括表示长度或大小的任何变量,这些变量确定传输的数组元素(它们可以是单独的参数,也可以与结构中的字符串捆绑在一起)。 These attributes can be used with wide-character or single-byte character arrays just as they would be with arrays of other types. 这些属性可以与宽字符或单字节字符数组一起使用,就像与其他类型的数组一样。

And

As an [in] parameter, achInOut must point to valid storage on the client side. 作为[in]参数,achInOut必须指向客户端上的有效存储。 The developer allocates memory associated with the array on the client side before making the remote procedure call. 在进行远程过程调用之前,开发人员会在客户端上分配与数组关联的内存。 The stubs use the [size_is] parameter strsize to allocate memory on the server and then use the [length_is] parameter pcbSize to transmit the array elements into this memory. 存根使用[size_is]参数strsize在服务器上分配内存,然后使用[length_is]参数pcbSize将数组元素传输到此内存中。 The developer must make sure the client code sets the [length_is] variable before calling the remote procedure. 开发人员必须在调用远程过程之前确保客户端代码设置了[length_is]变量。

Their example of character array sending: 他们的字符数组发送示例:

#define STRSIZE 500 //maximum string length

void Analyze(
  [in, out, length_is(*pcbSize), size_is(STRSIZE)] char  achInOut[],
  [in, out]  long *pcbSize);


/* client */ 
char achInOut[STRSIZE];
long cbSize;
...
gets_s(achInOut, STRSIZE);       // get patient input
cbSize = strlen(achInOut) + 1;   // transmit '\0' too
Analyze(achInOut, &cbSize);

/* server */ 
Analyze(char * str, long * pcbSize)
{
   ...
   *pcbSize = strlen(str) + 1; // transmit '\0' too
   return;
}

I think, this msdn link will help you. 我认为,此msdn链接将为您提供帮助。

Do you have to use OpenCV to read image data? 您必须使用OpenCV读取图像数据吗? Since this post has not been closed, you can try this alternative way to open image file(it works for text file as well) in binary mode, then read/save data into a float array, send it to server. 由于此帖子尚未关闭,您可以尝试这种替代方法以二进制模式打开图像文件(它也适用于文本文件),然后将数据读取/保存到float数组中,然后将其发送到服务器。 I wrote a simple demo. 我写了一个简单的演示。 It works and avoid the null-terminator problem for string. 它可以正常工作,避免了字符串的空终止符问题。

Sender: 发件人:

//Open file
char filename[] = "demo1.jpg";
FILE *fp = fopen(filename,"rb");

//Get File size
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
fseek(fp, 0, SEEK_SET);

//Read file to buffer
float *img = new float[size];
fread(img, 1, size, fp);

RpcTryExcept
{   
    //Call your function pre-defined in IDL here to send float arry  
}

Receiver: 接收器:

FILE *fp = fopen((char *)fileName, "wb");
int recvByte = fwrite(img, 1, size, fp);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM