private byte[] GetWebsocketMessageData(WebsocketPipeMessageInfo msg) { MemoryStream strm = new MemoryStream(); System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); try { DataSocket.WriteMessage(msg, strm); } catch (Exception ex) { var str = "Error while writing to data socket: " + ex.Message; WriteLogMessage(null, str); throw new Exception(str, ex); } watch.Stop(); WriteLogTimeMessage(null, "Write to datasocket, ", watch.Elapsed.TotalMilliseconds); byte[] data = strm.ToArray(); strm.Close(); strm.Dispose(); return(data); }
/// <summary> /// Writes the message to a memory mapped file, where the memory mapped file name is WebsocketPipe.Address + id. /// mmf format: [wasread? 1 byte][datasize(int)][length(int)][msg][length(int)][msg]... /// If wasread=0, then writes the new message to the end of the message list and advances the number of messages +1. /// If wasread=1, clears the mmf and then writes the new message. /// </summary> /// <param name="wp">The calling WebsocketPipe</param> /// <param name="msg">The message to write.</param> /// <param name="to">The stream to write the mmf filename to.</param> /// <param name="id">The id of the targer we are writing to, since there may be many we open a mmf for each</param> public virtual void WriteMessage(WebsocketPipeMessageInfo msg, Stream to) { if (msg.Data.Length < this.UseInternalPacketDataSendingIfMsgByteSizeIsLessThen) { // write that this is an internal message. to.WriteByte(1); WebsocketAsInternalDataSocket.WriteMessage(msg, to); return; } // write that this is a mmf msg. to.WriteByte(0); // make the id and write it to the stream. string id = MakeValidMmfID(msg.DataSocketId); byte[] mmfnamebuffer = ASCIIEncoding.ASCII.GetBytes(id); to.Write(mmfnamebuffer, 0, mmfnamebuffer.Length); Mutex mu = new Mutex(false, id + "_mutex"); if (!mu.WaitOne(MemoryMappedFileAccessTimeout)) { throw new Exception("Memory mapped file access timedout."); } // The data size for a single message. int totalDataSize = msg.Data.Length + sizeof(int) + 1; // Creating/Opening the stream. MemoryMappedViewStream strm = GetDataWritingMemoryMappedViewStream(id, ref totalDataSize); // we are at the position of the write, and are ready for the message write. msg.WriteToStream(strm); strm.Flush(); strm.Close(); strm.Dispose(); strm = null; // release the mutex. mu.ReleaseMutex(); }
public virtual IEnumerable <WebsocketPipeMessageInfo> ReadMessages(Stream from) { return(new WebsocketPipeMessageInfo[] { WebsocketPipeMessageInfo.FromStream(from) }); }
public virtual void WriteMessage(WebsocketPipeMessageInfo msg, Stream to) { msg.WriteToStream(to); }
/// <summary> /// Reads the pending messages in the memory mapped file, where the memory mapped file name is in the stream from. /// mmf format: [wasread? 1 byte][datasize(int)][length(int)][msg][length(int)][msg]... /// If wasread=1, then ignores the read since the mmf was not written to, or was already read. /// If wasread=0, reads all pending messages and sets wasread to 1. /// </summary> /// <param name="wp"></param> /// <param name="from"></param> /// <returns></returns> public virtual IEnumerable <WebsocketPipeMessageInfo> ReadMessages(Stream from) { // reading the memory mapped file name or the msg bytes. if (from.ReadByte() == 1) { // internal message. return(WebsocketAsInternalDataSocket.ReadMessages(from)); } // read the id from the from stram. StreamReader freader = new StreamReader(from, ASCIIEncoding.ASCII); string id = freader.ReadToEnd(); // calling the mutex to verify reading. Mutex mu = new Mutex(false, id + "_mutex"); if (!mu.WaitOne(MemoryMappedFileAccessTimeout)) { throw new Exception("Wait timeout while attempting to read messages from mmf file with id: " + id); } MemoryMappedFile mmf = MemoryMappedFile.OpenExisting(id); Stream strm = mmf.CreateViewStream(0, 0, MemoryMappedFileAccess.ReadWrite); BinaryReader reader = new BinaryReader(strm); strm.Seek(0, SeekOrigin.Begin); BinaryReader msgreader = null; int totalDataLength = 0; if (strm.Length > MMFHeaderSize && reader.ReadByte() == 0) { // there is something we need to read. // reading all the contents. totalDataLength = reader.ReadInt32(); if (totalDataLength > 0) { msgreader = new BinaryReader(new MemoryStream(reader.ReadBytes(totalDataLength))); } // marking as read. strm.Seek(0, SeekOrigin.Begin); strm.WriteByte(1); } strm.Flush(); strm.Close(); strm.Dispose(); // clearing the newly created mmf. mmf.Dispose(); mmf = null; // release the mutex allowing others to write. mu.ReleaseMutex(); mu.Dispose(); mu = null; reader = null; // return nothing... if (msgreader == null) { return(new WebsocketPipeMessageInfo[0]); } // reading the messages. strm = msgreader.BaseStream; msgreader.BaseStream.Seek(0, SeekOrigin.Begin); List <WebsocketPipeMessageInfo> msgs = new List <WebsocketPipeMessageInfo>(); while (strm.Position < totalDataLength) { WebsocketPipeMessageInfo info = WebsocketPipeMessageInfo.FromStream(msgreader); if (info == null) { break; // something went wrong. } msgs.Add(info); } strm.Close(); strm.Dispose(); msgreader = null; strm = null; return(msgs); }
/// <summary> /// Sends a message to sepcific clients by the client id. Method should be used for servers. /// </summary> /// <param name="msg">The message to send</param> /// <param name="clientIds">The client ids to send the msg to, if a server.</param> /// /// <param name="response">If not null, the thread will wait for response.</param> public void Send(TMessage msg, string[] clientIds, Action <TMessage> response = null) { //if (clientIds != null && WS != null) // throw new Exception("You are trying to send a message to specific clients from a client WebsocketPipe. This is not A server."); if (WSServer == null && WS == null) { throw new Exception("Not connected to any server or listening for connections. Please call either Connect, or Listen."); } Stopwatch watch = new Stopwatch(); WebsocketPipeMessageInfo minfo; watch.Start(); try { minfo = new WebsocketPipeMessageInfo(Serializer.ToBytes <TMessage>(msg), null, response != null); } catch (Exception ex) { var str = "Error serializing message. " + ex.Message; WriteLogMessage(null, str); throw new Exception(str, ex); } watch.Stop(); WriteLogTimeMessage(null, "Serialized msg with " + minfo.Data.Length + " [bytes]", watch.Elapsed.TotalMilliseconds); var senders = new[] { new { socketID = "", handlerID = "", session = (WebSocket)null, hndl = (ResponseWaitHandle)null, } }.ToList(); senders.Clear(); if (WS != null) { senders.Add(new { socketID = ToDataSocketID(SendAsClientWebsocketID), handlerID = SendAsClientWebsocketID, session = WS, hndl = new ResponseWaitHandle(), }); } else { foreach (WebSocketSharp.Server.IWebSocketSession session in FindValidSession(clientIds)) { senders.Add(new { socketID = ToDataSocketID(session.ID), handlerID = session.ID, session = session.Context.WebSocket, hndl = new ResponseWaitHandle(), }); } } if (senders.Count == 0) { if (response != null) { response(null); } return; // nothing to do. } if (response == null) { foreach (var sender in senders) { minfo.DataSocketId = sender.socketID; sender.session.Send(GetWebsocketMessageData(minfo)); //sender.session.SendAsync(GetWebsocketMessageData(minfo), (t) => { }); } } else { foreach (var sender in senders) { PendingResponseWaitHandles[sender.socketID] = sender.hndl; } foreach (var sender in senders) { minfo.DataSocketId = sender.socketID; sender.session.Send(GetWebsocketMessageData(minfo)); //sender.session.SendAsync(GetWebsocketMessageData(minfo), (t) => //{ // if (!t) // { // // not complete sending. // // error. // // response is null. // sender.hndl.Response = null; // sender.hndl.Set(); // } //}); } bool timedout = false; foreach (var sender in senders) { if (!sender.hndl.WaitOne(WaitTimeout)) { timedout = true; } } // check if timeout. //bool timedout = senders.Any(s => s.hndl.WaitOne(0)); if (timedout) { throw new Exception("Timedout waiting for response. Waited [ms] " + WaitTimeout.TotalMilliseconds); } foreach (var sender in senders) { response(sender.hndl.Response); } } }