NetworkStream.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / Net / System / Net / Sockets / NetworkStream.cs / 3 / NetworkStream.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Net.Sockets { 
    using System.IO; 
    using System.Runtime.InteropServices;
    using System.Threading; 
    using System.Security.Permissions;

    /// 
    ///     
    ///       Provides the underlying stream of data for network access.
    ///     
    ///  
    public class NetworkStream : Stream {
        ///  
        ///    
        ///       Used by the class to hold the underlying socket the stream uses.
        ///    
        ///  
        private Socket    m_StreamSocket;
 
        ///  
        ///    
        ///       Used by the class to indicate that the stream is m_Readable. 
        ///    
        /// 
        private bool      m_Readable;
 
        /// 
        ///     
        ///       Used by the class to indicate that the stream is writable. 
        ///    
        ///  
        private bool      m_Writeable;

        private bool      m_OwnsSocket;
 
        /// 
        /// Creates a new instance of the  without initalization. 
        ///  
        internal NetworkStream() {
            m_OwnsSocket = true; 
        }


        // Can be constructed directly out of a socket 
        /// 
        /// Creates a new instance of the  class for the specified . 
        ///  
        public NetworkStream(Socket socket) {
#if DEBUG 
            using (GlobalLog.SetThreadKind(ThreadKinds.User)) {
#endif
            if (socket == null) {
                throw new ArgumentNullException("socket"); 
            }
            InitNetworkStream(socket, FileAccess.ReadWrite); 
#if DEBUG 
            }
#endif 
        }

        //UEUE (see FileStream)
        // ownsHandle: true if the file handle will be owned by this NetworkStream instance; otherwise, false. 
        public NetworkStream(Socket socket, bool ownsSocket) {
#if DEBUG 
            using (GlobalLog.SetThreadKind(ThreadKinds.User)) { 
#endif
            if (socket == null) { 
                throw new ArgumentNullException("socket");
            }
            InitNetworkStream(socket, FileAccess.ReadWrite);
            m_OwnsSocket = ownsSocket; 
#if DEBUG
            } 
#endif 
        }
 
        internal NetworkStream(NetworkStream networkStream, bool ownsSocket) {
            Socket socket = networkStream.Socket;
            if (socket == null) {
                throw new ArgumentNullException("networkStream"); 
            }
            InitNetworkStream(socket, FileAccess.ReadWrite); 
            m_OwnsSocket = ownsSocket; 
        }
 
        // Create with a socket and access mode
        /// 
        /// Creates a new instance of the  class for the specified  with the specified access rights.
        ///  
        public NetworkStream(Socket socket, FileAccess access) {
#if DEBUG 
            using (GlobalLog.SetThreadKind(ThreadKinds.User)) { 
#endif
            if (socket == null) { 
                throw new ArgumentNullException("socket");
            }
            InitNetworkStream(socket, access);
#if DEBUG 
            }
#endif 
        } 
        public NetworkStream(Socket socket, FileAccess access, bool ownsSocket) {
#if DEBUG 
            using (GlobalLog.SetThreadKind(ThreadKinds.User)) {
#endif
            if (socket == null) {
                throw new ArgumentNullException("socket"); 
            }
            InitNetworkStream(socket, access); 
            m_OwnsSocket = ownsSocket; 
#if DEBUG
            } 
#endif
        }

        // 
        // Socket - provides access to socket for stream closing
        // 
        protected Socket Socket { 
            get {
                return m_StreamSocket; 
            }
        }

        internal Socket InternalSocket { 
            get {
                Socket chkSocket = m_StreamSocket; 
                if (m_CleanedUp || chkSocket == null) { 
                    throw new ObjectDisposedException(this.GetType().FullName);
                } 

                return chkSocket;
            }
        } 

        internal void ConvertToNotSocketOwner() { 
            m_OwnsSocket = false; 
            // Suppress for finialization still allow proceed the requests
            GC.SuppressFinalize(this); 
        }

        /// 
        ///     
        ///       Used by the class to indicate that the stream is m_Readable.
        ///     
        ///  
        protected bool Readable {
            get { 
                return m_Readable;
            }
            set {
                m_Readable = value; 
            }
        } 
 
        /// 
        ///     
        ///       Used by the class to indicate that the stream is writable.
        ///    
        /// 
        protected bool Writeable { 
            get {
                return m_Writeable; 
            } 
            set {
                m_Writeable = value; 
            }
        }

 
        /// 
        ///     
        ///       Indicates that data can be read from the stream. 
        ///         We return the readability of this stream. This is a read only property.
        ///     
        /// 
        public override bool CanRead {
            get {
                return m_Readable; 
            }
        } 
 

        ///  
        ///    
        ///       Indicates that the stream can seek a specific location
        ///       in the stream. This property always returns 
        ///       . 
        ///    
        ///  
        public override bool CanSeek { 
            get {
                return false; 
            }
        }

 
        /// 
        ///     
        ///       Indicates that data can be written to the stream. 
        ///    
        ///  
        public override bool CanWrite {
            get {
                return m_Writeable;
            } 
        }
 
 
        /// 
        ///    Indicates whether we can timeout 
        /// 
        public override bool CanTimeout {
            get {
                return true; // should we check for Connected state? 
            }
        } 
 

        ///  
        ///    Set/Get ReadTimeout, note of a strange behavior, 0 timeout == infinite for sockets,
        ///         so we map this to -1, and if you set 0, we cannot support it
        /// 
        public override int ReadTimeout { 
            get {
#if DEBUG 
                using (GlobalLog.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) { 
#endif
                int timeout = (int)m_StreamSocket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout); 
                if (timeout == 0) {
                    return -1;
                }
                return timeout; 
#if DEBUG
                } 
#endif 
            }
            set { 
#if DEBUG
                using (GlobalLog.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) {
#endif
                if (value<=0 && value!=System.Threading.Timeout.Infinite) { 
                    throw new ArgumentOutOfRangeException(SR.GetString(SR.net_io_timeout_use_gt_zero));
                } 
                SetSocketTimeoutOption(SocketShutdown.Receive, value, false); 
#if DEBUG
                } 
#endif
            }
        }
 
        /// 
        ///    Set/Get WriteTimeout, note of a strange behavior, 0 timeout == infinite for sockets, 
        ///         so we map this to -1, and if you set 0, we cannot support it 
        /// 
 	    public override int WriteTimeout { 
            get {
#if DEBUG
                using (GlobalLog.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) {
#endif 
                int timeout = (int)m_StreamSocket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout);
                if (timeout == 0) { 
                    return -1; 
                }
                return timeout; 
#if DEBUG
                }
#endif
            } 
            set {
#if DEBUG 
                using (GlobalLog.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) { 
#endif
                if (value <= 0 && value != System.Threading.Timeout.Infinite) { 
                    throw new ArgumentOutOfRangeException(SR.GetString(SR.net_io_timeout_use_gt_zero));
                }
                SetSocketTimeoutOption(SocketShutdown.Send, value, false);
#if DEBUG 
                }
#endif 
            } 
        }
 
        /// 
        ///    
        ///       Indicates data is available on the stream to be read.
        ///         This property checks to see if at least one byte of data is currently available 
        ///    
        ///  
        public virtual bool DataAvailable { 
            get {
#if DEBUG 
                using (GlobalLog.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) {
#endif
                if (m_CleanedUp){
                    throw new ObjectDisposedException(this.GetType().FullName); 
                }
 
                Socket chkStreamSocket = m_StreamSocket; 
                if(chkStreamSocket == null) {
                    throw new IOException(SR.GetString(SR.net_io_readfailure, SR.GetString(SR.net_io_connectionclosed))); 
                }

                // Ask the socket how many bytes are available. If it's
                // not zero, return true. 

                return chkStreamSocket.Available != 0; 
#if DEBUG 
                }
#endif 
            }
        }

 
        /// 
        ///     
        ///       The length of data available on the stream. Always throws . 
        ///    
        ///  
        public override long Length {
            get {
                throw new NotSupportedException(SR.GetString(SR.net_noseek));
            } 
        }
 
        ///  
        ///    
        ///       Gets or sets the position in the stream. Always throws . 
        ///    
        /// 
        public override long Position {
            get { 
                throw new NotSupportedException(SR.GetString(SR.net_noseek));
            } 
 
            set {
                throw new NotSupportedException(SR.GetString(SR.net_noseek)); 
            }
        }

 
        /// 
        ///     
        ///       Seeks a specific position in the stream. This method is not supported by the 
        ///     class.
        ///     
        /// 
        public override long Seek(long offset, SeekOrigin origin) {
            throw new NotSupportedException(SR.GetString(SR.net_noseek));
        } 

 
        /*++ 

            InitNetworkStream - initialize a network stream. 

            This is the common NetworkStream constructor, called whenever a
            network stream is created. We validate the socket, set a few
            options, and call our parent's initializer. 

            Input: 
 
                S           - Socket to be used.
                Access      - Access type desired. 


            Returns:
 
                Nothing, but may throw an exception.
        --*/ 
 
        internal void InitNetworkStream(Socket socket, FileAccess Access) {
            // 
            // parameter validation
            //
            if (!socket.Blocking) {
                throw new IOException(SR.GetString(SR.net_sockets_blocking)); 
            }
            if (!socket.Connected) { 
                throw new IOException(SR.GetString(SR.net_notconnected)); 
            }
            if (socket.SocketType != SocketType.Stream) { 
                throw new IOException(SR.GetString(SR.net_notstream));
            }

            m_StreamSocket = socket; 

            switch (Access) { 
                case FileAccess.Read: 
                    m_Readable = true;
                    break; 
                case FileAccess.Write:
                    m_Writeable = true;
                    break;
                case FileAccess.ReadWrite: 
                default: // assume FileAccess.ReadWrite
                    m_Readable = true; 
                    m_Writeable = true; 
                    break;
            } 

        }

        internal bool PollRead() { 
            if (m_CleanedUp) {
                return false; 
            } 
            Socket chkStreamSocket = m_StreamSocket;
            if (chkStreamSocket == null) { 
                return false;
            }
            return chkStreamSocket.Poll(0, SelectMode.SelectRead);
        } 

        internal bool Poll(int microSeconds, SelectMode mode) { 
            if (m_CleanedUp){ 
                throw new ObjectDisposedException(this.GetType().FullName);
            } 

            Socket chkStreamSocket = m_StreamSocket;
            if (chkStreamSocket == null) {
                throw new IOException(SR.GetString(SR.net_io_readfailure, SR.GetString(SR.net_io_connectionclosed))); 
            }
 
            return chkStreamSocket.Poll(microSeconds, mode); 
        }
 

        /*++
            Read - provide core Read functionality.
 
            Provide core read functionality. All we do is call through to the
            socket Receive functionality. 
 
            Input:
 
                Buffer  - Buffer to read into.
                Offset  - Offset into the buffer where we're to read.
                Count   - Number of bytes to read.
 
            Returns:
 
                Number of bytes we read, or 0 if the socket is closed. 

        --*/ 

        /// 
        ///    
        ///       Reads data from the stream. 
        ///    
        ///  
        //UEUE 
        public override int Read([In, Out] byte[] buffer, int offset, int size) {
#if DEBUG 
            using (GlobalLog.SetThreadKind(ThreadKinds.User | ThreadKinds.Sync)) {
#endif
            if (m_CleanedUp){
                throw new ObjectDisposedException(this.GetType().FullName); 
            }
            // 
            // parameter validation 
            //
            if (buffer==null) { 
                throw new ArgumentNullException("buffer");
            }
            if (offset<0 || offset>buffer.Length) {
                throw new ArgumentOutOfRangeException("offset"); 
            }
            if (size<0 || size>buffer.Length-offset) { 
                throw new ArgumentOutOfRangeException("size"); 
            }
            if (!CanRead) { 
                throw new InvalidOperationException(SR.GetString(SR.net_writeonlystream));
            }

 
            Socket chkStreamSocket = m_StreamSocket;
            if (chkStreamSocket == null) { 
                throw new IOException(SR.GetString(SR.net_io_readfailure, SR.GetString(SR.net_io_connectionclosed))); 
            }
 
            try {
                int bytesTransferred = chkStreamSocket.Receive(buffer, offset, size, 0);
                return bytesTransferred;
            } 
            catch (Exception exception) {
                if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) { 
                    throw; 
	            }
 
                //
                // some sort of error occured on the socket call,
                // set the SocketException as InnerException and throw
                // 
                throw new IOException(SR.GetString(SR.net_io_readfailure, exception.Message), exception);
            } 
#if DEBUG 
            }
