Async Socket receiving data in the wrong order or missing - c#

I've asked about this topic before and thought I had a handle on it but I'm finding I'm missing something here. I've got some C code in linux that I'm sending data through a socket to my C# winforms visualization code. I'm sending the data from C as fast as I can calculate it which pretty damn fast. But in C# my datagridview is not updating correctly. If I slow down the rate at which I am sending the data to the c# code it does okay. But I can't really do that. I really am dying here.
So in C# this is what I have:
{
. . .
sListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sListener.Bind(new IPEndPoint(0, 1994));
Listen();
}
private void Listen()
{
sListener.Listen(10);
// Begins an asynchronous operation to accept an attempt
AsyncCallback aCallback = new AsyncCallback(AcceptCallback);
sListener.BeginAccept(aCallback, sListener);
}
public void AcceptCallback(IAsyncResult ar)
{
Socket listener = null;
// A new Socket to handle remote host communication
Socket handler = null;
try
{
// Receiving byte array
byte[] buffer = new byte[1024];
// Get Listening Socket object
listener = (Socket)ar.AsyncState;
// Create a new socket
handler = listener.EndAccept(ar);
// Using the Nagle algorithm
handler.NoDelay = false;
// Creates one object array for passing data
object[] obj = new object[2];
obj[0] = buffer;
obj[1] = handler;
// Begins to asynchronously receive data
handler.BeginReceive( buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), obj);
// Begins an asynchronous operation to accept an attempt
AsyncCallback aCallback = new AsyncCallback(AcceptCallback);
listener.BeginAccept(aCallback, listener);
}
catch (Exception exc) { MessageBox.Show(exc.ToString()); }
}
public void ReceiveCallback(IAsyncResult ar)
{
try
{
// Fetch a user-defined object that contains information
object[] obj = new object[2];
obj = (object[])ar.AsyncState;
// Received byte array
byte[] buffer = (byte[])obj[0];
// A Socket to handle remote host communication.
handler = (Socket)obj[1];
// Received message
string content = string.Empty;
// The number of bytes received.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
Array.Resize(ref buffer, bytesRead);
double[] values = new double[buffer.Length / 8];
int i = 0;
values[i] = BitConverter.ToDouble(buffer, i * 8);
values[++i] = BitConverter.ToDouble(buffer, i * 8);
values[++i] = BitConverter.ToDouble(buffer, i * 8);
values[++i] = BitConverter.ToDouble(buffer, i * 8);
values[++i] = BitConverter.ToDouble(buffer, i * 8);
this.Invoke((MethodInvoker)delegate()
{
if (dataGridView1.Rows.Count > 5)
{
dataGridView1.Rows.RemoveAt(this.dataGridView1.Rows[5].Index);
}
dataGridView1.Rows[0].Cells[1].Value = values[0];
dataGridView1.Rows[1].Cells[1].Value = values[1];
dataGridView1.Rows[2].Cells[1].Value = values[2];
dataGridView1.Rows[3].Cells[1].Value = values[3];
dataGridView1.Rows[4].Cells[1].Value = values[4];
});
}
// Continues to asynchronously receive data
byte[] buffernew = new byte[1024];
obj[0] = buffernew;
obj[1] = handler;
handler.BeginReceive(buffernew, 0, buffernew.Length,
SocketFlags.None,
new AsyncCallback(ReceiveCallback), obj);
}
catch (Exception exc) { MessageBox.Show(exc.ToString()); }
}

Your async code is firing async, which is as expected... But this means that the order of processing could differ from the order of receive. For example:
.NET receive message 1
.NET receive message 2
.NET finish receive message 2
.NET finish receive message 1
Here you assumed you'd see 1, then 2 since that's the order they were received in, but NOT the order they finished being received in.
If the order of your data is important, you must either send all of it at once in a large batch (bad), or receive it sequentially (the underlying TCP should ensure that messages are delivered in the appropriate order).

Related

How to prevent Stack Overflow Exception due to an async ReceiveCallback (TCP Server)

