【问题标题】:C# c++ named pipes connectionC# c++ 命名管道连接
【发布时间】:2016-06-14 20:26:36
【问题描述】:

我正在尝试使用命名管道将 c# 项目与 c++ 项目连接,但 c++ 项目未连接。

ps: .exe 都在同一个文件中

附带问题:我不明白在我的管道名称前使用“\\.\pipe\”。它有什么作用,真的有必要吗?

这是我的代码,也许你能发现错误

C# 服务器:

程序.cs

static class Program
{

    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        pipeHandler pipe = new pipeHandler();

        var proc = new Process();
        proc.StartInfo.FileName = "cplpltestpipes.exe";
        proc.Start();


        pipe.establishConnection();

        Application.Run(new Form1(pipe));
    }
}


public class pipeHandler
{

    private StreamReader re;
    private StreamWriter wr;
    private NamedPipeServerStream pipeServer;

    public void establishConnection()
    {
       pipeServer = new NamedPipeServerStream("myNamedPipe1");
        pipeServer.WaitForConnection();
        re = new StreamReader(pipeServer);
        wr = new StreamWriter(pipeServer);
    }

    public void writePipe(string text)
    {
        wr.Write(text);

    }

    public string readPipe()
    {
        if(re.Peek()==-1)
            System.Threading.Thread.Sleep(2000);
        if (re.Peek() > -1)
        {
            string s;
            s = re.ReadToEnd();
            return s;
        }
        else
            return "fail";
    }


}

Form1.cs:

public partial class Form1 : Form
{
    pipeHandler pipePointer;
    public Form1(pipeHandler pipe)
    {
        pipePointer=pipe;
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    private void button1_Click(object sender, EventArgs e)
    {
        pipePointer.writePipe(textBox1.Text);
        textBox2.Text = pipePointer.readPipe();
    }


}

c++ 客户端

#define chrSize 16

int main()
{
    TCHAR chr[chrSize];
    DWORD bytesRead;



HANDLE pipeHandler;
LPTSTR pipeName = TEXT("\\\\.\\pipe\\myNamedPipe1");


pipeHandler = CreateFile(
    pipeName,   // pipe name 
    GENERIC_READ |  // read and write access 
    GENERIC_WRITE,
    0,              // no sharing 
    NULL,           // default security attributes
    OPEN_EXISTING,  // opens existing pipe 
    0,              // default attributes 
    NULL);          // no template file 

bool flag=false;

while (!flag) 
{
    flag = ConnectNamedPipe(pipeHandler, NULL);
    cout << "trying";
}



ReadFile(
    pipeHandler,    // pipe handle 
    chr,    // buffer to receive reply 
    chrSize * sizeof(TCHAR),  // size of buffer 
    &bytesRead,  // number of bytes read 
    NULL);    // not overlapped 

cout << chr;


LPTSTR pipeMessage = TEXT("message receive");
DWORD bytesToWrite= (lstrlen(pipeMessage) + 1) * sizeof(TCHAR);
DWORD cbWritten;


WriteFile(
    pipeHandler,                  // pipe handle 
    pipeMessage,             // message 
    bytesToWrite,              // message length 
    &cbWritten,             // bytes written 
    NULL);                  // not overlapped 


CloseHandle(pipeHandler);

}

运行程序只会在 C# 中给出这个异常

**************异常文本************** System.InvalidOperationException:管道尚未连接。 …… …… ....

而在 c++ 中,只是在控制台中不断打印“正在尝试”

【问题讨论】:

标签: c# c++ named-pipes


【解决方案1】:

当您调用CreateFile 时,CreateFile 如何知道字符串myNamedPipe1 所代表的对象是管道?它知道是因为名称以\\ServerName\pipe\ 为前缀。

在您的情况下,ServerName 可以只是 .,因为这是“本机”的快捷方式,如果您将代码切换到 LPTSTR pipeName = TEXT("\\\\.\\pipe\\myNamedPipe1");,如果没有其他问题,它应该开始工作。

您不需要将它放在 C# 代码中,因为 NamedPipeServerStreamputs it there for you

编辑:查看您的代码,您可能希望将pipeServer = new NamedPipeServerStream("myNamedPipe1"); 移动到pipeHandler 的构造函数,现在您的C++ 程序可能在服务器启动之前启动,即使你有正确的名字你仍然可能得到错误。

EDIT2: ConnectNamedPipepipeServer.WaitForConnection(); 的 C++ 等价物,如果 C++ 程序是客户端,则不应这样做。只要您拥有来自CreateFile 的有效句柄,您就应该可以开始阅读和写作了

EDIT3:这是一个示例,说明如何在启动 C++ 应用程序之前重写 C# 应用程序以启动服务器

static class Program
{    
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        //The server now gets created here.
        pipeHandler pipe = new pipeHandler();    

        var proc = new Process();
        proc.StartInfo.FileName = "cplpltestpipes.exe";
        proc.Start();

        //The server used to be created here.
        pipe.EstablishConnection();

        Application.Run(new Form1(pipe));
    }
}


public class pipeHandler
{    
    private StreamReader re;
    private StreamWriter wr;
    private NamedPipeServerStream pipeServer;

    public pipeHandler()
    {
       //We now create the server in the constructor.
       pipeServer = new NamedPipeServerStream("myNamedPipe1");
    }

    public void establishConnection()
    {
        pipeServer.WaitForConnection();
        re = new StreamReader(pipeServer);
        wr = new StreamWriter(pipeServer);
    }
 ...
}

然后在你的 C++ 代码中删除

while (!flag) 
{
    flag = ConnectNamedPipe(pipeHandler, NULL);
    cout << "trying";
}

【讨论】:

  • 它不再出现连接错误,谢谢!但是现在c#应用程序冻结等待响应,c++应用程序无法读取和响应。如果您觉得大方,可以看看我的其余代码吗?提前谢谢你!
  • readPipe() 看起来超级古怪。摆脱所有偷看的东西,只需读取数据。除此之外,使用调试器并找出它在哪一行停止并提出一个新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-30
  • 1970-01-01
相关资源
最近更新 更多