I am noobie in IPC. I am trying to send the Image Frame from my C++ Server to C# Client. I have start learning about that and make a small Client and Server that In which my C++ Server sends Hello. I saw a related question and someone told to first convert the Image into Byte Array and then send that in same way as Hello Message but I am not able to do that.
My Basic Client Server Code
C++ Code:
Mat image = imread("IMG_0_10_34_45_2018_1.bmp");
uchar buffer[500][500];
for (int i = 0; i < image.rows; i++)
{
for (int j = 0; j < image.cols; j++)
{
buffer[i][j] = image.at<unsigned char>(i, j);
}
}
cout << "Server Creating Pipe\n";
HANDLE hPipe = ::CreateNamedPipe(_T("\\\\.\\pipe\\HyperPipe"),
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
PIPE_UNLIMITED_INSTANCES,
4096,
4096,
0,
NULL);
cout << "Server Created Succesfully";
ConnectNamedPipe(hPipe, NULL);
cout << "Sending Message to Client";
DWORD bytesWritten = 0;
WriteFile(hPipe, buffer, sizeof(buffer) * sizeof(uchar), &bytesWritten, NULL);
CloseHandle(hPipe);
return 0;
And C# Code:
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();
}
I also noticed that in my C++ Server I have to change the PIPE_TYPE to BYTE and also READMODE to BYTE. I am using OpenCV library for Image Processing so I can easily make Byte Array no issue with that.
So, Can Anyone Please tell me how to send that Byte Array from C++ to C#.
Or if possible that anyone can provide me the code for that
Thanks in Advance
Update:
No error is coming but at the client side i.e C# Side the the output of Message from Server is ????? .
To Send the Byte Array from Server to Client i.e the buffer just small changes in the WriteFile function is required.
WriteFile(hPipe, buffer, sizeof(buffer) * sizeof(uchar), &bytesWritten, NULL);
This method will send whole Byte Array to the Client
And also changing the buffer
int _count = 0;
UINT8 _imageBuffer[110592];
for (int _imageRow = 0; _imageRow < _image.rows; _imageRow++)
{
for (int _imageCol = 0; _imageCol < _image.cols; _imageCol++)
{
buffer[_count] = image.at<uchar>(_imageRow, _imageCol);
_count++;
}
}
I have hardCode the buffer Array because I known that my camera will only send 110592 byte to create one frame.
And On the Client Side just use Read function.
int _imageRowSize = 288;
int _imageColSize = 384;
int _count = 0;
byte[] buffer = new byte[_imageColSize * _imageRowSize];
Image<Gray, UInt16> image = new Image<Gray, UInt16>(_imageColSize,_imageRowSize);
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 (MemoryStream ms = new MemoryStream())
{
while (true)
{
_count = 0;
int read = pipe.Read(buffer, 0, buffer.Length);
for (int _imageRow = 0; _imageRow < 288; _imageRow++)
{
for (int _imageCol = 0; _imageCol < 384; _imageCol++)
{
try
{
image.Data[_imageRow, _imageCol, 0] = (UInt16)(buffer[_count] * 255);
}catch(Exception exception)
{
Console.WriteLine(exception);
}
_count++;
}
}
if (read <= 0)
break;
ms.Write(buffer, 0, read);
}
}
CvInvoke.Imshow("Image", image);
}
Related
I have a wpf gui that I want to upload files from and send to a C client .
I want to send 3 files and for some reason 1 of them is being sent and written (but it adds 8 nulls in the end and removes 4 of the first letters in the file)
and in the other two when I try to receive the size it says their size is 0
I've been stuck on this problem for a while now and i'm becoming depserate as i'm probably missing a small thing , if any of u could give a hand that'll mean a lot ! I really wanna know whats the problem in my code.
I have the files paths in an array and sending it in main like so
C# Main
IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5555);//switch the port
Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listenSocket.Bind(ipPoint);
listenSocket.Listen(1);
Socket clientSocket = listenSocket.Accept();
for (int i = 0; i < 1; i++)
{
SendFile(clientSocket, filePaths[i]);
}
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
SendFile(C# side)
public static void SendFile(Socket clientSocket, string filePath)
{
if (File.Exists(filePath))
{
FileInfo fi = new FileInfo(filePath);
long file_size = fi.Length;
byte[] preBuffer;
using (var memoryStream = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(memoryStream))
{
writer.Write(file_size);
}
preBuffer = memoryStream.ToArray();
byte[] fixedBuffer = new byte[4];
Array.Copy(preBuffer, 0, fixedBuffer, 0, 4);
Console.WriteLine(BitConverter.ToString(preBuffer));
Console.WriteLine(BitConverter.ToString(fixedBuffer)); //fixing the problem i had with the converting to array that it added 4 useless zeros.
clientSocket.Send(fixedBuffer); // sending size
}
byte[] data = new Byte[4096];
using (FileStream fs = new FileStream(filePath, FileMode.Open))
{
int actualRead;
do
{
actualRead = fs.Read(data, 0, data.Length);
clientSocket.Send(data);
file_size -= actualRead;
} while (file_size - filePath.Length > 0);
}
}
else
{
MessageBox.Show("File for the program is missing! lua/pcap/csv");
}
}
C Receive(built from 3 functions)
/*
============================================
General : function is responsible for receiving a length of data from the client
Parameters : sock - client socket to receive the data from
*buf - holds a pointer to the buffer that needs to update
bufsize - the length of the buffer
Return Value : returns TRUE when the data is read correctly
else, FALSE when there was a socket error or no bytes are received.
============================================
*/
bool recv_raw(SOCKET sock, void* buf, int bufsize)
{
unsigned char* pbuf = (unsigned char*)buf;
while (bufsize > 0) {
int num = recv(sock, pbuf, bufsize, 0);
if (num <= 0) { return false; }
pbuf += num;
bufsize -= num;
}
return true;
}
/*
===================================================
General : receives the length of the file and updates it
Parameters : sock - client socket to receive the data from
*filesize - holds a pointer to the size of the buffer that needs to update
filesize_len - the length of the file size pointer
Return Value : returns TRUE when the size is read correctly
else, FALSE when there was a socket error or no bytes are received.
===================================================
*/
bool recv_file_len(SOCKET sock, long* filesize)
{
if (!recv_raw(sock, filesize, sizeof(*filesize))) { return false; }
return true;
}
/*
================================================== =
General : writes to the lua file the data from the file
that was received in the socket
Parameters : sock - the socket between the client and server
*f - the file to write the data received to
Return Value : returns TRUE when everything was written to the file.
returns FALSE if there's no data received or detected a socket problem.
================================================== =
*/
bool write_data(SOCKET sock, FILE *f)
{
long filesize;//size of address
char buffer[BUFFER_SIZE];
if (!recv_file_len(sock, &filesize)) { return false; }
printf("file size (From C#) : %ld\n", filesize);
int n = recv_raw(sock, buffer, 8); // need to get the size of the name
if (filesize > 0)
{
do {
int num = min(filesize, BUFFER_SIZE);
if (!recv_raw(sock, buffer, num)) {
return false;
}
int offset = 0;
do
{
size_t written = fwrite(&buffer[offset], 1, num - offset, f);
if (written < 1) { return false; }
offset += written;
} while (offset < num);
filesize -= num;
} while (filesize > 0);
}
return true;
}
C Main
FILE* luafhandler = fopen("test.lua", "wb");//the new lua file
if (luafhandler == NULL)
{
fclose(luafhandler);
printf("GUI CONNECT lua file failed to open!\n");
}
FILE* pcapfhandler = fopen("test.pcap", "wb");//the new lua file
if (pcapfhandler == NULL)
{
fclose(pcapfhandler);
printf("GUI CONNECT pcap file failed to open!\n");
}
FILE* csvfhandler = fopen("AlgoTest.csv", "wb");//the new lua file
if (csvfhandler == NULL)
{
fclose(csvfhandler);
printf("GUI CONNECT csv file failed to open!\n");
}
else {
SOCKET sock1 = open_socket(5555, SERVER_IP);
bool check = write_data(sock1, luafhandler);
bool check1 = write_data(sock1, pcapfhandler);
bool check2 = write_data(sock1, csvfhandler);
fclose(luafhandler);
fclose(pcapfhandler);
fclose(csvfhandler);
}
I am writing a simple Tcp communication programs using TcpListener and TcpClient , .Net 4.7.1
I designed my own protocol to be:
For each "data unit", the first 4 bytes is an int, indicating the length of data body. Once a complete "data unit" is received, the data body (as a byte[]) is passed to upper level.
My read and write functions are:
public static byte[] ReadBytes(Stream SocketStream)
{
int numBytesToRead = 4, numBytesRead = 0, n;
byte[] Length = new byte[4];
do
{
n = SocketStream.Read(Length, numBytesRead, numBytesToRead);
numBytesRead += n;
numBytesToRead -= n;
} while (numBytesToRead > 0 && n != 0);
if (n == 0) return null; //network error
if (!BitConverter.IsLittleEndian) Array.Reverse(Length);
numBytesToRead = BitConverter.ToInt32(Length, 0); //get the data body length
numBytesRead = 0;
byte[] Data = new byte[numBytesToRead];
do
{
n = SocketStream.Read(Data, numBytesRead, numBytesToRead);
numBytesRead += n;
numBytesToRead -= n;
} while (numBytesToRead > 0 && n != 0);
if (n == 0) return null; //network error
return Data;
}
public static void SendBytes(Stream SocketStream, byte[] Data)
{
byte[] Length = BitConverter.GetBytes(Data.Length);
if (!BitConverter.IsLittleEndian) Array.Reverse(Length);
SocketStream.Write(Length, 0, Length.Length);
SocketStream.Write(Data, 0, Data.Length);
SocketStream.Flush();
}
And I made a simple echo program to test the RTT:
private void EchoServer()
{
var Listener = new TcpListener(System.Net.IPAddress.Any, 23456);
Listener.Start();
var ClientSocket = Listener.AcceptTcpClient();
var SW = new System.Diagnostics.Stopwatch();
var S = ClientSocket.GetStream();
var Data = new byte[1];
Data[0] = 0x01;
Thread.Sleep(2000);
SW.Restart();
SendBytes(S, Data); //send the PING signal
ReadBytes(S); //this method blocks until signal received from client
//System.Diagnostics.Debug.WriteLine("Ping: " + SW.ElapsedMilliseconds);
Text = "Ping: " + SW.ElapsedMilliseconds;
SW.Stop();
}
private void EchoClient()
{
var ClientSocket = new TcpClient();
ClientSocket.Connect("serverIP.com", 23456);
var S = ClientSocket.GetStream();
var R = ReadBytes(S); //wait for PING signal from server
SendBytes(S, R); //response immediately
}
In "ReadBytes", I have to read 4 bytes from the NetworkStream first in order to know how many bytes I have to read next. So in total I have to call NetworkStream.Read twice, as shown in above codes.
The problem is: I discovered that calling it twice resulted in around 110ms RTT. While calling it once(regardless of data completeness) is only around 2~10ms(put a "return Length;" immediately after the first do-while loop, or comment out the first do-while loop and hard-code the data length, or read as much as it can in one call to "Read").
If I go for the "read as much as it can in one call" method, it may result in "over-read" of data and I have to write more lines to handle the over-read data to assemble next "data unit" correctly.
Anyone knows what's the cause of the almost 50 times overhead?
As I read from Micrisoft
Microsoft improved the performance of all streams in the .NET Framework by including a built-in buffer.
so even if I call .Read twice, it's only reading from memory, am I correct?
(if you want to test the codes, please do it on a real server and connect from your home PC maybe, do it in localhost always returns 0ms)
Thanks for Jeroen Mostert's comment reminder. I added:
ClientSocket.NoDelay = true;
ClientSocket.Client.NoDelay = true;
to both the client and server side and the annoying delay is gone, the RTT is back to expected.
TcpClient.NoDelay Property
Further tests showed that both sides(client and server) contributed around 50ms delay without modifying "NoDelay" option, so in total around 100ms RTT "overhead".
I am working on a software that transfers multiple files between different computers but i am faced with the problem of concurrency. When both threads start sending using Task.Run() the bytes mumble up on the receiving side i.e the data clashes together. I have tried locking every possible part of my code that could cause the error all to no avail. This is part of my code.
//code to transfer asynchronously
public void StartTransferAsync(Socket socket)
{
Task.Factory.StartNew(() =>
{
lock (this)
{
uploader = new Uploader(this, socket);
uploader.Upload();
}
});
}
//code to receive the asynchronous files coming in
public byte[] DownloadData()
{
int total = 0;
int recv = 0;
int size = 0;
int dataleft = 0;
byte[] data;
byte[] dataSize = new byte[4];
recv = socket.Receive(dataSize, 0, 4, 0);
size = BitConverter.ToInt32(dataSize, 0);
Console.WriteLine($"Size received: {size}");
if (size > 100038)
{
Console.WriteLine("Shii here");
}
dataleft = size;
data = new byte[size];
while (total < size)
{
recv = socket.Receive(data, total, dataleft, 0);
total += recv;
dataleft -= recv;
}
return data;
}
Please help i really need this.
My application works with some peripheral device. I must receive array of bytes from COM-port. Below are the snippets of code executing synchronously from my application:
// COM-port used.
private SerialPort _serialPort;
// Buffer for bytes received from COM-port.
private Byte[] _inputOutputBuffer;
// Buffer for instances of Point.
private List<Point> _linePoints = new List<Point>();
This method prepairs COM-port to work.
// Prepaires COM-port.
void PrepareComPort()
{
if (this._serialPort == null)
this._serialPort = new SerialPort(this.SelectedAvailableComPortsName);
this._serialPort.BaudRate = 115200;
this._serialPort.Parity = Parity.None;
this._serialPort.DataBits = 8;
this._serialPort.StopBits = StopBits.One;
this._serialPort.Handshake = Handshake.None;
this._serialPort.ReadTimeout = SerialPort.InfiniteTimeout
this._serialPort.WriteTimeout = 1000;
if (!this._serialPort.IsOpen)
this._serialPort.Open();
}
This method gets array of bytes via COM-port.
// Gets bytes from device via COM-port.
void recieveBytesFromDevice()
{
// Get bytes array at whole from COM-port.
while (this._serialPort.BytesToRead < 4006) { ; }
this._inputOutputBuffer = new Byte[this._serialPort.BytesToRead];
this._serialPort.Read(this._inputOutputBuffer, offset: 0, count: this._serialPort.BytesToRead);
}
This method fills the list of instances of Point.
// Fills list of instances of Point.
void FillPointsList()
{
for (int i = 0, j = 0; i <= this._inputOutputBuffer.Length - 8; i++)
{
Int16 shortValue = 0;
if (i % 2 == 0)
{
Byte[] bytes = new Byte[] { this._inputOutputBuffer[i], this._inputOutputBuffer[i + 1] };
Array.Reverse(bytes);
shortValue = BitConverter.ToInt16(bytes, startIndex: 0);
_linePoints.Add(new Point(j, shortValue));
j++;
}
}
}
My application sends data request via COM-port to the peripheral device and the peripheral device always send just 4006 bytes as a reply which my application must receive. If the peripheral device sends 4006 bytes without any delay than the application works good. But when the peripheral device has some delay before sending of 4006 bytes than my application hangs. How to realize aforementioned PrepareComPort and FillPointsList methods as one method for asynchronous work using await async?
I made a client & server that establishes a TCP connection through sockets, I'm trying to send binary data over the socket but I could only send txt or pdf files, I had no luck with exe files, I use fread and fseek to read the file and split it into a buffer. When I read the whole exe file it gets sent successfully but when I split it, it gets sent corrupted!
I read some books about sockets but I still don't know much and I have some questions.
is it okay to send the whole file in one send()?? or I should continue with sending it in small chunks?
Also, why exe files get corrupted when I send them in chunks?
Thank you!
Client Code (in c):
int bufSize = 10000;
int sentBytes = 0;
FILE * pFile;
long remainingBytes;
char * buffer;
size_t result;
pFile = fopen ( "D:\\file.exe" , "rb" );
fseek (pFile , 0 , SEEK_END);
remainingBytes = ftell (pFile);
rewind (pFile);
int bufferSize = remainingBytes > bufSize ? bufSize : remainingBytes;
buffer = (char*) malloc (sizeof(char)*bufferSize);
send(Socket, (char*)&remainingBytes, 4, 0);
while(remainingBytes > 0)
{
fseek (pFile , sentBytes , SEEK_SET);
result = fread(buffer,1,bufferSize,pFile);
if(bufferSize < remainingBytes)
{
send(Socket, buffer, bufferSize, 0);
}
else
{
send(Socket, buffer, remainingBytes, 0);
bufferSize = remainingBytes;
}
remainingBytes -= bufferSize;
sentBytes += bufferSize;
}
Server code (in c#)
try
{
int bufferSize = 200;
int len = 0;
int receivedBytes = 0;
int remainingBytes = len;
byte[] length = new byte[4];
//byte[] imgBuf = new byte[bufferSize];
int current = 0;
List<byte[]> coming = new List<byte[]>();
sockets[number].Receive(length,4,0);
len = BitConverter.ToInt32(length, 0);
remainingBytes = len;
bufferSize = len < bufferSize ? len : bufferSize;
while(receivedBytes < len)
{
if (remainingBytes > bufferSize)
{
coming.Add(new byte[bufferSize]);
//imgBuf = new byte[bufferSize];
sockets[number].Receive(coming[current], bufferSize, 0);
}
else
{
coming.Add(new byte[remainingBytes]);
//imgBuf = new byte[remainingBytes];
sockets[number].Receive(coming[current], remainingBytes, 0);
bufferSize = remainingBytes;
}
remainingBytes -= bufferSize;
receivedBytes += bufferSize;
current++;
//Array.Clear(imgBuf, 0, imgBuf.Length);
}
using (var stream = new FileStream(#"C:\receivedFile.exe",FileMode.Create))
{
using (var binaryWriter = new BinaryWriter(stream))
{
foreach (byte[] buffer in coming)
{
binaryWriter.Write(buffer);
}
}
}
}
catch (Exception ex)
{ this.setText(ex.Message, textBox2); }
Edit: Thanks for the help, I got it working :)
try
{
int bufferSize = 1024 * 100;
int len = 0;
int receivedBytes = 0;
int remainingBytes = len;
int reached = 0;
byte[] length = new byte[4];
byte[] imgBuf = new byte[bufferSize];
int current = 0;
sockets[number].Receive(length,4,0);
len = BitConverter.ToInt32(length, 0);
remainingBytes = len;
bufferSize = len < bufferSize ? len : bufferSize;
imgBuf = new byte[len];
while (reached < len)
{
reached += sockets[number].Receive(imgBuf, receivedBytes, remainingBytes, 0);
remainingBytes = len - reached;
receivedBytes = reached;
current++;
//Array.Clear(imgBuf, 0, imgBuf.Length);
}
using (var stream = new FileStream(#"C:\putty.exe",FileMode.Create))
{
using (var binaryWriter = new BinaryWriter(stream))
{
binaryWriter.Write(imgBuf);
}
}
Array.Clear(imgBuf, 0, imgBuf.Length);
}
catch (Exception ex)
{ this.setText(ex.Message, textBox2); }
You don't check how many bytes you actually received in sockets[number].Receive(coming[current], bufferSize, 0); . It doesn't have to be equal to the buffer size you have declared.
Additionaly, as said in comments, keeping whole file in memory is not a good idea.
In addition to checking the number of bytes received, you need to check the number of bytes sent by each send call -- if your TCP transmit window fills up, a send call might send less data than you requested, in which case the you'll need to resend the unsent data.
In general, you ALWAYS need to check the return value of your system calls to check for the all the various odd corner cases that can occur. Read the man pages for send(2) and recv(2) for a full list of everything that can happen.