I have a namedpipeServerStream and I want to stop Reading its pipe when I meet the timeout.
these are my Read and Read callback function , and I call Read in my main program loop repeatedly,
Actually my question is how can I call my callback function manually(or any other way)when timeout happened for endread.
private void Read()
{
tmpBuff = new byte[600];
inRead = true;
ReadTimer.Enabled = true;
len = 0;
try
{
_namedpipeserver.BeginRead(tmpBuff, 0, 600, ReadCallback, null);
}
catch (Exception ex) //disconnected/disposed
{
return;
}
}
static void ReadCallback(IAsyncResult ar)
{
int readbyte;
try
{
readbyte = _namedpipeserver.EndRead(ar);
if (readbyte > 0)
{
len = readbyte;
int packetLen = tmpBuff[0] + (tmpBuff[1] * 256);
Console.WriteLine(" packet len: " + packetLen + " bytes ");
readbyte = 0;
array = null;
array = new byte[packetLen];
Array.Copy(tmpBuff, 2, array, 0, packetLen);
}
}
catch (IOException) //closed
{
return;
}
inRead = false;
}
Any help Appreciated.Thanks
I resolved this problem by disposing connection after a defined timeout and waiting for other side of the pipe to connect again.
Task.Run(() =>
{
tmpBuff = new byte[600];
readbyte = _namedpipeserver.Read(tmpBuff, 0, 600);
}).Wait(10000);
if (readbyte <= 0)
return null;
In case null returned try to reinitiate pipe.
Related
I am trying to send a flatteded DBl array from labview to c# through tcp.
i am receiving the flattened string in c#.
i dont know how to convert them back to DBL array?
This is my code in C#:
{
private TcpClient socketConnection;
private Thread clientReceiveThread;
void Start()
{
ConnectToTcpServer();
}
void Update()
{
}
private void ConnectToTcpServer()
{
try
{
clientReceiveThread = new Thread(new ThreadStart(ListenForData));
clientReceiveThread.IsBackground = true;
clientReceiveThread.Start();
}
catch (Exception e)
{
Debug.Log("On client connect exception " + e);
}
}
private void ListenForData()
{
try
{
socketConnection = new TcpClient("localhost", 5333);
Byte[] bytes = new Byte[4000];
while (true)
{
using (NetworkStream stream = socketConnection.GetStream())
{
int length;
while ((length = stream.Read(bytes, 0, bytes.Length)) != 0)
{
Debug.Log(bytes.Length);
var incomingData = new byte[length];
Array.Copy(bytes, 0, incomingData, 0, length);
// Convert byte array to string message.
string serverMessage = Encoding.ASCII.GetString(incomingData);
Debug.Log("server message received as: " + serverMessage);
Debug.Log(serverMessage.Length);
}
}
}
}
catch (SocketException socketException)
{
Debug.Log("Socket exception: " + socketException);
}
}
}
This is my labview code:
This is my labview output: (Float array and flattened string)
This is the output in C#:
Since you wired FALSE to the "prepend array or string size", the only data in the buffer is the flattened doubles themselves. But you need to explicitly set "little endian" in order to talk to C#.
If you make that change in the G code, then this should work:
double[] dblArray = (double[])Array.CreateInstance(typeof(System.Double), length / 8);
// I'm not sure if you need the cast or not.
You have the constant "4000" in your code. I would change that to a declared constant and put a comment next to it that says, "Make sure this is a multiple of 8 (number of bytes in double data type)."
I am stuck with this serious problem.
I have async TcpListener. Sometimes there are several connected clients and everything is fine. Sometimes even if there is one person. The server starts usage 50-60% of my CPU.
I think the problem could be in handling of reading exceptions but it's my only tip and I don't know how to test it.
Here is code for server:
class Server
{
private TcpListener server;
public Server(string hostname, int port = 25000)
{
server = new TcpListener(IPAddress.Parse(hostname), port);
}
public void ServerStart()
{
server.Start();
WaitForClientConnect();
}
private async void WaitForClientConnect()
{
TcpClient client = await server.AcceptTcpClientAsync();
Console.WriteLine("The async connection created for: " + ((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString());
OnClientConnect(client);
}
private void OnClientConnect(TcpClient client)
{
ClientLowAPI clientReq = new ClientLowAPI(client);
WaitForClientConnect();
}
}
Here is the code for handling a single client:
class ClientLowAPI
{
private TcpClient client;
private NetworkStream stream;
public ClientLowAPI(TcpClient clientConnected)
{
client = clientConnected;
stream = client.GetStream();
WaitForHeader();
}
private async void WaitForHeader()
{
byte[] buffer = new byte[4];
int bytesRead = 0;
while (bytesRead < 4)
{
try
{
bytesRead += await stream.ReadAsync(buffer, bytesRead, buffer.Length - bytesRead);
}
catch
{
stream.Close();
client.Close();
return;
}
}
WaitForData(FourBytesToInt(buffer));
}
private async void WaitForData(int length)
{
byte[] buffer = new byte[length];
int bytesRead = 0;
while (bytesRead < length)
{
try
{
bytesRead += await stream.ReadAsync(buffer, bytesRead, buffer.Length - bytesRead);
}
catch
{
stream.Close();
client.Close();
return;
}
}
ExecuteMessage(buffer);
}
private void ExecuteMessage(byte[] binaryData)
{
// Do something with message
WaitForHeader();
}
public async void SendMessage(byte[] message)
{
byte[] buffer = new byte[message.Length + 4];
byte[] length = IntToFourBytes(message.Length);
length.CopyTo(buffer, 0);
message.CopyTo(buffer, 4);
try
{
await stream.WriteAsync(buffer, 0, buffer.Length);
}
catch
{
stream.Close();
client.Close();
return;
}
}
private int FourBytesToInt(byte[] array)
{
int res = 0;
res += array[0] * 256 * 256 * 256;
res += array[1] * 256 * 256;
res += array[2] * 256;
res += array[3];
return res;
}
private byte[] IntToFourBytes(int intValue)
{
byte[] array = new byte[4];
array[0] = (byte)(intValue >> 24);
array[1] = (byte)(intValue >> 16);
array[2] = (byte)(intValue >> 8);
array[3] = (byte)intValue;
return array;
}
}
The problem was caused by this loop:
while (bytesRead < 4)
{
try
{
bytesRead += await stream.ReadAsync(buffer, bytesRead, buffer.Length - bytesRead);
}
catch
{
stream.Close();
client.Close();
return;
}
}
Normally was connection killed by force and server has raised exception but sometimes the connection was properly closed by client by TcpClient.Close() then the exception was not raised and the stream.ReadAsync method start returns 0 which caused infinty loop with huge CPU usage.
for fast fix i used the following condition:
if (bytesRead == 0)
{
throw new System.IO.IOException();
}
I want to stop my thread on button click event and As I am new to threads I don't know how can I do this in C#. My application is of TCP Client and I am reading TCP server continuously using this thread
public void ClientReceive()
{
try
{
stream = client.GetStream(); //Gets The Stream of The Connection
new Thread(() => // Thread (like Timer)
//Thread mythread = new Thread(ClientReceive);
{
//MessageBox.Show(stream.Read(datalength, 0, 256).ToString());
//(i = stream.Read(datalength, 0, 256)) != 0
while (i != 1)//Keeps Trying to Receive the Size of the Message or Data
{
// how to make a byte E.X byte[] examlpe = new byte[the size of the byte here] , i used BitConverter.ToInt32(datalength,0) cuz i received the length of the data in byte called datalength :D
// byte[] data = BitConverter.GetBytes(1000); // Creates a Byte for the data to be Received On
byte[] data = new byte[1000];
stream.Read(data, 0, data.Length); //Receives The Real Data not the Size
this.Invoke((MethodInvoker)delegate // To Write the Received data
{
//txtLog.Text += System.Environment.NewLine + "Server : " + Encoding.Default.GetString(data); // Encoding.Default.GetString(data); Converts Bytes Received to String
DateTime now = DateTime.Now;
//MessageBox.Show(Encoding.Default.GetString(data));
if (Encoding.Default.GetString(data) != "")
{
txtLog.Text += System.Environment.NewLine + now.ToString() + " Received : \r\n" + Encoding.Default.GetString(data) + "\r\n";
}
for (int j = 0; j < txtLog.Lines.Length; j++)
{
if (txtLog.Lines[j].Contains("Received"))
{
this.CheckKeyword(txtLog.Lines[j + 1], Color.Red, 0);
}
if (txtLog.Lines[j].Contains("Sent"))
{
this.CheckKeyword(txtLog.Lines[j + 1], Color.Blue, 0);
}
}
});
}
// mythread.Start();
}).Start(); // Start the Thread
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
I recommend you to use Task instead of Thread. Because Aborting a thread is not recommnded and it may affect your data as well.
Eric Lippert explained it very well here.
Here is the code for you:
private CancellationTokenSource tokenSource; //global field
public void ClientReceive()
{
try
{
//initiate CancellationTokenSource
tokenSource = new CancellationTokenSource();
stream = client.GetStream(); //Gets The Stream of The Connection
//start parallel task
Task.Factory.StartNew(() =>
{
//MessageBox.Show(stream.Read(datalength, 0, 256).ToString());
//(i = stream.Read(datalength, 0, 256)) != 0
while (i != 1)//Keeps Trying to Receive the Size of the Message or Data
{
// how to make a byte E.X byte[] examlpe = new byte[the size of the byte here] , i used BitConverter.ToInt32(datalength,0) cuz i received the length of the data in byte called datalength :D
// byte[] data = BitConverter.GetBytes(1000); // Creates a Byte for the data to be Received On
byte[] data = new byte[1000];
stream.Read(data, 0, data.Length); //Receives The Real Data not the Size
this.Invoke((MethodInvoker)delegate // To Write the Received data
{
//txtLog.Text += System.Environment.NewLine + "Server : " + Encoding.Default.GetString(data); // Encoding.Default.GetString(data); Converts Bytes Received to String
DateTime now = DateTime.Now;
//MessageBox.Show(Encoding.Default.GetString(data));
if (Encoding.Default.GetString(data) != "")
{
txtLog.Text += System.Environment.NewLine + now.ToString() + " Received : \r\n" + Encoding.Default.GetString(data) + "\r\n";
}
for (int j = 0; j < txtLog.Lines.Length; j++)
{
if (txtLog.Lines[j].Contains("Received"))
{
this.CheckKeyword(txtLog.Lines[j + 1], Color.Red, 0);
}
if (txtLog.Lines[j].Contains("Sent"))
{
this.CheckKeyword(txtLog.Lines[j + 1], Color.Blue, 0);
}
}
});
}
}, tokenSource.Token);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
//call this method on cancel button
private void cancelTask()
{
if(tokenSource != null) //check if its even initialized or not
tokenSource.Cancel();
}
If you need more explanation about TPL refer to this article.
Try this:
Thread thread = new Thread(() =>
{
Console.WriteLine("Some actions inside thread");
});
thread.Start();
thread.Abort();
First you need to set your thread to some field and then you can control it as shown in code, Start(),Abort().
If you want Abort() thread from button click event you need to move thread field out of method, that way you can get access from your button click event.
Hope Helps!
In the below code state is an object which has a property msgLength which is the total message length.The msgLength is the first four bytes of the message.
I am getting unexpected results in the state.msgLength propery when more than one message is received in "quick" succesion.When the state.msglength is not as expected
I get an error trying to receive. Specified argument was out of the range of valid values.
StateObj state = (StateObj)ar.AsyncState;
try
{
state.read += state.socket.EndReceive(ar);
if (state.read == 0)
{
state.socket.Close();
state.socket.Dispose();
state.socket = null;
this.Invoke((MethodInvoker)delegate { listBox1.Items.Add(DateTime.Now.ToString("HH:mm ss") + " socket closed"); });
return;
}
}
catch (Exception)
{
this.Invoke((MethodInvoker)delegate { listBox1.Items.Add(DateTime.Now.ToString("HH:mm ss") + " socket closed"); });
return;
}
if (state.read < 4)
{
//read again you dont have state,msglength
state.socket.BeginReceive(state.dataBuffer, state.read, 4 - state.read, 0, cbReceive, state);
}
else
{
state.msglength = BitConverter.ToInt32(state.dataBuffer, 0);
}
if (state.read < state.msglength)
{
//read again you dont have the complete message
//here is the error Specified argument was out of the range of valid values.
state.socket.BeginReceive(state.dataBuffer, state.read, state.msglength - state.read, 0, cbReceive, state);
}
else
{
//process here
if (state.read > state.msglength )
{
state.read = state.read - state.msglength;
}
else
{
state.read = 0;
}
state.socket.BeginReceive(state.dataBuffer, 0, state.dataBuffer.Length, 0, cbReceive, state);
}
I think that state.socket.BeginReceive is executed twice.
Because when it is reading it's header, both if (state.read < 4) and if (state.read < state.msglength) are true. Return after the first state.socket.BeginReceive(.. could solve the issue.
if (state.read < 4)
{
//read again you dont have state,msglength
state.socket.BeginReceive(state.dataBuffer, state.read, 4 - state.read, 0, cbReceive, state);
return; // <------
}
else
{
state.msglength = BitConverter.ToInt32(state.dataBuffer, 0);
}
if (state.read < state.msglength)
{
//read again you dont have the complete message
//here is the error Specified argument was out of the range of valid values.
state.socket.BeginReceive(state.dataBuffer, state.read, state.msglength - state.read, 0, cbReceive, state);
}
else
{
state.read = 0;
//process correctly expected message
}
I think I found another issue, If the messageLength specified within the message is only the size of the data. You should read if (state.read < state.msglength+4) Because the length header is included in your buffer.
I mostly split-up reading header/data. Like: (PSEUDO)
byte[] header;
byte[] buffer;
int bytesRead;
public void ReadHeader()
{
bytesNeeded = 4;
bytesRead = 0;
BeginReadHeader();
}
public void BeginReadHeader()
{
BeginReceive(header, bytesRead, bytesNeeded-bytesRead, EndReadHeader);
}
public void EndReadHeader()
{
int read = EndReceive();
if(read == 0)
{
CloseSocket();
return;
}
bytesRead += read;
if(bytesRead == byteNeeded)
ReadData();
else
BeginReadHeader();
}
public void ReadData()
{
bytesNeeded = BitConverter.ToInt32(header, 0);
bytesRead = 0;
if(buffer.Length < bytesNeeded)
buffer = new byte[bytesNeeded];
BeginReadData();
}
public void BeginReadData()
{
BeginReceive(buffer, bytesRead, bytesNeeded-bytesRead, EndReadData);
}
public void EndReadData()
{
int read = EndReceive();
if(read == 0)
{
CloseSocket();
}
bytesRead += read;
if(bytesRead == byteNeeded)
{
HandleData();
}
else
BeginReadData();
}
public void HandleData()
{
// handle data in buffer. BinaryReader
ReadHeader();
}
i code socket application using blocing socket and use multithreading..my problem is i want to receive two large packet..as we know tcp must be split large data into multiple packet..this the scenario:
i send 6 mb text file and tcp split packet into 2 separate packet
at the same time i send 26 mb video file and tcp also split packet into 2 separate packet
at my application i recive first part of text file let say it 3 mb of 6 mb
and then i receive first part of video let say it 13 mb of 26 mb..
the question is how i know that first packet of text file and first packet of video file is a different data and should handle in different way..(different buffer maybe??)
sorry for my bad english..
thanks in advance..
this some part of my code
ns = client.GetStream();
while (isListen == true && client.Connected)
{
while (!ns.DataAvailable)
{
try
{
Thread.Sleep(1);
}
catch (Exception ex)
{
}
}
data = new byte[client.ReceiveBufferSize];
//client.Client.Receive(data);
int indx = ns.Read(data, 0, data.Length);
string message = Encoding.ASCII.GetString(data, 0, indx);
if (message == GetEnumDescription(TypeData.Disconnect))
{
isListen = false;
server.ClientKeluar = objClient;
if (ClientDisconnected != null)
{
ClientDisconnected(objClient);
}
thisThread.Abort();
Server.kumpulanThread.Remove(thisThread);
Server._serverConnections.Remove(this);
client.Close();
}
else if (message.Contains(GetEnumDescription(TypeData.GetFile)))
{
//jalankan proses pengambilan data
}
else if (message.Contains(GetEnumDescription(TypeData.ByteLength)))
{
string length = message.Substring(6, message.Length - 6);
int len = int.Parse(length);
expectedLength = client.ReceiveBufferSize = len;
data = new byte[len];
}
else if (message.Contains(GetEnumDescription(TypeData.Image)))
{
typeData = "Image";
dat1 = new byte[client.ReceiveBufferSize];
index = 0;
}
else if (message.Contains(GetEnumDescription(TypeData.Video)))
{
typeData = "Video";
dat2 = new byte[client.ReceiveBufferSize];
index = 0;
}
else
{
if (typeData == "Image")
{
expectedLength = expectedLength - message.Length;
if (expectedLength == 0)
{
Array.Copy(data, 0, dat1, index, message.Length);
if (ImageDelivered != null)
{
ImageDelivered(dat1);
}
}
else
{
Array.Copy(data, 0, dat1, index, message.Length);
index = message.Length;
}
}
else if (typeData == "Video")
{
expectedLength = expectedLength - message.Length;
if (expectedLength == 0)
{
Array.Copy(data, 0, dat2, index, message.Length);
if (VideoDelivered != null)
{
VideoDelivered(dat2);
}
}
else
{
Array.Copy(data, 0, dat2, index, message.Length);
index = message.Length;
}
}
else
{
expectedLength = expectedLength - message.Length;
if (expectedLength == 0)
{
dataToWrite = dataToWrite + message;
string text = dataToWrite;
if (MessageDelivered != null)
{
MessageDelivered(text);
}
dataToWrite = "";
}
else
{
dataToWrite += message;
}
}
}
}
may anyone give sample code so i can get inspiration to solve this problem?
TCP protocol take cares of making segments of files and later joining them. You will get complete data in receive.