问个问题!createprocess和两条管道pipe通信造成的混乱!

u010249954 2013-04-12 04:48:05
描述差不多是这样的,我要在main下边调用createprocess创建一个ffplay.exe,在设置STARTUPINFO结构的时候:
STARTUPINFO siStartInfo;
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = g_hChildStd_Error; // 错误输出句柄
siStartInfo.hStdOutput = g_hChildStd_OUT_Wr; // 输出句柄
siStartInfo.hStdInput = g_hChildStd_IN_Rd; // 输入句柄
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;

当然这两个g_hChildStd_IN_Rd和g_hChildStd_OUT_Wr是绑定起来的:
if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) )
if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0))

现在是这样的:
我要往里面写一个getinfo:

while (!end_write_pipe)
{
if (!write_message.empty())
{
bSuccess = WriteFile(g_hChildStd_IN_Wr, ( char* )write_message.c_str(), write_message.length(), &dwWritten, &o);
}
else
{
Sleep(100);
}
}


然后从另一handle中取出消息,注意这里,需要两次ReadFile才能出现结果,一次什么都读不到:

while (!end_read_pipe)
{
bSuccess = ReadFile( g_hChildStd_OUT_Rd, chBuf, 90, &dwRead, &o);
DWORD dwError = GetLastError();
if (!bSuccess && (dwError == ERROR_IO_PENDING))
{
WaitForSingleObject(g_hChildStd_OUT_Rd, INFINITE);
bSuccess = true;
}
if (bSuccess && write_message == "$gw")
{
int i = strlen(chBuf);
char str[10] = {'\0'};
memcpy(str, chBuf+2, 3);
w = atoi(str);
char str2[10] = {'\0'};
memcpy(str2, chBuf+6, 3);
h = atoi(str2);
if( ! bSuccess || dwRead == 0 ) break;
if (w == (int)time_total_ms)
{
ReadFile( g_hChildStd_OUT_Rd, chBuf, 90, &dwRead, NULL);
int i = strlen(chBuf);
char str[10] = {'\0'};
memcpy(str, chBuf+2, 3);
w = atoi(str);
char str2[10] = {'\0'};
memcpy(str2, chBuf+6, 3);
h = atoi(str2);
if( ! bSuccess || dwRead == 0 ) break;
}
write_message.clear();
printf("width : %d, height : %d\n", w, h);
}
else if (bSuccess && write_message == "$gt")
{
int i = strlen(chBuf);
char str[10] = {'\0'};
memcpy(str, chBuf+2, i - 2);
time_total_ms = atof(str);
if (w == (int)time_total_ms)
{
ReadFile( g_hChildStd_OUT_Rd, chBuf, 90, &dwRead, NULL);
int i = strlen(chBuf);
char str[10] = {'\0'};
memcpy(str, chBuf+2, i - 2);
time_total_ms = atof(str);
}
write_message.clear();
printf("time_total_ms is : %f\n", time_total_ms);
}
else
{
Sleep(100);
}
memset(chBuf, 0, strlen(chBuf));
}


但是ffplay还接收q和p信息,q为退出,p为暂停和播放,上面的代码,会导致输入p的时候,造成无数次的暂停和播放(也就是反复的写入p)!

注意这里,我觉得更奇葩的是,
把Write改成这样的:

while (!end_write_pipe)
{
if (!write_message.empty())
{
printf("i : %d\n", ++i);
bSuccess = WriteFile(g_hChildStd_IN_Wr, ( char* )write_message.c_str(), write_message.length(), &dwWritten, &o);
}
else
{
Sleep(100);
}
}


ReadFile这样的:

while (!end_read_pipe)
{
bSuccess = ReadFile( g_hChildStd_OUT_Rd, chBuf, 90, &dwRead, &o);
DWORD dwError = GetLastError();
if (!bSuccess && (dwError == ERROR_IO_PENDING))
{
WaitForSingleObject(g_hChildStd_OUT_Rd, INFINITE);
bSuccess = true;
}
if (bSuccess && write_message == "$gw")
{
int i = strlen(chBuf);
char str[10] = {'\0'};
memcpy(str, chBuf+2, 3);
w = atoi(str);
char str2[10] = {'\0'};
memcpy(str2, chBuf+6, 3);
h = atoi(str2);
if( ! bSuccess || dwRead == 0 ) break;
// if (w == (int)time_total_ms)
// {
// ReadFile( g_hChildStd_OUT_Rd, chBuf, 90, &dwRead, NULL);
// int i = strlen(chBuf);
// char str[10] = {'\0'};
// memcpy(str, chBuf+2, 3);
// w = atoi(str);
// char str2[10] = {'\0'};
// memcpy(str2, chBuf+6, 3);
// h = atoi(str2);
// if( ! bSuccess || dwRead == 0 ) break;
// }
write_message.clear();
printf("width : %d, height : %d\n", w, h);
}
else if (bSuccess && write_message == "$gt")
{
int i = strlen(chBuf);
char str[10] = {'\0'};
memcpy(str, chBuf+2, i - 2);
time_total_ms = atof(str);
// if (w == (int)time_total_ms)
// {
// ReadFile( g_hChildStd_OUT_Rd, chBuf, 90, &dwRead, NULL);
// int i = strlen(chBuf);
// char str[10] = {'\0'};
// memcpy(str, chBuf+2, i - 2);
// time_total_ms = atof(str);
// }
write_message.clear();
printf("time_total_ms is : %f\n", time_total_ms);
}
else
{
Sleep(100);
}
memset(chBuf, 0, strlen(chBuf));
}