#endif 
        }

        /*++
            Write - provide core Write functionality. 

            Provide core write functionality. All we do is call through to the 
            socket Send method.. 

            Input: 

                Buffer  - Buffer to write from.
                Offset  - Offset into the buffer from where we'll start writing.
                Count   - Number of bytes to write. 

            Returns: 
 
                Number of bytes written. We'll throw an exception if we
                can't write everything. It's brutal, but there's no other 
                way to indicate an error.
        --*/

        ///  
        ///    
        ///       Writes data to the stream.. 
        ///     
        /// 
        public override void Write(byte[] buffer, int offset, int size) { 
#if DEBUG
            using (GlobalLog.SetThreadKind(ThreadKinds.User | ThreadKinds.Sync)) {
#endif
            if (m_CleanedUp){ 
                throw new ObjectDisposedException(this.GetType().FullName);
            } 
            // 
            // parameter validation
            // 
            if (buffer==null) {
                throw new ArgumentNullException("buffer");
            }
            if (offset<0 || offset>buffer.Length) { 
                throw new ArgumentOutOfRangeException("offset");
            } 
            if (size<0 || size>buffer.Length-offset) { 
                throw new ArgumentOutOfRangeException("size");
            } 
            if (!CanWrite) {
                throw new InvalidOperationException(SR.GetString(SR.net_readonlystream));
            }
 

            Socket chkStreamSocket = m_StreamSocket; 
            if(chkStreamSocket == null) { 
                throw new IOException(SR.GetString(SR.net_io_writefailure, SR.GetString(SR.net_io_connectionclosed)));
            } 

            try {
                //
                // since the socket is in blocking mode this will always complete 
                // after ALL the requested number of bytes was transferred
                // 
                chkStreamSocket.Send(buffer, offset, size, SocketFlags.None); 
            }
            catch (Exception exception) { 
                if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) {
                    throw;
	            }
 
                //
                // some sort of error occured on the socket call, 
                // set the SocketException as InnerException and throw 
                //
                throw new IOException(SR.GetString(SR.net_io_writefailure, exception.Message), exception); 
            }
            catch {
                //
                // some sort of error occured on the socket call, 
                // set the SocketException as InnerException and throw
                // 
                throw new IOException(SR.GetString(SR.net_io_writefailure, string.Empty), new Exception(SR.GetString(SR.net_nonClsCompliantException))); 
            }
#if DEBUG 
            }
