C# 命名管道双向通信
本文关键字:双向通信 管道 | 更新日期: 2023-09-27 18:35:32
我有两个用 c++ 和 c# 编写的程序。我想在它们之间使用命名管道建立双向通信。C# 客户端程序可以连接到 C++ 服务器程序创建的命名管道。但两端都没有收到任何消息。
这是 c++ 部分(服务器):
#include <iostream>
#include <windows.h>
#include <stdlib.h>
#define UNICODE
using namespace std;
HANDLE hnamedPipe = INVALID_HANDLE_VALUE;
BOOL Finished =false;
HANDLE hThread = NULL;
unsigned long __stdcall CS_RcvThr(void * pParam) ;
int main(int argc, char **argv)
{
hnamedPipe = CreateNamedPipe(
"''''.''pipe''vikeyP",
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;
}
}
else
{
cout<<"Connected!"<<endl;
hThread = CreateThread( NULL, 0, &CS_RcvThr, NULL, 0, NULL);
if(hThread) cout<<"read thread created"<<endl; else cout<<"cant crat rd thed'n";
break;
}
}
while(1)
{
cout<<"lst loop"<<endl;
//Send over the message
char chResponse[] = "hello'n";
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;
Sleep(10);
}
}
unsigned long __stdcall CS_RcvThr(void * pParam) {
BOOL fSuccess;
char chBuf[100];
DWORD dwBytesToWrite = (DWORD)strlen(chBuf);
DWORD cbRead;
int i;
while (1)
{
fSuccess =ReadFile( hnamedPipe,chBuf,dwBytesToWrite,&cbRead, NULL);
if (fSuccess)
{
printf("C++ App: Received %d Bytes : ",cbRead);
for(i=0;i<cbRead;i++)
printf("%c",chBuf[i]);
printf("'n");
}
if (! fSuccess && GetLastError() != ERROR_MORE_DATA)
{
printf("Can't Read'n");
if(Finished)
break;
}
}
}
下面是 C# 部分(客户端):
private Thread vikeyClientThread;
public void ThreadStartClient()
{
Console.WriteLine("Thread client started ID ={0} name = {1} " ,
Thread.CurrentThread.ManagedThreadId,Thread.CurrentThread.Name);
using (NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", "vikeyP"))
{
// The connect function will indefinately wait for the pipe to become available
// If that is not acceptable specify a maximum waiting time (in ms)
Console.WriteLine("Connecting to ViKEY server...");
pipeStream.Connect();
Console.WriteLine("Connected :)");
//Write from client to server
StreamWriter sw = new StreamWriter(pipeStream);
while (true)
{
//Read server reply
StreamReader sr = new StreamReader(pipeStream);
string temp = "";
sw.WriteLine(System.DateTime.Now);
byte[] c = new byte[200];
temp = sr.ReadLine();
pipeStream.Read(c, 0, c.Length);
Console.WriteLine("RX =:{0}", Encoding.UTF8.GetString(c, 0, c.Length));
Thread.Sleep(500);
}
}
Console.WriteLine("Vikey pipe Closed");
Console.WriteLine("Thread with ID ={0} name = {1} is closed.",
Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.Name);
}
您已将服务器端设置为消息类型与字节类型。如果要读取任意数量的字节,则需要使用名为 pipe 的字节类型。
您将流包装在 2 个对象中,一个 StreamReader 和一个 StreamWriter。不要这样做,只需使用流。您正在尝试按行阅读,也不要这样做。而是发送要读取的字节数,后跟字节数。在客户端,您将读取字节计数,然后创建一个足够大的缓冲区,然后读取。如果是文本数据,则可以使用编码器(可能是 ASCII)将其转换回 C# 字符串。
您的 while(true) 应该改为检测服务器何时关闭管道。
您可能应该考虑使用异步命名管道。