/// <summary> /// This tries to fill requests with text on hand and then, if there are still /// requests remaining, requests more data from the underlying socket. /// </summary> private void ProcessReceiveQueue() { lock (receiveRequests) { // For each complete line of text, invoke the corresponding callback. while (receivedLines.Count() > 0 && receiveRequests.Count() > 0) { String line = receivedLines.Dequeue(); ReceiveRequest req = receiveRequests.Dequeue(); ThreadPool.QueueUserWorkItem(x => req.Callback(line, null, req.Payload)); } // If any unserviced requests remain, request more bytes. while (receiveRequests.Count > 0) { try { socket.BeginReceive(receiveBytes, 0, receiveBytes.Length, SocketFlags.None, BytesReceived, null); break; } catch (Exception e) { ReceiveRequest req = receiveRequests.Dequeue(); ThreadPool.QueueUserWorkItem(x => req.Callback(null, e, req.Payload)); incompleteLine = ""; } } } }
/// <summary> /// This tries to fill requests with text on hand and then, if there are still /// requests remaining, requests more data from the underlying socket. /// </summary> private void ProcessReceiveQueue() { lock (receiveRequests) { // While there is sufficient text, service the callbacks. while (receiveRequests.Count() > 0) { // Deal with a line request if (receiveRequests.Peek().Length <= 0) { if (receivedLines.Count > 0) { String line = receivedLines.Dequeue(); ReceiveRequest req = receiveRequests.Dequeue(); ThreadPool.QueueUserWorkItem(x => req.Callback(line, null, req.Payload)); } else { break; } } // Deal with a character request else { string chunk = ExtractChunk(receiveRequests.Peek().Length); if (chunk != null) { ReceiveRequest req = receiveRequests.Dequeue(); ThreadPool.QueueUserWorkItem(x => req.Callback(chunk, null, req.Payload)); } else { break; } } } // If any unserviced requests remain, request more bytes. while (receiveRequests.Count > 0) { try { socket.BeginReceive(receiveBytes, 0, receiveBytes.Length, SocketFlags.None, BytesReceived, null); break; } catch (Exception e) { ReceiveRequest req = receiveRequests.Dequeue(); ThreadPool.QueueUserWorkItem(x => req.Callback(null, e, req.Payload)); incompleteLine = ""; } } } }
/// <summary> /// This private method is the callback for the receive attempts. /// </summary> private void BytesReceived(IAsyncResult ar) { // Get the number of bytes received. int count; try { count = socket.EndReceive(ar); } catch (Exception e) { ReceiveRequest req = receiveRequests.Dequeue(); ThreadPool.QueueUserWorkItem(x => req.Callback(null, e, req.Payload)); ProcessReceiveQueue(); incompleteLine = ""; return; } // If no bytes were received, this means that the remote socket has // shut down. Send a null to the callback to signal this. if (count == 0) { receivedLines.Enqueue(null); ProcessReceiveQueue(); } // If bytes were received, save them. else { //incompleteLine += encoding.GetString(receiveBytes, 0, count); int charsRead = decoder.GetChars(receiveBytes, 0, count, receiveChars, 0, false); incompleteLine += new String(receiveChars, 0, charsRead); // Extract all complete lines of text and put into the ReceivedLines queue int lineEnd, lineStart = 0; while ((lineEnd = incompleteLine.IndexOf('\n', lineStart)) >= 0) { receivedLines.Enqueue(incompleteLine.Substring(lineStart, lineEnd - lineStart)); lineStart = lineEnd + 1; } incompleteLine = incompleteLine.Substring(lineStart); // Try to fill requests with the new data ProcessReceiveQueue(); } }