I am trying to have a 2-way communication between a VC++ 6 app and a C# app. I am using named pipes. In my C++ code I can read the message from the C# client but then the server "dies" and I have to restart it again.
What I want to do is have the C# app connect to the C++ app, request a status, and the C++ app goes off and checks the status, and then returns either "busy" or "idle".
I can't write anything back to the C# client as it says the connection has been closed. Some things I have commented out are things I have tried already.
C++ code (started as a thread)
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# Code:
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();
}
}
}
Generally speaking, the charging speed of USB C to C is faster than that of USB A 2.0 to USB C, but the charging speed of USB C to C is compared with that of USB A 3.0 to USB C. It depends on the interface protocol. The maximum USB interface power is 100W, but USB 3.1 Gen2 is required to achieve this data.
"Full-featured" USB C to USB C cable This cable is best for charging USB C devices as well as data transfer. It is NOT meant to be used as a DisplayPort or to connect any other type of display receptacle.
Type C is smaller, a little oblong, and symmetrical. One major difference is Type C connectors are the same on both sides, so they are reversible. This means, that there is no 'this side up' with C-Type cables. This is not the case with Type A.
Disposing of a StreamWriter
or StreamReader
will close the underlying stream.
Your using statements therefore will be causing the stream to close.
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);
}
}
It should also be noted that because you wrap your stream in a using statement, the commented out pipeStream.Close()
function isn't needed.
Ok, got it working for my application .... thanks Blam !
Here's the C++ server (run this inside a thread):
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;
}
And here's the C# client:
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);
}
}
I'm not actually sending anything from the client to the server because I don't need to ... the key thing in this was the PIPE_WAIT parameter in the CreateNamedPipe() function. This makes the server wait for a client connection.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With