#endif
        }
 
        private int m_CloseTimeout = Socket.DefaultCloseTimeout; // 1 ms; -1 = respect linger options
 
        public void Close(int timeout) { 
#if DEBUG
            using (GlobalLog.SetThreadKind(ThreadKinds.User | ThreadKinds.Sync)) { 
#endif
            if (timeout < -1) {
                throw new ArgumentOutOfRangeException("timeout");
            } 
            m_CloseTimeout = timeout;
            Close(); 
#if DEBUG 
            }
#endif 
        }

        private bool m_CleanedUp = false;
        protected override void Dispose(bool disposing) { 
#if DEBUG
            using (GlobalLog.SetThreadKind(ThreadKinds.User)) { 
#endif 
            if (!m_CleanedUp && disposing) {
                // 
                // only resource we need to free is the network stream, since this
                // is based on the client socket, closing the stream will cause us
                // to flush the data to the network, close the stream and (in the
                // NetoworkStream code) close the socket as well. 
                //
                if (m_StreamSocket!=null) { 
                    m_Readable = false; 
                    m_Writeable = false;
                    if (m_OwnsSocket) { 
                        //
                        // if we own the Socket (false by default), close it
                        // ignoring possible exceptions (eg: the user told us
                        // that we own the Socket but it closed at some point of time, 
                        // here we would get an ObjectDisposedException)
                        // 
                        Socket chkStreamSocket = m_StreamSocket; 
                        if (chkStreamSocket!=null) {
                            chkStreamSocket.InternalShutdown(SocketShutdown.Both); 
                            chkStreamSocket.Close(m_CloseTimeout);
                        }
                    }
                } 
            }
            m_CleanedUp = true; 
#if DEBUG 
            }
#endif 
            base.Dispose(disposing);
        }

        ~NetworkStream() { 
#if DEBUG
            GlobalLog.SetThreadSource(ThreadKinds.Finalization); 
           // using (GlobalLog.SetThreadKind(ThreadKinds.System | ThreadKinds.Async)) { 
#endif
            Dispose(false); 
#if DEBUG
           // }
#endif
        } 

        ///  
        ///     
        ///       Indicates whether the stream is still connected
        ///     
        /// 
        internal bool Connected {
            get {
                Socket socket = m_StreamSocket; 
                if (!m_CleanedUp && socket !=null && socket.Connected) {
                    return true; 
                } else { 
                    return false;
                } 
            }
        }

 
        /*++
            BeginRead - provide async read functionality. 
 
            This method provides async read functionality. All we do is
            call through to the underlying socket async read. 

            Input:

                buffer  - Buffer to read into. 
                offset  - Offset into the buffer where we're to read.
                size   - Number of bytes to read. 
 
            Returns:
 
                An IASyncResult, representing the read.

        --*/
 
        /// 
        ///     
        ///       Begins an asychronous read from a stream. 
        ///    
        ///  
        [HostProtection(ExternalThreading=true)]
        public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback callback, Object state) {
#if DEBUG
            using (GlobalLog.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) { 
#endif
            if (m_CleanedUp){ 
                throw new ObjectDisposedException(this.GetType().FullName); 
            }
            // 
            // parameter validation
            //
            if (buffer==null) {
                throw new ArgumentNullException("buffer"); 
            }
            if (offset<0 || offset>buffer.Length) { 
                throw new ArgumentOutOfRangeException("offset"); 
            }
            if (size<0 || size>buffer.Length-offset) { 
                throw new ArgumentOutOfRangeException("size");
            }
            if (!CanRead) {
                throw new InvalidOperationException(SR.GetString(SR.net_writeonlystream)); 
            }
 
            Socket chkStreamSocket = m_StreamSocket; 
            if(chkStreamSocket == null) {
                throw new IOException(SR.GetString(SR.net_io_readfailure, SR.GetString(SR.net_io_connectionclosed))); 
            }

            try {
                IAsyncResult asyncResult = 
                    chkStreamSocket.BeginReceive(
                        buffer, 
                        offset, 
                        size,
                        SocketFlags.None, 
                        callback,
                        state);

                return asyncResult; 
            }
            catch (Exception exception) { 
                if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) { 
                    throw;
	            } 

                //
                // some sort of error occured on the socket call,
                // set the SocketException as InnerException and throw 
                //
                throw new IOException(SR.GetString(SR.net_io_readfailure, exception.Message), exception); 
            } 
            catch {
                // 
                // some sort of error occured on the socket call,
                // set the SocketException as InnerException and throw
                //
                throw new IOException(SR.GetString(SR.net_io_readfailure, string.Empty), new Exception(SR.GetString(SR.net_nonClsCompliantException))); 
            }
#if DEBUG 
            } 
