예제 #1
0
        /// <summary>
        /// We can read a string from the StringSocket by doing
        ///
        ///     ss.BeginReceive(callback, payload)
        ///
        /// where callback is a ReceiveCallback (see below) and payload is an arbitrary object.
        /// This is non-blocking, asynchronous operation.  When the StringSocket has read a
        /// string of text terminated by a newline character from the underlying Socket, or
        /// failed in the attempt, it invokes the callback.  The parameters to the callback are
        /// a (possibly null) string, a (possibly null) Exception, and the payload.  Either the
        /// string or the Exception will be non-null, but nor both.  If the string is non-null,
        /// it is the requested string (with the newline removed).  If the Exception is non-null,
        /// it is the Exception that caused the send attempt to fail.
        ///
        /// This method is non-blocking.  This means that it does not wait until a line of text
        /// has been received before returning.  Instead, it arranges for a line to be received
        /// and then returns.  When the line is actually received (at some time in the future), the
        /// callback is called on another thread.
        ///
        /// This method is thread safe.  This means that multiple threads can call BeginReceive
        /// on a shared socket without worrying around synchronization.  The implementation of
        /// BeginReceive must take care of synchronization instead.  On a given StringSocket, each
        /// arriving line of text must be passed to callbacks in the order in which the corresponding
        /// BeginReceive call arrived.
        ///
        /// Note that it is possible for there to be incoming bytes arriving at the underlying Socket
        /// even when there are no pending callbacks.  StringSocket implementations should refrain
        /// from buffering an unbounded number of incoming bytes beyond what is required to service
        /// the pending callbacks.
        ///
        /// <param name="callback"> The function to call upon receiving the data</param>
        /// <param name="payload">
        /// The payload is "remembered" so that when the callback is invoked, it can be associated
        /// with a specific Begin Receiver....
        /// </param>
        ///
        /// <example>
        ///   Here is how you might use this code:
        ///   <code>
        ///                    client = new TcpClient("localhost", port);
        ///                    Socket       clientSocket = client.Client;
        ///                    StringSocket receiveSocket = new StringSocket(clientSocket, new UTF8Encoding());
        ///                    receiveSocket.BeginReceive(CompletedReceive1, 1);
        ///
        ///   </code>
        /// </example>
        /// </summary>
        public void BeginReceive(ReceiveCallback callback, object payload)
        {
            // Store the receive request, with its specified callback and payload.
            ReceiveRequest receiveRequest = new ReceiveRequest(callback, payload);

            ReceiveQueue.Enqueue(receiveRequest);

            // Ask the socket to call MessageReceive as soon as up to 1024 bytes arrive.
            byte[] buffer = new byte[1024];//this should work when this is set to a small number
            socket.BeginReceive(buffer, 0, buffer.Length,
                                SocketFlags.None, MessageReceived, buffer);
        }
예제 #2
0
        /// <summary>
        /// We can read a string from the StringSocket by doing
        ///
        ///     ss.BeginReceive(callback, payload)
        ///
        /// where callback is a ReceiveCallback (see below) and payload is an arbitrary object.
        /// This is non-blocking, asynchronous operation.  When the StringSocket has read a
        /// string of text terminated by a newline character from the underlying Socket, or
        /// failed in the attempt, it invokes the callback.  The parameters to the callback are
        /// a (possibly null) string, a (possibly null) Exception, and the payload.  Either the
        /// string or the Exception will be non-null, but nor both.  If the string is non-null,
        /// it is the requested string (with the newline removed).  If the Exception is non-null,
        /// it is the Exception that caused the send attempt to fail.
        ///
        /// This method is non-blocking.  This means that it does not wait until a line of text
        /// has been received before returning.  Instead, it arranges for a line to be received
        /// and then returns.  When the line is actually received (at some time in the future), the
        /// callback is called on another thread.
        ///
        /// This method is thread safe.  This means that multiple threads can call BeginReceive
        /// on a shared socket without worrying around synchronization.  The implementation of
        /// BeginReceive must take care of synchronization instead.  On a given StringSocket, each
        /// arriving line of text must be passed to callbacks in the order in which the corresponding
        /// BeginReceive call arrived.
        ///
        /// Note that it is possible for there to be incoming bytes arriving at the underlying Socket
        /// even when there are no pending callbacks.  StringSocket implementations should refrain
        /// from buffering an unbounded number of incoming bytes beyond what is required to service
        /// the pending callbacks.
        ///
        /// <param name="callback"> The function to call upon receiving the data</param>
        /// <param name="payload">
        /// The payload is "remembered" so that when the callback is invoked, it can be associated
        /// with a specific Begin Receiver....
        /// </param>
        ///
        /// <example>
        ///   Here is how you might use this code:
        ///   <code>
        ///                    client = new TcpClient("localhost", port);
        ///                    Socket       clientSocket = client.Client;
        ///                    StringSocket receiveSocket = new StringSocket(clientSocket, new UTF8Encoding());
        ///                    receiveSocket.BeginReceive(CompletedReceive1, 1);
        ///
        ///   </code>
        /// </example>
        /// </summary>
        public void BeginReceive(ReceiveCallback callback, object payload)
        {
            // Protect the ReceiveQueue
            lock (ReceiveQueue)
            {
                // Create and store the receive request.
                ReceiveRequest receiveRequest = new ReceiveRequest(callback, payload);
                ReceiveQueue.Enqueue(receiveRequest);

                // If there is no receive ongoing, start receiving.
                if (ReceiveQueue.Count == 1)
                {
                    ProcessReceivedMessage();
                }
            }
        }
예제 #3
0
        /// <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();
            }
        }