C#c ++命名管道连接

时间:2016-06-14 20:26:37

标签: c# c++ named-pipes

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

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

方面问题:我不明白在管道名称之前使用“\\。\ pipe \”。它做了什么,它确实是必要的?

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

C#server:

Program.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 ++中只是在控制台中继续打印“尝试”

1 个答案:

答案 0 :(得分: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#app以启动服务器的示例

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";
}