使用命名管道的两种 C++ 到 C# 通信
Posted
技术标签:
【中文标题】使用命名管道的两种 C++ 到 C# 通信【英文标题】:Two way C++ to C# communication using named pipes 【发布时间】:2012-05-24 15:22:24 【问题描述】:我正在尝试在 VC++ 6 应用程序和 C# 应用程序之间进行双向通信。我正在使用命名管道。在我的 C++ 代码中,我可以从 C# 客户端读取消息,但随后服务器“死机”,我必须再次重新启动它。
我想做的是让 C# 应用程序连接到 C++ 应用程序,请求状态,然后 C++ 应用程序关闭并检查状态,然后返回“忙碌”或“空闲”。
我无法将任何内容写回 C# 客户端,因为它说连接已关闭。我注释掉的一些东西是我已经尝试过的。
C++ 代码(作为线程启动)
UINT CNamedPipe::StartNamedPipeServer()
LPTSTR lpszPipename = "\\\\.\\pipe\\SAPipe";
HANDLE hPipe;
BOOL flg;
DWORD dwWrite,dwRead;
char szServerUpdate[200];
char szClientUpdate[200];
hPipe = CreateNamedPipe ( lpszPipename,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE |
PIPE_READMODE_MESSAGE |
PIPE_NOWAIT, //changed from nowait
PIPE_UNLIMITED_INSTANCES, // max. instances
BUFSIZE, // output buffer size
BUFSIZE, // input buffer size
PIPE_TIMEOUT, // client time-out
NULL); // no security attribute
if (hPipe == INVALID_HANDLE_VALUE)
return 0;
ConnectNamedPipe(hPipe, NULL);
while(m_bServerActive) //This seems to work well ....
//Read from client
flg = ReadFile(hPipe,szClientUpdate,strlen(szClientUpdate),&dwRead, NULL);
if(flg) //Read something from the client!!!!
CString csMsg,csTmp;
for(int i=0;i<dwRead;i++)
csTmp.Format("%c",szClientUpdate[i]);
csMsg += csTmp;
AfxMessageBox("Client message: " + csMsg);
strcpy( szServerUpdate,"busy");
//Write status to Client
flg = WriteFile(hPipe, szServerUpdate, strlen(szServerUpdate), &dwWrite, NULL);
EndServer();
StartServer();
return 0;
C#代码:
public void ThreadStartClient(object obj)
// Ensure that we only start the client after the server has created the pipe
ManualResetEvent SyncClientServer = (ManualResetEvent)obj;
// Only continue after the server was created -- otherwise we just fail badly
// SyncClientServer.WaitOne();
using (NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", "SAPipe"))
// The connect function will indefinately wait for the pipe to become available
// If that is not acceptable specify a maximum waiting time (in ms)
pipeStream.Connect();
//Write from client to server
using (StreamWriter sw = new StreamWriter(pipeStream))
sw.WriteLine("What's your status?");
//Read server reply
/*using (StreamReader sr = new StreamReader(pipeStream))
string temp = "";
temp = sr.ReadLine(); //Pipe is already closed here ... why?
MessageBox.Show(temp);
*/
//pipeStream.Close();
【问题讨论】:
【参考方案1】:处理StreamWriter
或StreamReader
将关闭底层流。
因此,您的 using 语句将导致流关闭。
public void ThreadStartClient(object obj)
// Ensure that we only start the client after the server has created the pipe
ManualResetEvent SyncClientServer = (ManualResetEvent)obj;
// Only continue after the server was created -- otherwise we just fail badly
// SyncClientServer.WaitOne();
using (NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", "SAPipe"))
// The connect function will indefinately wait for the pipe to become available
// If that is not acceptable specify a maximum waiting time (in ms)
pipeStream.Connect();
//Write from client to server
StreamWriter sw = new StreamWriter(pipeStream))
sw.WriteLine("What's your status?");
//Read server reply
StreamReader sr = new StreamReader(pipeStream)
string temp = "";
temp = sr.ReadLine(); //Pipe is already closed here ... why?
MessageBox.Show(temp);
还应注意,由于您将流包装在 using 语句中,因此不需要注释掉的 pipeStream.Close()
函数。
【讨论】:
谢谢,帮助很大。我将更改我的代码,看看会发生什么。您可能已经猜到了,我是 C# 新手。 没问题,记得点选票下的勾,这样你的支持率会更高!【参考方案2】:好的,让它适用于我的应用程序......谢谢 Blam!
这是 C++ 服务器(在线程中运行):
UINT CNamedPipe::StartNamedPipeServer()
if(!m_bServerActive)
return 0;
LPTSTR lpszPipename = "\\\\.\\pipe\\MyPipe";
HANDLE hPipe;
BOOL flg;
DWORD dwWrite,dwRead;
char szServerUpdate[200];
char szClientUpdate[200];
hPipe = CreateNamedPipe ( lpszPipename,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE |
PIPE_READMODE_MESSAGE |
PIPE_WAIT, //HAS TO BE THIS
PIPE_UNLIMITED_INSTANCES, // max. instances
BUFSIZE, // output buffer size
BUFSIZE, // input buffer size
PIPE_TIMEOUT, // client time-out
NULL); // no security attribute
if (hPipe == INVALID_HANDLE_VALUE)
return 0;
ConnectNamedPipe(hPipe, NULL);
strcpy( szServerUpdate,"busy");
//Write status to Client
flg = WriteFile(hPipe, szServerUpdate, strlen(szServerUpdate), &dwWrite, NULL);
EndServer();
StartServer();
return 0;
这是 C# 客户端:
public void ThreadStartClient(object obj)
// Ensure that we only start the client after the server has created the pipe
ManualResetEvent SyncClientServer = (ManualResetEvent)obj;
using (NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", "MyPipe", PipeDirection.InOut))
// The connect function will indefinately wait for the pipe to become available
// If that is not acceptable specify a maximum waiting time (in ms)
pipeStream.Connect();
if (!pipeStream.IsConnected) //It thinks it's connected but can't read anything ....
MessageBox.Show("Failed to connect ....");
return;
//Read server reply
StreamReader sr = new StreamReader(pipeStream);
char[] c = new char[200];
while (sr.Peek() >= 0)
sr.Read(c, 0, c.Length);
string s = new string(c);
MessageBox.Show(s);
我实际上并没有从客户端向服务器发送任何内容,因为我不需要...其中的关键是 CreateNamedPipe() 函数中的 PIPE_WAIT 参数。这使服务器等待客户端连接。
【讨论】:
以上是关于使用命名管道的两种 C++ 到 C# 通信的主要内容,如果未能解决你的问题,请参考以下文章