#endif
        } 

        internal virtual IAsyncResult UnsafeBeginRead(byte[] buffer, int offset, int size, AsyncCallback callback, Object state)
        {
            if (m_CleanedUp) 
            {
                throw new ObjectDisposedException(GetType().FullName); 
            } 
            if (!CanRead)
            { 
                throw new InvalidOperationException(SR.GetString(SR.net_writeonlystream));
            }

            Socket chkStreamSocket = m_StreamSocket; 
            if (chkStreamSocket == null)
            { 
                throw new IOException(SR.GetString(SR.net_io_readfailure, SR.GetString(SR.net_io_connectionclosed))); 
            }
 
            try
            {
                IAsyncResult asyncResult = chkStreamSocket.UnsafeBeginReceive(
                    buffer, 
                    offset,
                    size, 
                    SocketFlags.None, 
                    callback,
                    state); 

                return asyncResult;
            }
            catch (Exception exception) 
            {
                if (NclUtilities.IsFatal(exception)) throw; 
 
                //
                // some sort of error occured on the socket call, 
                // set the SocketException as InnerException and throw
                //
                throw new IOException(SR.GetString(SR.net_io_readfailure, exception.Message), exception);
            } 
            catch {
                // 
                // some sort of error occured on the socket call, 
                // set the SocketException as InnerException and throw
                // 
                throw new IOException(SR.GetString(SR.net_io_readfailure, string.Empty), new Exception(SR.GetString(SR.net_nonClsCompliantException)));
            }
        }
 
        /*++
            EndRead - handle the end of an async read. 
 
            This method is called when an async read is completed. All we
            do is call through to the core socket EndReceive functionality. 
            Input:

                buffer  - Buffer to read into.
                offset  - Offset into the buffer where we're to read. 
                size   - Number of bytes to read.
 
            Returns: 

                The number of bytes read. May throw an exception. 

        --*/

        ///  
        ///    
        ///       Handle the end of an asynchronous read. 
        ///     
        /// 
        public override int EndRead(IAsyncResult asyncResult) { 
#if DEBUG
            using (GlobalLog.SetThreadKind(ThreadKinds.User)) {
#endif
            if (m_CleanedUp){ 
                throw new ObjectDisposedException(this.GetType().FullName);
            } 
 
            //
            // parameter validation 
            //
            if (asyncResult==null) {
                throw new ArgumentNullException("asyncResult");
            } 

            Socket chkStreamSocket = m_StreamSocket; 
            if(chkStreamSocket == null) { 
                throw new IOException(SR.GetString(SR.net_io_readfailure, SR.GetString(SR.net_io_connectionclosed)));
            } 

            try {
                int bytesTransferred = chkStreamSocket.EndReceive(asyncResult);
                return bytesTransferred; 
            }
            catch (Exception exception) { 
                if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) { 
                    throw;
 	            } 

                //
                // some sort of error occured on the socket call,
                // set the SocketException as InnerException and throw 
                //
                throw new IOException(SR.GetString(SR.net_io_readfailure, exception.Message), exception); 
            } 
            catch {
                // 
                // some sort of error occured on the socket call,
                // set the SocketException as InnerException and throw
                //
                throw new IOException(SR.GetString(SR.net_io_readfailure, string.Empty), new Exception(SR.GetString(SR.net_nonClsCompliantException))); 
            }
#if DEBUG 
            } 