I'm working on a Server-Client application with TCP and Sockets
The communication works fine and all and the messages arrive correctly.
The way I made this is:
a packet arrives and gets written into a client specific buffer The first 10 characters is the length of the message, the rest is
the message (JSON-string)
if the buffer is the same length as the message CheckIfMessageArrivedCompletely(Socket client ) gets executed which does whatever the message includes (the message is a JSON object in which it contains a path element which is inserted into the "forwardingDictionary"
if the buffer is shorter wait until everything arrived.
Now onto the problem:
Since The new socket.BeginReceive and therefore the AsyncCallback is called within the old AsyncCallback it is recursive. After about 2000 times the program throws the Stack Overflow exception. This is somewhat logical even if the function only is called after a packet arrives. But how can this be prevented. The goal is to have a continuously open Socket which is able to receive Data. This is especially a problem when sending a file (converted to byte[] ) over ~20kb.
I'm new to networking, so if you would see any rookie mistake feel free to correct me.
I would really appreciate it.
This is the code responsible for the networking:
public static void InitializeServer(){
//---listen at the specified IP and port no.---
Console.WriteLine("Starting Server...");
Console.WriteLine("Listening...");
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Bind(new IPEndPoint(IPAddress.Any, PORT_NO));
serverSocket.Listen(NUM_OF_PLAYERS); //the maximum pending client
serverSocket.BeginAccept(new AsyncCallback(acceptCallback), null);
string result = "";
do {
result = Console.ReadLine();
} while (result.ToLower().Trim() != "exit");
}
private static void acceptCallback(IAsyncResult result) {
Socket socket = null;
try {
socket =serverSocket.EndAccept(result);
Console.WriteLine(socket.RemoteEndPoint.Serialize());
//Do something as you see it needs on client acceptance
buffer.Add(socket,new byte[BUFFER_SIZE]);
socket.BeginReceive(buffer[socket], 0, buffer[socket].Length, SocketFlags.None, new AsyncCallback(receiveCallback), socket);
serverSocket.BeginAccept(new AsyncCallback(acceptCallback), null); //to receive another client
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
private const int BUFFER_SIZE = 10000;
private static Dictionary<Socket,byte[]> buffer = new Dictionary<Socket, byte[]>();
private static Dictionary<Socket,byte[]> messageBuffer = new Dictionary<Socket, byte[]>();
const int MAX_RECEIVE_ATTEMPT = 10;
static int receiveAttempt = 0;
private static void receiveCallback(IAsyncResult result) {
Socket socket = null;
try {
socket =(Socket)result.AsyncState;
if (socket.Connected) { //simple checking
int received = socket.EndReceive(result);
if (received > 0) {
Console.Write("."); //to log incoming packet;
//Check if Client has an unfinished Packet
int lastNonZeroIndex = Array.FindLastIndex(buffer[socket],x => x != 0);
if(messageBuffer.ContainsKey(socket)){
int firstNullIndex = Array.FindIndex(messageBuffer[socket], x => x == 0);
//Copy the incoming data at the end of the buffer
Buffer.BlockCopy(buffer[socket],0,messageBuffer[socket],firstNullIndex,lastNonZeroIndex+1);
}
else{
//Since it's a new message, parse its length and add the empty byte to the dictionary
int messageLength = int.Parse(new string(Encoding.UTF8.GetChars(buffer[socket])).Substring(0,10));
messageBuffer.Add(socket,new byte[messageLength]);
Console.WriteLine(messageLength);
//Copy the incoming data at the end of the buffer
Array.Copy(buffer[socket],10,messageBuffer[socket],0,lastNonZeroIndex+1-10);
}
CheckIfMessageArrivedCompletely(socket);
Array.Clear(buffer[socket]);
receiveAttempt = 0; //reset receive attempt
socket.BeginReceive(buffer[socket], 0, buffer[socket].Length, SocketFlags.None, new AsyncCallback(receiveCallback), socket);
} else if (receiveAttempt < MAX_RECEIVE_ATTEMPT) { //fail but not exceeding max attempt, repeats
++receiveAttempt; //increase receive attempt;
socket.BeginReceive(buffer[socket], 0, buffer[socket].Length, SocketFlags.None, new AsyncCallback(receiveCallback), socket);
} else { //completely fails!
Console.WriteLine("receiveCallback fails!"); //don't repeat beginReceive
receiveAttempt = 0; //reset this for the next connection
}
}
} catch (Exception e) { // this exception will happen when "this" is be disposed...
Console.WriteLine("receiveCallback fails with exception! " + e.ToString());
}
}
static void CheckIfMessageArrivedCompletely(Socket client){
//if The Message arrived completely, execute the command and remove the message from the client buffer
if(!messageBuffer.ContainsKey(client)){
Console.WriteLine("ERROR: client not in dictionary");
return;
}
if(messageBuffer[client][messageBuffer[client].Length-1] == 0)return; // if not completed return and wait for the rest
//Convert bytes to string and then parse JSON
string strData = new string(Encoding.UTF8.GetChars(messageBuffer[client]));
messageBuffer.Remove(client); // removing the bytes from the buffer
JObject messageInJObject = JObject.Parse(strData);
string[] command = messageInJObject["path"].ToObject<string[]>();
if(!forwardingDictionary.ContainsKey(command[0])) return; // if not in dictionary --> return
forwardingDictionary[command[0]](client,messageInJObject);
}
The error looks like this:
Stack overflow.
at System.Text.OSEncoding.WideCharToMultiByte(Int32, Char*, Int32, Byte*, Int32)
at System.Text.OSEncoder.GetBytes(Char*, Int32, Byte*, Int32, Boolean)
at System.Text.Encoder.GetBytes(System.ReadOnlySpan`1<Char>, System.Span`1<Byte>, Boolean)
at System.IO.StreamWriter.Flush(Boolean, Boolean)
at System.IO.StreamWriter.Write(System.String)
at System.IO.TextWriter+SyncTextWriter.Write(System.String)
at System.Console.Write(System.String)
at Program.receiveCallback(System.IAsyncResult)
at System.Threading.Tasks.TaskToApm+TaskAsyncResult..ctor(System.Threading.Tasks.Task, System.Object, System.AsyncCallback)
at System.Net.Sockets.Socket.BeginReceive(Byte[], Int32, Int32, System.Net.Sockets.SocketFlags, System.AsyncCallback, System.Object)
at Program.receiveCallback(System.IAsyncResult)
And the last 3 lines repeated the number of times it took to cause the error (about 2000 times)

C# / Sockets: Receiving data and constructing a message from it

I am trying to implement a system that can send and receive "Nessages" (a custom type) using async Sockets. Each Message consists of three elements:
First I send the Message-ID (4 bytes), next is the length of the data (4 bytes) and then the actual data.
The way TCP/IP works, I can not know if the full Message is in the buffer of data that I just received. I need to look for the InfoHeader (ID and length) first and use the remaining data to fill the Message's DataBuffer.
public void ReadCallback(IAsyncResult ar)
{
try
{
// How many bytes were received? They are now stored in the PacketBuffer
int bytesReceived = Socket.EndReceive(ar);
if (bytesReceived != 0)
{
// We did receive some data
if (MessageInfoHeader.Length < NetProtocol.NetInfoHeaderSize)
{
// The InfoHeader we have is not complete yet. How many bytes are missing from it?
int infoHeaderDataInCurrentBuffer = NetProtocol.NetInfoHeaderSize - (int) MessageInfoHeader.Length;
// Check if we have read enough data to fill the entire missing InfoHeader
if (infoHeaderDataInCurrentBuffer > bytesReceived)
{
// Nope, we dont. Fill as much as we can
infoHeaderDataInCurrentBuffer = bytesReceived;
Log.Info("We do not have enough data to complete the InfoHeader yet. Fill as much as we can");
}
else
{
Log.Info("We do have enough data to complete the InfoHeader");
}
// Now fill it from the chunk of data we just received
MessageInfoHeader.Write(ReceivedData, 0, infoHeaderDataInCurrentBuffer);
// See if there is any data remaining in the buffer that we can store in the MessageDataBuffer
int dataRemainingInPacket = bytesReceived - infoHeaderDataInCurrentBuffer;
Log.Info("DataRemainingInPacket: " + dataRemainingInPacket);
// Check again if we have the full header
if (MessageInfoHeader.Length == NetProtocol.NetInfoHeaderSize)
{
Log.Info("We now have assembled the full InfoHeader");
// We do have the full InfoHeader. Use the rest of the data to fill the DataBuffer
using (MemoryStream ms = new MemoryStream())
{
byte[] b = MessageInfoHeader.GetBuffer();
ms.Write(b, 0, b.Length);
ms.Seek(0, SeekOrigin.Begin);
try
{
using (BinaryReader br = new BinaryReader(ms))
{
CurrentMessageID = br.ReadInt32();
CurrentMessageDataLength = br.ReadInt32();
Log.Info("InfoHeader: MessageID=" + CurrentMessageID + " / DataLength=" + CurrentMessageDataLength);
}
}
catch (Exception ex)
{
throw ex;
}
}
if (dataRemainingInPacket > 0)
{
Log.Info("There are " + dataRemainingInPacket + " bytes remaining in the packet. Writing them to the PacketDataBuffer");
MessageDataBuffer.Write(ReceivedData, CurrentPacketBytesRead, ReceivedData.Length - CurrentPacketBytesRead);
}
}
}
else
{
MessageDataBuffer.Write(ReceivedData, 0, ReceivedData.Length);
if(ReceivedData.Length <= NetDataBufferSize)
{
Log.Info("WE HAVE RECEIVED THE ENTIRE MESSAGE");
}
}
// Start receiving the new TCP-Packet
Socket.BeginReceive(ReceivedData, 0, ReceivedData.Length, SocketFlags.None, new AsyncCallback(ReadCallback), null);
}
else
{
Log.Info("No data has been received");
}
}
catch (Exception ex)
{
throw ex;
}
}
private void AcceptCallback(IAsyncResult ar)
{
// Retrieve the listening Socket
Socket listener = (Socket)ar.AsyncState;
// Retrieve the Socket that is actually connected to the client
Socket csocket = listener.EndAccept(ar);
Log.Info("Accepted connection from: " + csocket.RemoteEndPoint.ToString());
// Create a new client with the CSocket and add it to the list
ClientConnection client = ClientManager.AddClient(csocket);
// Start reading data from the Client's Socket and then enter the "read-loop" inside the client
client.Socket.BeginReceive(client.ReceivedData, 0, (int) client.ReceivedData.Length, SocketFlags.None, new AsyncCallback(client.ReadCallback), null);
// Turn the listener back into listening mode
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
}
public const int NetInfoHeaderSize = 8; // 2x int
public static byte[] FrameMessage(NetMessage message)
{
byte[] result;
using(MemoryStream ms = new MemoryStream())
{
using (BinaryWriter bw = new BinaryWriter(ms))
{
bw.Write(message.ID);
bw.Write(message.Data.Length);
bw.Write(message.Data);
}
result = ms.ToArray();
}
return result;
}
This piece of code obviously does not work correctly. I get the "RECEIVED ENTIRE MESSAGE" line multiple times.
Question: What exactly am I doing wrong? I'm failing to wrap my head around what is the best way to handle something like this? Thanks in advance for any input!
There could be quite a few problems. But the first one I can see for the loop on "RECEIVED ENTIRE MESSAGE" is that you are assuming the ReceivedData buffer has been filled entirely by Socket.EndReceive(ar); - which isn't the case, so a first troubleshooting start could be to rewrite this:
MessageDataBuffer.Write(ReceivedData, 0, ReceivedData.Length);
if (ReceivedData.Length <= NetDataBufferSize)
{
Log.Info("WE HAVE RECEIVED THE ENTIRE MESSAGE");
}
to:
MessageDataBuffer.Write(ReceivedData, 0, bytesReceived);
if (MessageDataBuffer.Length <= NetDataBufferSize)
{
Log.Info("WE HAVE RECEIVED THE ENTIRE MESSAGE");
}
Assuming that MessageDataBuffer is intended to contain the entire message

My received data slipt in two part in socket c#

I have this code as a server application to receive data :
public AsyncCallback pfnWorkerCallBack;
private Socket m_mainSocket;
private Socket[] m_workerSocket = new Socket[25];
private int m_clientCount = 0;
public void startfun()
{
string Camera1Port = "1001";
int port1 = System.Convert.ToInt32(Camera1Port);
m_mainSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, port1);
m_mainSocket.Bind(ipLocal);
m_mainSocket.Listen(20);
m_mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);
}
public void OnClientConnect(IAsyncResult asyn)
{
m_workerSocket[m_clientCount] = m_mainSocket.EndAccept(asyn);
WaitForData(m_workerSocket[m_clientCount]);
++m_clientCount;
m_mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);
}
public class SocketPacket
{
public System.Net.Sockets.Socket m_currentSocket;
public byte[] dataBuffer ;
}
public void WaitForData(System.Net.Sockets.Socket soc)
{
if (pfnWorkerCallBack == null)
{
pfnWorkerCallBack = new AsyncCallback(OnDataReceived);
}
SocketPacket theSocPkt = new SocketPacket();
theSocPkt.dataBuffer = new byte[soc.ReceiveBufferSize];
theSocPkt.m_currentSocket = soc;
soc.BeginReceive(theSocPkt.dataBuffer, 0,
theSocPkt.dataBuffer.Length,
SocketFlags.None,
pfnWorkerCallBack,
theSocPkt);
}
public void OnDataReceived(IAsyncResult asyn)
{
SocketPacket socketData = (SocketPacket)asyn.AsyncState;
string res = GetParameters(socketData.dataBuffer);
MessageBox.Show(res);
WaitForData(socketData.m_currentSocket);
}
public string GetParameters(byte[] buf)
{
string result = System.Text.Encoding.UTF8.GetString(buf);
return result;
}
The problem is the data is breaking .I mean when i receive data from socket in first time all values are received and the messagebox show all of that.when i receive the second data ,i just receive some part of that .suppose the data is 870314854798 .I receive the data in first time correctly ,but in second i just get 3 or 4 digit of that(it is random) and the message box shows 3 or 4 digit after clicking of ok (Messagebox) the other digits are shown.why ?
i googled it and i found this but i can't map this solution with my solution
public static void Read_Callback(IAsyncResult ar){
StateObject so = (StateObject) ar.AsyncState;
Socket s = so.workSocket;
int read = s.EndReceive(ar);
if (read > 0) {
so.sb.Append(Encoding.ASCII.GetString(so.buffer, 0, read));
s.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0,
new AsyncCallback(Async_Send_Receive.Read_Callback), so);
}
else{
if (so.sb.Length > 1) {
//All of the data has been read, so displays it to the console
string strContent;
strContent = so.sb.ToString();
Console.WriteLine(String.Format("Read {0} byte from socket" +
"data = {1} ", strContent.Length, strContent));
}
s.Close();
}
}
The problem is how can i merge this solution with my code ?
In your OnDataReceived method you should EndReceive to complete the operation you began like this:
StateObject so = (StateObject) async.AsyncState;
Socket s = so.workSocket;
int read = s.EndReceive(async); // You need to do this.
You should always call, as per MSDN's recommendations, the EndReceive, EndInvoke etc on any async operation. Otherwise, you may not get the exceptions either.
That's how network stack (especially TCP) works. It does not guarantee that all data sent into a socket as a single piece would be delivered to the client as a single piece. You can only expect that all data sent into a socket will be received by the client in the same order, but can't rely on how it is going to be split into chunks.
E.g. as the data travel through the network they might pass nodes that have different settings and limitations on how big the packet may be. If a packet is too large, it will be split into multiple packets of appropriate size that will be then sent to the client.
If your protocol requires that a packet is delivered from the server to the client as a single solid piece, you would have to construct your own application layer protocol to control that. This is how http works: no matter how the data representing a web page is split into TCP packets, the client receives the whole page at once.