输出34次i,就不必两次ReadFile了!(如果像上面的代码不读两次 比如第一次获取wh,接着获取time,会出现time的结果是w的value!)

还有一种情况WriteFile的代码:

while (!end_write_pipe)
{
if (!write_message.empty())
{
write_message += "\r\n";
bSuccess = WriteFile(g_hChildStd_IN_Wr, ( char* )write_message.c_str(), write_message.length(), &dwWritten, &o);
// DWORD dwError = GetLastError();
write_message.clear();
}
else
{
Sleep(100);
}
}


p和q正常,但是永远获取不到wh和time!

这是很奇葩的!所以来这边问问!谢谢各位帮我看看,我可能写了一天代码了,一些细节问题没有注意到!
...全文
315 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
u010249954 2013-04-17
  • 打赏
  • 举报
回复
自己处理了,谢谢楼上各位
u010249954 2013-04-16
  • 打赏
  • 举报
回复
引用 17 楼 kyotrue 的回复:
引用 16 楼 u010249954 的回复:引用 15 楼 kyotrue 的回复: 引用 14 楼 u010249954 的回复:引用 12 楼 kyotrue 的回复: 你用同步方式试试,我觉得是你异步ReadFile出问题了 我感觉我现在就是同步的! 你用了OverLapped,哪儿是同步啊?同步读写的话,最后一个参数应该是NULL 那我改成NULL……
黏包是啥意思?给个简单的例子呗!
kyotrue 2013-04-16
  • 打赏
  • 举报
回复
引用 16 楼 u010249954 的回复:
引用 15 楼 kyotrue 的回复: 引用 14 楼 u010249954 的回复:引用 12 楼 kyotrue 的回复: 你用同步方式试试,我觉得是你异步ReadFile出问题了 我感觉我现在就是同步的! 你用了OverLapped,哪儿是同步啊?同步读写的话,最后一个参数应该是NULL 那我改成NULL也是一样的,我总觉得我的消息没控制好,从ReadFile那给我返回了多个……
比如应该是640&380的,却给我返回了640&380640&380640&380…… 这个是正常的,已经说过了,面向流的,本来就是这样。你要自己分包处理,加标记、加每个包长度标识、自己做缓存来黏包
u010249954 2013-04-16
  • 打赏
  • 举报
回复
引用 15 楼 kyotrue 的回复:
引用 14 楼 u010249954 的回复:引用 12 楼 kyotrue 的回复: 你用同步方式试试,我觉得是你异步ReadFile出问题了 我感觉我现在就是同步的! 你用了OverLapped,哪儿是同步啊?同步读写的话,最后一个参数应该是NULL
那我改成NULL也是一样的,我总觉得我的消息没控制好,从ReadFile那给我返回了多个消息,比如应该是640&380的,却给我返回了640&380640&380640&380,所以我觉得是WriteFile那里,多写了几次导致的!但我可能太笨 没看出来怎么处理!
kyotrue 2013-04-16
  • 打赏
  • 举报
回复
引用 14 楼 u010249954 的回复:
引用 12 楼 kyotrue 的回复: 你用同步方式试试,我觉得是你异步ReadFile出问题了 我感觉我现在就是同步的!
你用了OverLapped,哪儿是同步啊?同步读写的话,最后一个参数应该是NULL
  • 打赏
  • 举报
回复
引用 18 楼 u010249954 的回复:
引用 17 楼 kyotrue 的回复:引用 16 楼 u010249954 的回复:引用 15 楼 kyotrue 的回复: 引用 14 楼 u010249954 的回复:引用 12 楼 kyotrue 的回复: 你用同步方式试试,我觉得是你异步ReadFile出问题了 我感觉我现在就是同步的! 你用了OverLapped,哪儿是同步啊?同步读写的话,最后一……
你的这种情况就是黏包
微尘8 2013-04-15
  • 打赏
  • 举报