#endif
        } 

        /*++
            BeginWrite - provide async write functionality.
 
            This method provides async write functionality. All we do is
            call through to the underlying socket async send. 
 
            Input:
 
                buffer  - Buffer to write into.
                offset  - Offset into the buffer where we're to write.
                size   - Number of bytes to written.
 
            Returns:
 
                An IASyncResult, representing the write. 

        --*/ 

        /// 
        ///    
        ///       Begins an asynchronous write to a stream. 
        ///    
        ///  
        [HostProtection(ExternalThreading=true)] 
        public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, Object state) {
#if DEBUG 
            using (GlobalLog.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) {
#endif
            if (m_CleanedUp){
                throw new ObjectDisposedException(this.GetType().FullName); 
            }
            // 
            // parameter validation 
            //
            if (buffer==null) { 
                throw new ArgumentNullException("buffer");
            }
            if (offset<0 || offset>buffer.Length) {
                throw new ArgumentOutOfRangeException("offset"); 
            }
            if (size<0 || size>buffer.Length-offset) { 
                throw new ArgumentOutOfRangeException("size"); 
            }
            if (!CanWrite) { 
                throw new InvalidOperationException(SR.GetString(SR.net_readonlystream));
            }

            Socket chkStreamSocket = m_StreamSocket; 
            if(chkStreamSocket == null) {
                throw new IOException(SR.GetString(SR.net_io_writefailure, SR.GetString(SR.net_io_connectionclosed))); 
            } 

            try { 
                //
                // call BeginSend on the Socket.
                //
                IAsyncResult asyncResult = 
                    chkStreamSocket.BeginSend(
                        buffer, 
                        offset, 
                        size,
                        SocketFlags.None, 
                        callback,
                        state);

                return asyncResult; 
            }
            catch (Exception exception) { 
                if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) { 
                    throw;
	            } 

                //
                // some sort of error occured on the socket call,
                // set the SocketException as InnerException and throw 
                //
                throw new IOException(SR.GetString(SR.net_io_writefailure, exception.Message), exception); 
            } 
            catch {
                // 
                // some sort of error occured on the socket call,
                // set the SocketException as InnerException and throw
                //
                throw new IOException(SR.GetString(SR.net_io_writefailure, string.Empty), new Exception(SR.GetString(SR.net_nonClsCompliantException))); 
            }
#if DEBUG 
            } 