lua socket communication from c# receiving nil

I'm trying to use lua script to extract some data from a program, and then send that data to a c# script which then processed it and returns some simple messages for the lua script to then pass along to the program.
The lua script is as follows
-- Socket decls
local socket = require("socket")
local host, port = "127.0.0.1", 3000
local tcp = assert(socket.tcp())
tcp:connect(host,port)
tcp:settimeout(0)
tcp:send("Stream starting...")
function sendEventInfoToServer(string)
tcp:send(string)
end
function processEventInfo()
local received, status = tcp:receive()
if received ~= nil then
print(received, status);
end
end
while true do
-- unrelated logic
processEventInfo();
end
and on the C# end
public class SimpleTCPListener
{
private TcpListener tcpListener;
private TcpClient _tcpClient;
private Thread listenThread;
private NetworkStream clientStream;
List<string> eventsWaiting;
public List<string> EventsWaiting {
get {
List<string> tempList = new List<string>();
for (int i = 0; i < eventsWaiting.Count; i++)
tempList.Add(eventsWaiting[i]);
EventsWaiting = new List<string>();
return tempList;
}
private set { eventsWaiting = value; }
}
public SimpleTCPListener()
{
EventsWaiting = new List<string>();
this.tcpListener = new TcpListener(IPAddress.Any, 3000);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void ListenForClients()
{
this.tcpListener.Start();
while(true)
{
// blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
// create a thread to handle communication
// with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientCom));
clientThread.Start(client);
clientStream = client.GetStream();
}
}
public void SendSavestateLoadRequest()
{
if(clientStream != null)
{
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("HelloLua!\n");
Console.WriteLine("Sending data back to lua");
if (clientStream.CanWrite)
clientStream.Write(buffer, 0, buffer.Length);
else
Console.WriteLine("Connection close!");
//clientStream.Flush();
}
}
private void HandleClientCom(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while(true)
{
bytesRead = 0;
try
{
// blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
// a socket error has occured
break;
}
if(bytesRead == 0)
{
// the client disconnected
break;
}
// message has been recieved
ASCIIEncoding encoder = new ASCIIEncoding();
System.Diagnostics.Debug.WriteLine(encoder.GetString(message, 0, bytesRead));
string s = encoder.GetString(message, 0, bytesRead);
Console.WriteLine(s);
if (!string.IsNullOrEmpty(s))
eventsWaiting.Add(s);
}
tcpClient.Close();
}
}
Now, the Lua talks to the C# thread no problem, and the C# doesn't report any errors when sending data back to the lua, but on the lua side it's constantly receiving nil, however if I remove the nil check it sometimes receives and prints the string, but with the nil check it never seems to find 'received' as not nil. I'm really new with lua script so hopefully it's something simple I'm not understanding about the syntax but I can't seem to find lot of documentation.
Any suggestions would be hugely appreciated.

Error in asynchronous read from the NetworkStream

I have make an application to communicate with an IP Camera. That is configured to make connection on a predefined address. And TCP Listener is running on that address and accepts connection from camera. When camera connects i send command to get MJpeg stream from camera and camera starts sending stream in response to command.
I am using asynchronous method to read stream from socket. But after sometime my application is stuck while reading data from network stream.
I am using this code to read Data from network stream and i have write some messages on the screen to get status of camera connection.
private void ReadData()
{
try
{
string msg = "Reading Data... client connected " + _camClient.Connected.ToString() +
"... netStream Readable " +
_netStream.CanRead.ToString();
Console.WriteLine(msg);
_callback = new AsyncCallback(GetData);
_buffer = new byte[Buffersize];
_async = _netStream.BeginRead(_buffer, 0, Buffersize, _callback, null);
}
catch (Exception ex) { Console.WriteLine("ReadData: " + ex.Message); }
}
private void GetData(IAsyncResult result)
{
try
{
int read = _netStream.EndRead(result);
if (read > 0)
{
_data = new byte[read];
Array.Copy(_buffer, 0, _data, 0, read);
ProcessData();
}
ReadData();
}
catch (Exception ex) { Console.WriteLine("GetData: " + ex.Message); }
}
Firstly asynchronous methods on network streams are well known for loosing data or for never returning data!
In your case it could be the ProcessData call is blocking.
What you should do is to spawn a new background thread with a blocking listener (non asynchronous) and then use a new thread to read the data while the listener continues to listen.
I have an example here.
private static Socket s_chatListener;
public static void Listen(IPAddress LocalIPAddress, int Port)
{
IPEndPoint ipend = new IPEndPoint(LocalIPAddress, Port);
s_chatListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s_chatListener.Bind(ipend);
s_chatListener.Listen(10);
while (true)
{
Socket handler = s_chatListener.Accept();
ParameterizedThreadStart pst = new ParameterizedThreadStart(loadMessageFromSocket);
Thread t = new Thread(pst);
t.Start(handler);
}
}
private static void loadMessageFromSocket(object socket)
{
Socket handler = (Socket)socket;
string data = "";
while (true)
{
byte[] butes = new byte[1024];
int rec = handler.Receive(butes);
data += ASCIIEncoding.ASCII.GetString(butes);
if (data.IndexOf("\0") > -1)
break;
}
handler.Shutdown(SocketShutdown.Both);
handler.Close();
Console.Write(data);
}
Now just call the Listen Method from a new Thread in your main form or caller class.
Hope this helps.

Categories

Resources