回复
你可以下载这个参考参考,http://download.csdn.net/detail/xiaohuh421/2682969 VC++实现CMD命令执行与获得返回信息
u010249954 2013-04-15
  • 打赏
  • 举报
回复
引用 4 楼 zengraoli 的回复:
既然已经知道了,有这么两种情况,结合起来处理不了,那应该想想怎样分开出来单独处理,函数有些重复不要紧,完成既定任务才是最终的目标!楼主在好好想想!
似乎有点思路,不过太泛泛了!
u010249954 2013-04-15
  • 打赏
  • 举报
回复
引用 5 楼 kyotrue 的回复:
全是代码,缺少问题描述。。。 没看你的代码,你需要注意两点: 1、管道是面向流的,和TCP编程一样,发送方发N次,不代表接收方要收N次。 2、重定向子进程输入输出,两条管道都是单向使用的,一条是主进程写、替代子进程的键盘输入,一条是主进程读、替换子进程的屏幕输出
对啊 我就是这么做的 对于你的2点,我的疑问是,是不是有的时候发送方发N次,接收方可能得到比N少的次数呢?
kyotrue 2013-04-15
  • 打赏
  • 举报
回复
全是代码,缺少问题描述。。。 没看你的代码,你需要注意两点: 1、管道是面向流的,和TCP编程一样,发送方发N次,不代表接收方要收N次。 2、重定向子进程输入输出,两条管道都是单向使用的,一条是主进程写、替代子进程的键盘输入,一条是主进程读、替换子进程的屏幕输出
  • 打赏
  • 举报
回复
既然已经知道了,有这么两种情况,结合起来处理不了,那应该想想怎样分开出来单独处理,函数有些重复不要紧,完成既定任务才是最终的目标!楼主在好好想想!
u010249954 2013-04-15
  • 打赏
  • 举报
回复
引用 12 楼 kyotrue 的回复:
你用同步方式试试,我觉得是你异步ReadFile出问题了
我感觉我现在就是同步的!
u010249954 2013-04-15
  • 打赏
  • 举报
回复
引用 12 楼 kyotrue 的回复:
你用同步方式试试,我觉得是你异步ReadFile出问题了
怎样同步啊?
kyotrue 2013-04-15
  • 打赏
  • 举报
回复
你用同步方式试试,我觉得是你异步ReadFile出问题了
u010249954 2013-04-15
  • 打赏
  • 举报
回复
引用 9 楼 kyotrue 的回复:
引用 6 楼 u010249954 的回复:引用 5 楼 kyotrue 的回复: 全是代码,缺少问题描述。。。 没看你的代码,你需要注意两点: 1、管道是面向流的,和TCP编程一样,发送方发N次,不代表接收方要收N次。 2、重定向子进程输入输出,两条管道都是单向使用的,一条是主进程写、替代子进程的键盘输入,一条是主进程读、替换子进程的屏幕输出 对啊 我……
是的 我的问题就是这个了,我测试了一下,第一次写入的时候需要closehandle(写入句柄),才能从readfile中读出,不close就死在那了;如果我关闭了,在创建也不行
u010249954 2013-04-15
  • 打赏
  • 举报
回复
引用 8 楼 d704791892 的回复:
你可以下载这个参考参考,http://download.csdn.net/detail/xiaohuh421/2682969 VC++实现CMD命令执行与获得返回信息
他这个没有多大的价值,因为每次都是新建管道,我这是需要在同一个管道中写入和读取多次!
kyotrue 2013-04-15
  • 打赏
  • 举报
回复
引用 6 楼 u010249954 的回复:
引用 5 楼 kyotrue 的回复: 全是代码,缺少问题描述。。。 没看你的代码,你需要注意两点: 1、管道是面向流的,和TCP编程一样,发送方发N次,不代表接收方要收N次。 2、重定向子进程输入输出,两条管道都是单向使用的,一条是主进程写、替代子进程的键盘输入,一条是主进程读、替换子进程的屏幕输出 对啊 我就是这么做的 对于你的2点,我的疑问是,是不是有的时候发送方发N次,……
是面向流的,当然可能发送N次,只接收一次就完了;也可能发送1次接收2次;也可能发送2次也接收2次,但两次之间中断处不同。。。
u010249954 2013-04-13
  • 打赏
  • 举报
回复
有没有人啊!
u010249954 2013-04-12
  • 打赏
  • 举报
回复
还是等不到啊!哎
u010249954 2013-04-12
  • 打赏
  • 举报
回复
在线等!麻烦大家了!

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