void sendToClient(ThreadSafeStateObject state, MessageTO message) { BinaryFormatter serializer = new BinaryFormatter(); MemoryStream bytesToSend = new MemoryStream(); serializer.Serialize(bytesToSend, message); //bytesToSend.WriteByte(EOT); // add EOT before setting stream position bytesToSend.Position = 0; NetworkStream stream = new NetworkStream(state.Socket); byte[] header = System.Text.ASCIIEncoding.ASCII.GetBytes(String.Concat(bytesToSend.Length.ToString() + "|")); stream.Write(header, 0, header.Length); stream.Write(bytesToSend.GetBuffer(), 0, (Int32)bytesToSend.Length); stream.Flush(); try { state.Socket.Shutdown(SocketShutdown.Both); state.Socket.Close(); } catch (Exception exc) { //LOG.Error("An exception was caught trying to shut down a background server socket", exc); } }
void sendAckToClient(ThreadSafeStateObject state, string messageSize) { byte[] buffer = System.Text.Encoding.ASCII.GetBytes(messageSize); NetworkStream stream = new NetworkStream(state.Socket); stream.Write(buffer, 0, buffer.Length); stream.Flush(); }
void sendToClient(ThreadSafeStateObject state, string message) { MessageTO messageObject = new MessageTO() { Message = message }; sendToClient(state, messageObject); }
void acceptCallback(IAsyncResult iar) { SocketContainer srv = (SocketContainer)iar.AsyncState; if (!srv.Listening) { return; } Socket worker = null; try { // free up the main socket to accept requests immediately and assign socket to worker worker = srv.MainSocket.EndAccept(iar); // place main socket back in listening state for more connections this.SocketContainer.MainSocket.BeginAccept(new AsyncCallback(acceptCallback), this.SocketContainer); } catch { try { // wait and try again Thread.Sleep(100); // free up the main socket to accept requests immediately and assign socket to worker worker = this.SocketContainer.MainSocket.EndAccept(iar); // place main socket back in listening state for more connections this.SocketContainer.MainSocket.BeginAccept(new AsyncCallback(acceptCallback), this.SocketContainer); } catch { return; } // TODO: add thread safe logging to the reqhandle and log the beginaccept disposal } // copy reference to service state on our threadsafestateobject so shutdown can still be signaled ThreadSafeStateObject state = new ThreadSafeStateObject(worker, new byte[ThreadSafeStateObject.BufferSize]) { ServiceState = srv.ServiceState }; srv.AllDone.Set(); worker.BeginReceive(state.Buffer, 0, ThreadSafeStateObject.BufferSize, SocketFlags.None, new AsyncCallback(dataReceivedCallback), state); }
//void waitForData(StateObject state) //{ // state.Socket.BeginReceive(state.Buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(dataReceivedCallback), state); //} void dataReceivedCallback(IAsyncResult iar) { ThreadSafeStateObject state = (ThreadSafeStateObject)iar.AsyncState; Socket worker = state.Socket; try { int bytesRead = worker.EndReceive(iar); if (bytesRead == 0 && state.getMemoryStreamLength() == 0) { worker.Close(); return; } // first get length header int msgLength = 0; for (int i = 0; i < bytesRead; i++) { if (state.Buffer[i] == '\x7c') { msgLength = Convert.ToInt32(System.Text.ASCIIEncoding.ASCII.GetString(state.Buffer.Take(i).ToArray())); bytesRead = bytesRead - i - 1; // -1 for the pipe too break; } } state.Buffer = state.Buffer.Skip(msgLength.ToString().Length + 1).ToArray(); // now reset chunk to skip the header state.addBytesToMemoryStream(state.Buffer, bytesRead); state.Buffer = new byte[ThreadSafeStateObject.BufferSize]; while (state.getMemoryStreamLength() < msgLength) // while not EOT { bytesRead = worker.Receive(state.Buffer); state.addBytesToMemoryStream(state.Buffer, bytesRead); state.Buffer = new byte[ThreadSafeStateObject.BufferSize]; } //state.IsEOT = false; BinaryFormatter bf = new BinaryFormatter(); //state.BytesInMemory.Position = 0; // set position in stream to zero so deserialization succeeds byte[] bytes = state.getMemoryStream(); Stream memStream = new MemoryStream(bytes); memStream.Position = 0; MessageTO messageTO = (MessageTO)(bf.Deserialize(memStream)); sendToClient(state, RequestHandler.getInstance().handleRequest(messageTO, this)); // pass this because some methods use the properties and requesthandler is a singleton and not unique among threads // this is our hook for thread safety mentioned in RequestHandler // before returning check to see if shutdown signal was set if (messageTO.MessageType == MessageTypeTO.StopServerRequest) // this.ServiceState != null && this.ServiceState.Status == ServiceStatus.STOPPED) { if (state.ServiceState != null) { state.ServiceState.Status = ServiceStatus.STOPPED; } stopListener(); } } catch (Exception) { //LOG.Error("An unrecoverable error occurred while sending/receiving data", exc); try { worker.Shutdown(SocketShutdown.Both); worker.Close(); } catch (Exception) { } } }