我试图开始使用命名管道,因为将来我需要将其用于我的项目.
目前,我有一个C服务器,它等待客户端连接并发送测试消息.我大致按照此tutorial开始.相关代码如下:
#define MESSAGE L"TestMessage"
HANDLE hnamedPipe = INVALID_HANDLE_VALUE;
hnamedPipe = CreateNamedPipe(
L"\\\\.\\pipe\\testpipe",
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE|
PIPE_READMODE_MESSAGE|
PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
1024,
1024,
NMPWAIT_USE_DEFAULT_WAIT,
NULL);
if(hnamedPipe == INVALID_HANDLE_VALUE)
{
cout << "Failed" << endl;
}
while(true)
{
cout<< "Waiting for client"<< endl;
if(!ConnectNamedPipe(hnamedPipe,NULL))
{
if(ERROR_PIPE_CONNECTED != GetLastError())
{
cout << "FAIL"<< endl;
}
}
cout<<"Connected!"<<endl;
//Send over the message
wchar_t chResponse[] = MESSAGE;
DWORD cbResponse,cbWritten;
cbResponse = sizeof(chResponse);
if(!WriteFile(
hnamedPipe,
chResponse,
cbResponse,
&cbWritten,
NULL))
{
wprintf(L"failiure w/err 0x%08lx\n",GetLastError);
}
cout<<"Sent bytes :)" << endl;
}
客户端代码(C#)如下:
using (NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut))
{
while (true)
{
Console.WriteLine("Connecting to server...");
pipeClient.Connect();
Console.WriteLine("Connected :)");
Console.WriteLine(pipeClient.ReadByte());
pipeClient.Close();
Console.WriteLine("Closed");
}
}
目前,我已经使客户端成功连接到服务器,并且它打印出第一个字节.我想知道如何做两件事:
>阅读整个消息-我尝试在pipeClient上使用StreamReader读取消息,但它无限期地挂在ReadLine()上.
>连续发送消息-我希望服务器将消息后的消息发送给客户端,客户端将一次读取它们并打印出来.我对IPC一点儿也不了解,所以起初我尝试使客户端断开连接,并在while(true)循环中重新连接到服务器,而服务器处于while true循环中,该循环总是在顶部等待新的客户端连接之前发送另一条消息.我的尝试是在上面的代码中.
任何帮助,将不胜感激.最终目标是将图像从服务器发送到客户端.然后,客户端将它们实时打印到屏幕上.在尝试图像数据之前,我想使用简单的字符串消息来完成此工作.
编辑:
最终,我希望能够从客户端向服务器发送一条消息,指示它想要获取最新的图像帧,然后服务器将通过客户端随后在屏幕上显示的最新帧进行发送.因此流程为:
>客户->服务器:指示客户端需要最新的帧信息. (有些简单的事情,可能是值为1的无符号整数)
>服务器->客户:最新的框架信息. (640×480图像以RGB字节值存储在字节数组中)
>客户端:在显示屏上显示框架.
解决方法:
ReadLine挂起,因为它正在等待换行符,您的测试消息不包含换行符.
如果要服务器连续发送消息,只需在WriteFile调用周围放一个循环即可.您不需要连接多次.同样,在客户端中,将循环放在ReadLine周围.
如果每个消息都包含以换行符结尾的文本,则该内容就足够了,但是如果您确实希望管道客户端以消息模式工作,则需要调用:
pipeClient.ReadMode = PipeTransmissionMode.Message;
但是,我怀疑这是否可以与StreamReader很好地交互.相反,您应该使用pipeClient.Read阅读单个消息.
更新资料
要回答您的新问题:
在服务器上,一旦客户端连接,就进入一个循环,其中:
>服务器从客户端读取数据.这将阻塞,直到客户端请求一个帧为止.
>服务器发送一个帧.
在客户端上,一旦它连接到服务器,就进入一个循环,其中:
>客户端发送“请发送框架”消息.
>客户端从服务器读取以获取框架.
>客户端显示框架.
我不会使用消息模式管道.如果帧的大小固定,则客户端知道要从服务器读取多少数据.否则,请在框架前加上包含其长度的uint.