void SendData(CodedOutputStream writer, SendQueueEntry data) { // Write to a temp buffer so we can inspect what we send var stream = new MemoryStream(); var temp_writer = CodedOutputStream.CreateInstance(stream); temp_writer.WriteRawByte(data.ServiceId); temp_writer.WriteUInt32NoTag(data.MethodId); temp_writer.WriteFixedUInt16(data.RequestId); if (data.ListenerId.HasValue) { temp_writer.WriteUInt32NoTag(data.ListenerId.Value); } temp_writer.WriteMessageNoTag(data.Message); temp_writer.Flush(); var buffer = stream.ToArray(); //Debug.WriteLine("Sending data: "); //Debug.WriteLine(buffer.ToHexString()); writer.WriteRawBytes(buffer); writer.Flush(); }
void WriteLoop() { var writer = CodedOutputStream.CreateInstance(socket.GetStream()); while (socket.Connected) { try { SendQueueEntry send_data = null; lock (sendQueue) { // Wait for messages in the send queue while (sendQueue.Count == 0) { Monitor.Wait(sendQueue); } send_data = sendQueue.Dequeue(); } SendData(writer, send_data); } catch (Exception e) { Disconnect(e.Message); } } }
private void SenderThread() { // mark this thread as a background thread Thread.CurrentThread.IsBackground = true; Thread.CurrentThread.Name = "Dataset sender thread"; // keep track of client to remove List <IPEndPoint> removeList = new List <IPEndPoint>(); // enter the send queue lock Monitor.Enter(sendQueue); while (true) { if (sendQueue.Count == 0) { Monitor.Wait(sendQueue); } // assume that now there is an entry in the queue if (sendQueue.Count > 0) { // dequeue the entry SendQueueEntry entry = sendQueue.Dequeue(); // fill up the buffer until we're at our target size while (sendQueue.Count > 0) { SendQueueEntry nextEntry = sendQueue.Peek(); if (entry.length + nextEntry.length <= target_packet_size) { // add in this entry // actually dequeue the entry sendQueue.Dequeue(); // copy the next entry into our working buffer Buffer.BlockCopy(nextEntry.buffer, 0, entry.buffer, entry.length, nextEntry.length); // update the entry length entry.length += nextEntry.length; // free the next entry buffer FreeBuffer(nextEntry.buffer); } else { // leave the loop, adding the next packet would go over the target size break; } } // increment the packet count and byte count packetCount++; // release the lock Monitor.Exit(sendQueue); try { // acquire a reader lock using (ReaderLock rl = new ReaderLock(listenerRWLock)) { // clear the remove list removeList.Clear(); // iterate through the listeners and send to each of them foreach (IPEndPoint listener in listenerEndPoints) { try { sender.SendTo(entry.buffer, entry.length, SocketFlags.None, listener); byteCount += entry.length; } catch (Exception) { // for any client error, add to the remove list removeList.Add(listener); } } // if there are listeners to remove, acquire a writer lock and remove them // only wait for 20 milliseconds to get the writer lock to avoid blocking using (WriterLock wl = rl.UpgradeToWriter(20)) { foreach (IPEndPoint ep in removeList) { listenerEndPoints.Remove(ep); } } doSendDataValues = listenerEndPoints.Count > 0; } } catch (Exception) { // ignore any exceptions } finally { // re-enter the send queue lock Monitor.Enter(sendQueue); } // free the buffer entry FreeBuffer(entry.buffer); } } }