#endif
        } 



        internal virtual IAsyncResult UnsafeBeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, Object state) { 
#if DEBUG
            using (GlobalLog.SetThreadKind(ThreadKinds.User | ThreadKinds.Async)) { 
#endif 
                if (m_CleanedUp){
                    throw new ObjectDisposedException(this.GetType().FullName); 
                }

                if (!CanWrite) {
                    throw new InvalidOperationException(SR.GetString(SR.net_readonlystream)); 
                }
 
                Socket chkStreamSocket = m_StreamSocket; 
                if(chkStreamSocket == null) {
                    throw new IOException(SR.GetString(SR.net_io_writefailure, SR.GetString(SR.net_io_connectionclosed))); 
                }

                try {
                    // 
                    // call BeginSend on the Socket.
                    // 
                    IAsyncResult asyncResult = 
                        chkStreamSocket.UnsafeBeginSend(
                            buffer, 
                            offset,
                            size,
                            SocketFlags.None,
                            callback, 
                            state);
 
                    return asyncResult; 
                }
                catch (Exception exception) { 
                    if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) {
                        throw;
    	            }
 
                    //
                    // some sort of error occured on the socket call, 
                    // set the SocketException as InnerException and throw 
                    //
                    throw new IOException(SR.GetString(SR.net_io_writefailure, exception.Message), exception); 
                }
                catch {
                    //
                    // some sort of error occured on the socket call, 
                    // set the SocketException as InnerException and throw
                    // 
                    throw new IOException(SR.GetString(SR.net_io_writefailure, string.Empty), new Exception(SR.GetString(SR.net_nonClsCompliantException))); 
                }
#if DEBUG 
            }
#endif
        }
 

 
        ///  
        ///    
        ///       Handle the end of an asynchronous write. 
        ///       This method is called when an async write is completed. All we
        ///       do is call through to the core socket EndSend functionality.
        ///       Returns:  The number of bytes read. May throw an exception.
        ///     
        /// 
        public override void EndWrite(IAsyncResult asyncResult) { 
#if DEBUG 
            using (GlobalLog.SetThreadKind(ThreadKinds.User)) {
#endif 
            if (m_CleanedUp){
                throw new ObjectDisposedException(this.GetType().FullName);
            }
 
            //
            // parameter validation 
            // 
            if (asyncResult==null) {
                throw new ArgumentNullException("asyncResult"); 
            }

            Socket chkStreamSocket = m_StreamSocket;
            if(chkStreamSocket == null) { 
                throw new IOException(SR.GetString(SR.net_io_writefailure, SR.GetString(SR.net_io_connectionclosed)));
            } 
 
            try {
                chkStreamSocket.EndSend(asyncResult); 
            }
            catch (Exception exception) {
                if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) {
                    throw; 
 	            }
 
                // 
                // some sort of error occured on the socket call,
                // set the SocketException as InnerException and throw 
                //
                throw new IOException(SR.GetString(SR.net_io_writefailure, exception.Message), exception);
            }
            catch { 
                //
                // some sort of error occured on the socket call, 
                // set the SocketException as InnerException and throw 
                //
                throw new IOException(SR.GetString(SR.net_io_writefailure, string.Empty), new Exception(SR.GetString(SR.net_nonClsCompliantException))); 
            }
#if DEBUG
            }
