c#命名管道双向通信
Posted
技术标签:
【中文标题】c#命名管道双向通信【英文标题】:c# named pipe two way communcation 【发布时间】:2016-02-20 13:05:41 【问题描述】:我有两个用 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);
【问题讨论】:
发生了什么?错误在哪里?你期望会发生什么,反而会发生什么?发生了哪些控制台输出? @misha130 在 C# 控制台中它应该打印“hello”,在 C++ 控制台中它应该发送当前日期和时间。 你试过'c++ to c++'还是'c# to c#'?可能,使用不同的语言不是问题... @dieter 跨语言使用管道没有问题。我已经完成了,没有问题。 【参考方案1】:您已将服务器端设置为消息类型与字节类型。如果要读取任意数量的字节,则需要使用名为管道的字节类型。
您将流包装在 2 个对象中,一个 StreamReader 和一个 StreamWriter。不要那样做,只需使用 Stream。您正在尝试逐行阅读,也不要这样做。而是发送要读取的字节数,后跟字节。在客户端,您将读取字节数,然后创建一个足够大的缓冲区然后读取。如果它是文本数据,那么您将使用编码器(可能是 ASCII)将其转换回 C# 字符串。
您的 while(true) 应该检测服务器何时关闭管道。
您可能应该考虑使用异步命名管道。
【讨论】:
以上是关于c#命名管道双向通信的主要内容,如果未能解决你的问题,请参考以下文章