zoukankan      html  css  js  c++  java
  • C# Socket IPackets

    using System;
    using System.Collections.Generic;
    using System.Diagnostics.Contracts;
    using System.Linq;
    using System.Text;
    using System.IO;
    
    namespace Rocky.Net
    {
        [ContractClass(typeof(IPacketsContract))]
        public interface IPackets
        {
            long ContentLength { get; }
            int? BufferSize { get; set; }
            bool Buffer { get; set; }
            Stream InputStream { get; }
        }
        [ContractClassFor(typeof(IPackets))]
        internal abstract class IPacketsContract : IPackets
        {
            long IPackets.ContentLength
            {
                get
                {
                    Contract.Ensures(Contract.Result<long>() >= SocketHelper.Special);
                    return default(long);
                }
            }
    
            int? IPackets.BufferSize
            {
                get
                {
                    return default(int?);
                }
                set
                {
    
                }
            }
    
            bool IPackets.Buffer
            {
                get
                {
                    return default(bool);
                }
                set
                {
    
                }
            }
    
            Stream IPackets.InputStream
            {
                get
                {
                    Contract.Ensures(Contract.Result<Stream>() != null);
                    return default(Stream);
                }
            }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    
    namespace Rocky.Net
    {
        public interface IPacketsFactory
        {
            IPackets Create(object graph);
            IPackets Create(Stream inputStream, long contentLength);
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Diagnostics.Contracts;
    using System.IO;
    
    namespace Rocky.Net
    {
        internal class Packets : IPackets
        {
            #region Fields
            private Stream _stream;
            #endregion
    
            #region Properties
            public long ContentLength { get; private set; }
            public int? BufferSize { get; set; }
            public bool Buffer { get; set; }
            public Stream InputStream
            {
                get { return _stream; }
            }
            #endregion
    
            #region Constructors
            public Packets(byte[] binary)
                : this(new MemoryStream(binary, 0, binary.Length, true, false), binary.Length)
            {
    
            }
            public Packets(Stream inputStream, long contentLength)
            {
                Contract.Requires(inputStream != null);
    
                _stream = inputStream;
                this.ContentLength = contentLength;
            }
            #endregion
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    
    namespace Rocky.Net
    {
        internal sealed class PacketsFactory : IPacketsFactory
        {
            public IPackets Create(object graph)
            {
                byte[] binary = Serializer.Serialize(graph);
                return new Packets(binary);
            }
    
            public IPackets Create(Stream inputStream, long contentLength)
            {
                return new Packets(inputStream, contentLength);
            }
        }
    }
    #region Packets
            /// <summary>
            /// 同步发送数据包
            /// </summary>
            /// <param name="instance"></param>
            /// <param name="pack">数据包</param>
            /// <param name="progress">进度器</param>
            /// <returns>
            /// -1  远程连接关闭
            /// >=0 已发送的字节数
            /// </returns>
            public static long SendPackets(this Socket instance, IPackets pack, bool acceptLength = true, TransferProgress progress = null)
            {
                Contract.Requires(instance != null);
                Contract.Requires(pack != null);
    
                var netStream = new NetworkStream(instance, FileAccess.Write, false);
                Stream src = netStream, dest = pack.InputStream;
                if (pack.Buffer)
                {
                    src = new BufferedStream(netStream, pack.BufferSize.GetValueOrDefault(4096));
                }
                long totalTransferred = 0L, contentLength = pack.ContentLength;
                if (contentLength == SocketHelper.Special)
                {
                    try
                    {
                        contentLength = pack.InputStream.Length;
                    }
                    catch (NotSupportedException)
                    {
    
                    }
                }
                ArraySegment<byte> seg;
                BufferSegment.MemoryBuffer.Take(out seg);
                bool doProg = false,
                    unknownLength = contentLength == SocketHelper.Special;
                try
                {
                    if (acceptLength)
                    {
                        instance.Send(BitConverter.GetBytes(contentLength));
                    }
                    if (progress != null)
                    {
                        doProg = true;
                        progress.Start(contentLength);
                    }
    
                    int read;
                    while ((unknownLength || totalTransferred < contentLength) && (read = dest.Read(seg)) != 0)
                    {
                        src.Write(seg, read);
                        src.Flush();
                        totalTransferred += read;
                        if (doProg)
                        {
                            progress.OnProgressChanged(read, totalTransferred);
                        }
    #if Sleep
                        Thread.Sleep(10);
    #endif
                    }
                    if (!unknownLength && totalTransferred != contentLength)
                    {
                        throw new InvalidOperationException("输入流长度和数据包长度必须相同");
                    }
                }
                catch (IOException ex)
                {
                    var sockEx = ex.InnerException as SocketException;
                    if (sockEx != null && sockEx.ErrorCode == 10054)
                    {
                        return SocketHelper.Special;
                    }
                    throw;
                }
                finally
                {
                    if (doProg)
                    {
                        progress.Stop();
                    }
                    BufferSegment.MemoryBuffer.Return(ref seg);
                    src.Dispose();
                }
                return totalTransferred;
            }
    
            /// <summary>
            /// 同步接收数据包
            /// </summary>
            /// <param name="instance"></param>
            /// <param name="pack">数据包</param>
            /// <param name="progress">进度器</param>
            /// <returns>
            /// -1  远程连接关闭
            /// >=0 已接受的字节数
            /// </returns>
            public static long ReceivePackets(this Socket instance, IPackets pack, bool acceptLength = true, TransferProgress progress = null)
            {
                Contract.Requires(instance != null);
                Contract.Requires(pack != null);
    
                var netStream = new NetworkStream(instance, FileAccess.Read, false);
                Stream src = netStream, dest = pack.InputStream;
                if (pack.Buffer)
                {
                    src = new BufferedStream(netStream, pack.BufferSize.GetValueOrDefault(4096));
                }
                long totalTransferred = 0L, contentLength = pack.ContentLength;
                ArraySegment<byte> seg;
                BufferSegment.MemoryBuffer.Take(out seg);
                bool doProg = false,
                    unknownLength = contentLength == SocketHelper.Special;
                try
                {
                    if (acceptLength)
                    {
                        byte[] buffer = new byte[SocketHelper.PerLongSize];
                        instance.Receive(buffer);
                        contentLength = buffer.ToInt64(0);
                    }
                    if (progress != null)
                    {
                        doProg = true;
                        progress.Start(contentLength);
                    }
    
                    int read;
                    while ((unknownLength || totalTransferred < contentLength) && (read = src.Read(seg)) != 0)
                    {
                        dest.Write(seg, read);
                        dest.Flush();
                        totalTransferred += read;
                        if (doProg)
                        {
                            progress.OnProgressChanged(read, totalTransferred);
                        }
    #if Sleep
                        Thread.Sleep(10);
    #endif
                    }
                    // recv == 0, 远程主动关闭连接
                    if (totalTransferred < contentLength)
                    {
                        return SocketHelper.Special;
                    }
                }
                catch (IOException ex)
                {
                    var sockEx = ex.InnerException as SocketException;
                    // 远程强制关闭连接
                    if (sockEx != null && sockEx.ErrorCode == 10054)
                    {
                        return SocketHelper.Special;
                    }
                    throw;
                }
                finally
                {
                    if (doProg)
                    {
                        progress.Stop();
                    }
                    BufferSegment.MemoryBuffer.Return(ref seg);
                    src.Dispose();
                }
                return totalTransferred;
            }
            #endregion
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Diagnostics;
    using System.Diagnostics.Contracts;
    using System.IO;
    
    namespace Rocky.Net
    {
        public class SocketSyncArgs : EventArgs
        {
            #region Fields
            private IPacketsFactory _packFac;
            private IPackets _header, _content;
            #endregion
    
            #region Properties
            public bool Buffer { get; set; }
            public bool TransferHeader { get; set; }
            public object HeaderEntity { get; set; }
            public TransferProgress Progress { get; set; }
            public bool IsShutdown { get; internal set; }
            #endregion
    
            #region Constructors
            public SocketSyncArgs()
            {
                _packFac = SocketHelper.CreatePacketsFactory();
            }
            #endregion
    
            #region Methods
            [DebuggerStepThrough]
            internal IPackets[] GetPackets()
            {
                if (_content == null)
                {
                    throw new InvalidOperationException("未设置内容包");
                }
                if (this.HeaderEntity != null)
                {
                    _header = _packFac.Create(this.HeaderEntity);
                }
                return new IPackets[] { _header, _content };
            }
    
            public void SetPackets(Stream inputStream, long contentLength)
            {
                Contract.Requires(inputStream != null);
    
                _content = _packFac.Create(inputStream, contentLength);
                this.IsShutdown = false;
            }
            #endregion
        }
    }
    /// <summary>
            /// 同步发送SocketSyncArgs
            /// </summary>
            /// <param name="sock"></param>
            /// <param name="e"></param>
            /// <returns>已发送字节数(不包含HeaderPackets)</returns>
            public static long SendSync(this Socket sock, SocketSyncArgs e, bool acceptLength = true)
            {
                var packs = e.GetPackets();
                long sent;
                if (e.TransferHeader)
                {
                    if (packs[0] == null)
                    {
                        throw new InvalidOperationException("头对象为空");
                    }
                    sent = sock.SendPackets(packs[0]);
                    if (sent == SocketHelper.Special)
                    {
                        e.IsShutdown = true;
                        goto done;
                    }
                }
                packs[1].Buffer = e.Buffer;
                sent = sock.SendPackets(packs[1], acceptLength, e.Progress);
                if (sent == SocketHelper.Special)
                {
                    e.IsShutdown = true;
                }
            done:
                return sent;
            }
    
            /// <summary>
            /// 同步接收SocketSyncArgs
            /// </summary>
            /// <param name="sock"></param>
            /// <param name="e"></param>
            /// <param name="transferLength"></param>
            /// <returns>已接收字节数(不包含HeaderPackets)</returns>
            public static long ReceiveSync(this Socket sock, SocketSyncArgs e, bool acceptLength = true)
            {
                var packs = e.GetPackets();
                long recv;
                if (e.TransferHeader)
                {
                    if (packs[0] == null)
                    {
                        throw new InvalidOperationException("头对象为空");
                    }
                    recv = sock.ReceivePackets(packs[0]);
                    if (recv == SocketHelper.Special)
                    {
                        e.IsShutdown = true;
                        goto done;
                    }
                }
                packs[1].Buffer = e.Buffer;
                recv = sock.ReceivePackets(packs[1], acceptLength, e.Progress);
                if (recv == SocketHelper.Special)
                {
                    e.IsShutdown = true;
                }
            done:
                return recv;
            }
  • 相关阅读:
    MFC列表控件更改一行的字体颜色
    MFC之sqlite
    MFC笔记10
    MFC---关于string.h相关函数
    MFC笔记8
    MFC笔记7
    MFC笔记6
    MFC笔记5
    MFC笔记4
    MFC笔记3
  • 原文地址:https://www.cnblogs.com/Googler/p/3055300.html
Copyright © 2011-2022 走看看