#endif 
        }
 
 
        /// 
        ///     
        ///       Performs a sync Write of an array of buffers.
        ///    
        /// 
        internal virtual void MultipleWrite(BufferOffsetSize[] buffers) 
        {
            GlobalLog.ThreadContract(ThreadKinds.Sync, "NetworkStream#" + ValidationHelper.HashString(this) + "::MultipleWrite"); 
 
            //
            // parameter validation 
            //
            if (buffers == null) {
                throw new ArgumentNullException("buffers");
            } 

            Socket chkStreamSocket = m_StreamSocket; 
            if(chkStreamSocket == null) { 
                throw new IOException(SR.GetString(SR.net_io_writefailure, SR.GetString(SR.net_io_connectionclosed)));
            } 

            try {
                buffers = ConcatenateBuffersOnWin9x(buffers);
 
                chkStreamSocket.MultipleSend(
                    buffers, 
                    SocketFlags.None); 

            } 
            catch (Exception exception) {
                if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) {
                    throw;
 	            } 

                // 
                // some sort of error occured on the socket call, 
                // set the SocketException as InnerException and throw
                // 
                throw new IOException(SR.GetString(SR.net_io_writefailure, exception.Message), exception);
            }
            catch {
                // 
                // some sort of error occured on the socket call,
                // set the SocketException as InnerException and throw 
                // 
                throw new IOException(SR.GetString(SR.net_io_writefailure, string.Empty), new Exception(SR.GetString(SR.net_nonClsCompliantException)));
            } 
        }


        ///  
        ///    
        ///       Starts off an async Write of an array of buffers. 
        ///     
        /// 
        internal virtual IAsyncResult BeginMultipleWrite( 
            BufferOffsetSize[] buffers,
            AsyncCallback callback,
            Object state)
        { 
#if DEBUG
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "NetworkStream#" + ValidationHelper.HashString(this) + "::BeginMultipleWrite"); 
            using (GlobalLog.SetThreadKind(ThreadKinds.Async)) { 
#endif
 
            //
            // parameter validation
            //
            if (buffers == null) { 
                throw new ArgumentNullException("buffers");
            } 
 
            Socket chkStreamSocket = m_StreamSocket;
            if(chkStreamSocket == null) { 
                throw new IOException(SR.GetString(SR.net_io_writefailure, SR.GetString(SR.net_io_connectionclosed)));
            }

            try { 
                buffers = ConcatenateBuffersOnWin9x(buffers);
 
                // 
                // call BeginMultipleSend on the Socket.
                // 
                IAsyncResult asyncResult =
                    chkStreamSocket.BeginMultipleSend(
                        buffers,
                        SocketFlags.None, 
                        callback,
                        state); 
 
                return asyncResult;
            } 
            catch (Exception exception) {

                if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) {
                    throw; 
	            }
 
                // 
                // some sort of error occured on the socket call,
                // set the SocketException as InnerException and throw 
                //
                throw new IOException(SR.GetString(SR.net_io_writefailure, exception.Message), exception);
            }
            catch { 

                // 
                // some sort of error occured on the socket call, 
                // set the SocketException as InnerException and throw
                // 
                throw new IOException(SR.GetString(SR.net_io_writefailure, string.Empty), new Exception(SR.GetString(SR.net_nonClsCompliantException)));
            }
#if DEBUG
            } 
#endif
        } 
 

        internal virtual IAsyncResult UnsafeBeginMultipleWrite( 
            BufferOffsetSize[] buffers,
            AsyncCallback callback,
            Object state)
        { 
#if DEBUG
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "NetworkStream#" + ValidationHelper.HashString(this) + "::BeginMultipleWrite"); 
            using (GlobalLog.SetThreadKind(ThreadKinds.Async)) { 
#endif
 
            //
            // parameter validation
            //
            if (buffers == null) { 
                throw new ArgumentNullException("buffers");
            } 
 
            Socket chkStreamSocket = m_StreamSocket;
            if(chkStreamSocket == null) { 
                throw new IOException(SR.GetString(SR.net_io_writefailure, SR.GetString(SR.net_io_connectionclosed)));
            }

            try { 
                buffers = ConcatenateBuffersOnWin9x(buffers);
 
                // 
                // call BeginMultipleSend on the Socket.
                // 
                IAsyncResult asyncResult =
                    chkStreamSocket.UnsafeBeginMultipleSend(
                        buffers,
                        SocketFlags.None, 
                        callback,
                        state); 
 
                return asyncResult;
            } 
            catch (Exception exception) {

                if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) {
                    throw; 
 	            }
 
                // 
                // some sort of error occured on the socket call,
                // set the SocketException as InnerException and throw 
                //
                throw new IOException(SR.GetString(SR.net_io_writefailure, exception.Message), exception);
            }
            catch { 

                // 
                // some sort of error occured on the socket call, 
                // set the SocketException as InnerException and throw
                // 
                throw new IOException(SR.GetString(SR.net_io_writefailure, string.Empty), new Exception(SR.GetString(SR.net_nonClsCompliantException)));
            }
