简体   繁体   English

C#C ++命名管道连接

[英]C# c++ named pipes connection

I am trying to connect ac# project with a c++ project using named pipes but the c++ project doesn't connect. 我正在尝试使用命名管道将ac#项目与c ++项目连接,但是c ++项目无法连接。

ps: the .exe are both in the same file ps:.exe都在同一个文件中

side question: i don't understand the use of "\\\\.\\pipe\\" before my pipe name. 旁边的问题:我不知道在管道名称之前使用“ \\\\。\\ pipe \\”。 what does it do and it is really necesarry? 它是做什么的,真的是必需品吗?

Here's the my code maybe you can spot the error 这是我的代码,也许您可​​以发现错误

C# server: C#服务器:

Program.cs 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: 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++ client 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);

} }

Running the program just gives this exception in C# 运行程序只是在C#中给出了此异常

************** Exception Text ************** System.InvalidOperationException: Pipe hasn't been connected yet. **************异常文本************** System.InvalidOperationException:管道尚未连接。 .... .... .... .... .... ....

and in c++ just keeps printing "trying" in console 并且在c ++中,始终在控制台中打印“ trying”

When you call CreateFile how does CreateFile know that the object represented by the string myNamedPipe1 is a pipe? 当您调用CreateFile时, CreateFile如何知道由字符串myNamedPipe1表示的对象是管道? It knows because the name was prefixed with \\\\ServerName\\pipe\\ . 它知道,因为该名称以\\\\ServerName\\pipe\\为前缀。

In your case ServerName can just be . 就您而言, ServerName可以是. because that is a shortcut for "This machine", if you switch your code to LPTSTR pipeName = TEXT("\\\\\\\\.\\\\pipe\\\\myNamedPipe1"); 因为这是“本机”的快捷方式,所以如果您将代码切换到LPTSTR pipeName = TEXT("\\\\\\\\.\\\\pipe\\\\myNamedPipe1"); it should start working if there are no other issues. 如果没有其他问题,它应该开始工作。

you don't need to put it there in the C# code because the NamedPipeServerStream class puts it there for you . 您不需要将其放在C#代码中,因为NamedPipeServerStream为您放置了它

EDIT: Looking over your code, you may want to move pipeServer = new NamedPipeServerStream("myNamedPipe1"); 编辑:查看您的代码,您可能想要移动pipeServer = new NamedPipeServerStream("myNamedPipe1"); to the constructor of pipeHandler , right now your C++ program may start up before the server is ever started, even if you had the correct name you still might get the error. 对于pipeHandler的构造pipeHandler ,现在即使您使用正确的名称,您的C ++程序也可能在服务器启动之前启动,即使您仍然使用正确的名称,也可能会收到错误消息。

EDIT2: ConnectNamedPipe is the C++ equivalent of pipeServer.WaitForConnection(); 编辑2: ConnectNamedPipepipeServer.WaitForConnection();的C ++等效项pipeServer.WaitForConnection(); , you should not be doing that if the C++ program is the client. ,如果C ++程序是客户端,则不应这样做。 You should be good to go reading and writing as soon as you have a valid handle from CreateFile 只要拥有CreateFile的有效句柄,就应该开始阅读和写作。

EDIT3: here is a example of how to rewrite the C# app to start the server up before starting the C++ app 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);
    }
 ...
}

Then in your C++ code delete 然后在您的C ++代码中删除

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM