I have learned about Named Pipe and try to send the message from C++ and C# application and it works fine. But I am not able to send the image from C++ side to C# using Named Pipe. Can anyone please tell me how I can do this.
My C# Code for Named Pipe
static void Main(string[] args)
{
Console.WriteLine("Creating Client Pipe");
NamedPipeClientStream pipe = new NamedPipeClientStream(".", "HyperPipe", PipeDirection.InOut);
Console.WriteLine("Pipe Created Successfully, Connecting to Server");
pipe.Connect();
Console.WriteLine("Successfully, Connected to Server");
using (StreamReader rdr = new StreamReader(pipe, Encoding.Unicode))
{
System.Console.WriteLine("Message from Server: " + rdr.ReadToEnd());
}
Console.ReadKey();
}
and C++ Code
int _tmain(int argc, _TCHAR* argv[])
{
cout << "Server Creating Pipe\n";
HANDLE hPipe = ::CreateNamedPipe(_T("\\\\.\\pipe\\HyperPipe"),
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
PIPE_UNLIMITED_INSTANCES,
4096,
4096,
0,
NULL);
cout << "Server Created Succesfully";
ConnectNamedPipe(hPipe, NULL);
LPTSTR data = _T("Hello");
cout << "Sending Message to Client";
DWORD bytesWritten = 0;
WriteFile(hPipe, data, _tcslen(data) * sizeof(TCHAR), &bytesWritten, NULL);
CloseHandle(hPipe);
return 0;
}
What I want is when the I enter the path on the C# side it will send that to C++ and using OpenCV library I will fetch that image from the memory and send to the C#.
Thanks in Advance
Have you tried converting your image to an array of bytes, and then sending it the same way you did with the text ?
Related
I have C# Client and C# Server Programs that connected with each other successfully and works fine. But when i want to connect C# Client with C++ server then C# client gets halted while C++ Server produces success messages of "winsock initialization success " and "creating socket success".
C++ Server Code
WSADATA wsaData;
struct sockaddr_in address_of_server;
struct sockaddr_in address_of_client;
int socket_of_client;
int size_of_address_of_client = sizeof(address_of_client);
if (WSAStartup(MAKEWORD(2, 2), &wsaData) == 0) {
printf("winsock initialization success\n");
}
else {
printf("winsock initialization failure\n");
}
SOCKET socket_of_server = socket(AF_INET, SOCK_STREAM, 0);
if (socket_of_server == -1) {
printf("creating socket failure\n");
}
else {
printf("creating socket success\n");
}
memset(&address_of_server, 0, sizeof(address_of_server));
address_of_server.sin_family = AF_INET;
//address_of_server.sin_family = PF_INET;
address_of_server.sin_addr.s_addr = htonl(INADDR_ANY);
address_of_server.sin_port = htons(8888);
bind(socket_of_server, (struct sockaddr*)&address_of_server, sizeof(address_of_server));
listen(socket_of_server, 5);
ClientSocket = accept(socket_of_server, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(socket_of_server);
WSACleanup();
return 1;
}
socket_of_client = accept(socket_of_server, (struct sockaddr*)&address_of_client, &size_of_address_of_client);
WSACleanup();
C# Client Code
public CCRMain()
{
InitializeComponent();
clientSocket.Connect("127.0.0.1", 8888);
}
void Data()
{
MainWindow mw = (MainWindow)Application.Current.MainWindow;
NetworkStream serverStream = mw.clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(A1G1.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
byte[] inStream = new byte[10025];
serverStream.Read(inStream, 0, (int)mw.clientSocket.ReceiveBufferSize);
System.IO.MemoryStream ms = new System.IO.MemoryStream(inStream);
System.IO.BinaryReader br = new System.IO.BinaryReader(ms);
int[] inComingData = new int[5];
for (int i = 0; i < 5; i++)
{
inComingData[i] = br.ReadInt32();
Debug.WriteLine(inComingData[i].ToString());
A1G1Text.Text = inComingData[0].ToString();
}
}
NetworkStream.Read() is blocking. So as long as the server does not close the connection, this will not return until 10025 bytes have been read.
You should directly read from the network stream, not copy it over twice (or even four times in your case: From network to inStream and then to a MemoryStream and then to inCommingData and then to your text variable).
Use the NetworkStream.ReadTimeout property to indicate that you want Read() to return even if not the entire buffer was filed within some time.
I'm fairly new to socket programming, but, using an online tutorial, I've successfully sent a short string from one machine to another using C.
The problem I'm having is with trying to send a string from a client written in C#. The server (written in C) prints out a blank/empty string.
Here is the C code that runs on the "server" machine (in this case a router running OpenWRT):
int main(int argc, char *argv[])
{
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
char recvBuff[1025];
int bytesRead;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(1234);
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
printf("Listening for string on port 1234...\n");
listen(listenfd, 10);
while(1)
{
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
bytesRead = recv(connfd, recvBuff, 1024, 0); // Receive string
if (bytesRead < 0)
{
printf("Error reading from stream\n");
}
recvBuff[bytesRead] = 0; // null-terminate the string
printf("%d:%s\n", bytesRead, recvBuff);
close(connfd);
sleep(1);
}
}
When sending this little server a string from another C program it works exactly as expected (prints the string out then waits for another one). [Note: I don't think the C client's code is relevant, but I can post it if need be]
However, when trying to send it a string from a C# program (copied below), the server prints out 0: (i.e. 0 bytes read, followed by an empty string) and I can't for the life of me figure out what the issue is. Both apps are pretty straightforward, so I'm assuming I should be using something other than WriteLine (I've also tried Write but to no avail).
C# Client:
namespace SocketTest
{
class Program
{
static void Main(string[] args)
{
TcpClient client = new TcpClient("10.45.13.220", 1234);
Stream stream = client.GetStream();
StreamWriter writer = new StreamWriter(stream);
writer.WriteLine("Testing...");
client.Close();
}
}
}
To null terminate a string use
recvBuff[bytesRead] = '\0';
And call close on writer (which causes the writer to flush any pending bytes)
writer.WriteLine("Testing...");
writer.Close();
client.Close();
I successfully made a WebSocket server in C# which I can connect to. I make the handshake as RFC 6455 requires it.
Whatever I send (via WebSocket.send()) to it (for example "asd") the stream only has 9 bytes of data which is "unrepresentable" by UTF8.
using System.Net.Sockets;
using System.Net;
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
class Server
{
public static void Main()
{
TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 80);
server.Start();
TcpClient client = server.AcceptTcpClient();
NetworkStream stream = client.GetStream();
Boolean isHandshaked = false;
while (true)
{
while (!stream.DataAvailable)
{
}
Byte[] bytes = new Byte[client.Available];
stream.Read(bytes, 0, bytes.Length);
if (!isHandshaked)
{
Byte[] response = Encoding.UTF8.GetBytes("HTTP/1.1 101 Switching Protocols" + Environment.NewLine
+ "Connection: Upgrade" + Environment.NewLine
+ "Upgrade: websocket" + Environment.NewLine
+ "Sec-WebSocket-Accept: " + Convert.ToBase64String(
SHA1.Create().ComputeHash(
Encoding.UTF8.GetBytes(
new Regex("Sec-WebSocket-Key: (.*)").Match(
Encoding.UTF8.GetString(bytes)
).Groups[1].Value.Trim() + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
)
)
) + Environment.NewLine
+ Environment.NewLine);
stream.Write(response, 0, response.Length);
isHandshaked = true;
}
else
{
Console.WriteLine(Encoding.UTF8.GetString(bytes));
}
}
}
}
Where I missed something?
Messages between client and server are not sent as plain text. See the data framing section of the standard for how to encode/decode them.
For your example of a client sending a 3 byte string, this will result in a message of
1 byte - 0x81 - saying that this is a non-fragmented text message
1 byte - 0x83 - saying that the message body is 3 bytes long and it's contents are masked (all client -> server messages use masking. server -> client messages must not be masked). The top bit (byte_val & 0x80) is set if a message is masked. The remaining 7 bits (byte_val & 0x7F) gives the length of the messages up to 125 bytes. See link below for how to determine the length of longer messages.
4 bytes - mask. Always 4 bytes. Content determined by the client and should change for each message
3 bytes - message. Can be decoded using the mask and algorithm in section 5.3 of the spec.
You can unmask a message using code like the following
byte mask[4];
byte[] msg_data;
// read message, initialising mask, msg_data
for (int i=0; i<msg_data.Length; i++)
{
msg_data[i] = msg_data[i] ^ mask[i%4]
}
If you need more detail, this previous post explains message sending/receiving and includes some helpful pseudo code.
Having an empty loop to check for data i.e. while (!stream.DataAvailable){} is really a bad practice that you can avoid.
The read method is a blocking method, so it will wait until the data is available
int bufferSize = 1024; // change it as you want
byte[] message = new byte[bufferSize];
readLength = stream.Read(message, 0, bufferSize);
You can try code below and see if it works, i suspect you are not reading full response.
byte[] buffer = new byte[4155];
int bytesRead = 0;
using (var input = client.GetStream())
{
while (true)
{
bytesRead = input.Read(buffer, 0, buffer.Length);
totalBytes += bytesRead;
if (bytesRead > 0)
// keep processing ur data here, add it to another buffer maybe
else
break; // come out of while loop if there is no data
}
}
}
I'am having some trouble to make a Duplex communication between a C# server and a C++ work:
The objective is to create the pipe, read something from the client and write something back.
Everything is working fine if i'm just reading from the client or just writing to the client but I can't do both one after the other!
Here's my C# server:
// Create a name pipe
using (NamedPipeServerStream pipeStream = new NamedPipeServerStream("TestPipe"))
{
Console.WriteLine("[Server] Pipe created {0}", pipeStream.GetHashCode());
// Wait for a connection
pipeStream.WaitForConnection();
Console.WriteLine("[Server] Pipe connection established");
//Reading Part
using (StreamReader sr = new StreamReader(pipeStream))
{
string temp;
while ((temp = sr.ReadLine()) != null)
{
Console.WriteLine("{0}: {1}", DateTime.Now, temp);
}
}
//Writing Part
using (StreamWriter sw = new StreamWriter(pipeStream))
{
sw.AutoFlush = true;
String st = "send Back\0";
sw.WriteLine(st);
}
}
And Here is the C++ client:
HANDLE hFile;
BOOL flg;
DWORD dwWrite;
char szPipeUpdate[200];
hFile = CreateFile(L"\\\\.\\pipe\\TestPipe", GENERIC_WRITE|GENERIC_READ,
0, NULL, OPEN_EXISTING,
0, NULL);
strcpy(szPipeUpdate,"Sending some data from client to server!");
if(hFile == INVALID_HANDLE_VALUE)
{
DWORD dw = GetLastError();
printf("CreateFile failed for Named Pipe client\n:" );
}
else
{
flg = WriteFile(hFile, szPipeUpdate, strlen(szPipeUpdate), &dwWrite, NULL);
if (FALSE == flg)
{
printf("WriteFile failed for Named Pipe client\n");
}
else
{
printf("WriteFile succeeded for Named Pipe client\n");
}
}
printf("Let's read!\n");
//Read the datas sent by the server
BOOL fFinishRead = FALSE;
do
{
char chResponse[200];
DWORD cbResponse, cbRead;
cbResponse = sizeof(chResponse);
fFinishRead = ReadFile(
hFile, // Handle of the pipe
chResponse, // Buffer to receive the reply
cbResponse, // Size of buffer in bytes
&cbRead, // Number of bytes read
NULL // Not overlapped
);
if (!fFinishRead && ERROR_MORE_DATA != GetLastError())
{
DWORD dwError = GetLastError();
wprintf(L"ReadFile from pipe failed w/err 0x%08lx\n", dwError);
break;
}
std::cout << chResponse;
} while (!fFinishRead); // Repeat loop if ERROR_MORE_DATA
CloseHandle(hFile);
With the Server & Client NamedPipeStreams you need to make sure at least one end of the connection is attempting to read at all times, otherwise writes will fail. I'd guess it's a timing issue between your client & server around whichever is listening/writing. Here's a quick blog post explaining this behavior as well.
I'd recomend using two streams on the client & server, both reading/writing from the same pipe.
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();
}
}
}
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.