#if DEBUG
            } 
#endif
        } 
 

        internal virtual void EndMultipleWrite(IAsyncResult asyncResult) { 
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "NetworkStream#" + ValidationHelper.HashString(this) + "::EndMultipleWrite");

            //
            // parameter validation 
            //
            if (asyncResult == null) { 
                throw new ArgumentNullException("asyncResult"); 
            }
 
            Socket chkStreamSocket = m_StreamSocket;
            if(chkStreamSocket == null) {
                throw new IOException(SR.GetString(SR.net_io_writefailure, SR.GetString(SR.net_io_connectionclosed)));
            } 

            try { 
                chkStreamSocket.EndMultipleSend(asyncResult); 
            }
            catch (Exception exception) { 
                if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) {
                    throw;
	            }
 
                //
                // some sort of error occured on the socket call, 
                // set the SocketException as InnerException and throw 
                //
                throw new IOException(SR.GetString(SR.net_io_writefailure, exception.Message), exception); 
            }
            catch {
                //
                // some sort of error occured on the socket call, 
                // set the SocketException as InnerException and throw
                // 
                throw new IOException(SR.GetString(SR.net_io_writefailure, string.Empty), new Exception(SR.GetString(SR.net_nonClsCompliantException))); 
            }
        } 

        /// 
        ///    
        ///       Due to Winsock restrictions 
        ///       If on Win9x platforms and the number of buffers are more than 16, performs
        ///         concatenation of the buffers, so that we have 16 buffers. 
        ///     
        /// 
        private BufferOffsetSize[] ConcatenateBuffersOnWin9x(BufferOffsetSize[] buffers) { 
#if !FEATURE_PAL
            if (ComNetOS.IsWin9x && buffers.Length > 16) {
                // We met the limitation of winsock on Win9x
                // Combine buffers after the 15th into one so overall number does not exceed 16 
                BufferOffsetSize[] newBuffers = new BufferOffsetSize[16];
                int i; 
                for (i = 0; i < 16; ++i) { 
                    newBuffers[i] = buffers[i];
                } 
                int size = 0;
                for (i = 15; i < buffers.Length; ++i) {
                    size += buffers[i].Size;
                } 
                if (size > 0) {
                    newBuffers[15] = new BufferOffsetSize(new byte[size], 0, size, false); 
                    for (size = 0, i = 15; i < buffers.Length; size+=buffers[i].Size, ++i) { 
                        System.Buffer.BlockCopy(buffers[i].Buffer, buffers[i].Offset, newBuffers[15].Buffer, size, buffers[i].Size);
                    } 
                }
                buffers = newBuffers;
            }
#endif // !FEATURE_PAL 
            return buffers;
        } 
 
        /// 
        ///     
        ///       Flushes data from the stream.  This is meaningless for us, so it does nothing.
        ///    
        /// 
        public override void Flush() { 
        }
 
        ///  
        ///    
        ///       Sets the length of the stream. Always throws  
        ///    
        /// 
        public override void SetLength(long value) {
            throw new NotSupportedException(SR.GetString(SR.net_noseek)); 
        }
 
        int m_CurrentReadTimeout = -1; 
        int m_CurrentWriteTimeout = -1;
        internal void SetSocketTimeoutOption(SocketShutdown mode, int timeout, bool silent) { 
            GlobalLog.Print("NetworkStream#" + ValidationHelper.HashString(this) + "::SetSocketTimeoutOption() mode:" + mode + " silent:" + silent + " timeout:" + timeout + " m_CurrentReadTimeout:" + m_CurrentReadTimeout + " m_CurrentWriteTimeout:" + m_CurrentWriteTimeout);
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "NetworkStream#" + ValidationHelper.HashString(this) + "::SetSocketTimeoutOption");

            if (timeout < 0) { 
                timeout = 0; // -1 becomes 0 for the winsock stack
            } 
 
            Socket chkStreamSocket = m_StreamSocket;
            if (chkStreamSocket==null) { 
                return;
            }
            if (mode==SocketShutdown.Send || mode==SocketShutdown.Both) {
                if (timeout!=m_CurrentWriteTimeout) { 
                    chkStreamSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, timeout, silent);
                    m_CurrentWriteTimeout = timeout; 
                } 
            }
            if (mode==SocketShutdown.Receive || mode==SocketShutdown.Both) { 
                if (timeout!=m_CurrentReadTimeout) {
                    chkStreamSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, timeout, silent);
                    m_CurrentReadTimeout = timeout;
                } 
            }
        } 
 
#if TRAVE
        [System.Diagnostics.Conditional("TRAVE")] 
        internal void Debug() {
            if (m_StreamSocket != null) {
                GlobalLog.Print("m_StreamSocket:");
                m_StreamSocket.Debug(); 
            }
        } 
#endif 
    }
}
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK