Socket通讯工具类【SocketTools】(20140402修订版)

 

 

 

    /// <summary>
    /// Socket通讯工具类
    /// 约定:
    /// 一个数据包前8个字节为数据长度【长度不包括数据包前面的12个字节】,[支持4G大文件]
    /// 中间的4个字节为数据类别: 1为Json,2为文件
    /// 后面的均为 “数据”
    /// </summary>
    public class SocketTools
    {
        private static int JSON_TYPE = 1;
        private static int FILE_TYPE = 2;

        private readonly string mIp;
        private readonly int mPort;

        private Socket mClient;
        private bool mDeviceConnected;


        /// <summary>
        /// 当前连接状态:是否已经连接
        /// </summary>
        public bool Connected
        {
            get
            {
                try
                {
                    if (this.mClient != null
                        && this.mClient.Connected
                        && this.mClient.Poll(100, SelectMode.SelectWrite))
                    {
                        return true;
                    }
                }
                catch (Exception)
                { }
                return false;
            }
        }


        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="ip">ip地址</param>
        /// <param name="port">端口号</param>
        public SocketTools(string ip, int port)
        {
            this.mIp = ip;
            this.mPort = port;
            this.mDeviceConnected = true;
        }


        /// <summary>
        /// 连接服务器
        /// </summary>
        /// <returns></returns>
        public SocketResult ConnectServer()
        {
            if (!this.mDeviceConnected)
                return SocketResult.Error("设备已断开连接");

            this.DisConnect();
            try
            {
                //1.创建发送者
                this.mClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                //2.连接给谁发送     
                this.mClient.Connect(IPAddress.Parse(this.mIp), this.mPort);

                this.mClient.SendBufferSize = 102400;
                this.mClient.ReceiveBufferSize = 102400;
            }
            catch (Exception e)
            {
                return SocketResult.Error(e.Message);
            }

            return SocketResult.Success();
        }

        /// <summary>
        /// 断开Socket连接
        /// </summary>
        /// <returns></returns>
        public SocketResult DisConnect()
        {
            try
            {
                if (this.mClient != null && this.mClient.Connected)
                    this.mClient.Close();
            }
            catch (Exception e)
            {
                return SocketResult.Error(e.Message);
            }

            this.mClient = null;
            return SocketResult.Success();
        }


        public void DeviceDisConnect()
        {
            mDeviceConnected = false;
            this.DisConnect();
        }

        /// <summary>
        /// 向服务端发送Json格式数据,返回Json格式数据
        /// </summary>
        /// <param name="json"></param>
        /// <returns></returns>
        public SocketResult SendJsonReceiveJson(SocketModel json)
        {
            SocketResult tmp = Connect();
            if (!tmp.Result)
                return tmp;

            try
            {
                SendJson(json);

                return CheckReceiveJson(json);
            }
            catch (Exception e)
            {
                return SocketResult.Error(e.Message);
            }
        }

        /// <summary>
        /// 向服务端发送Json格式数据,返回文件
        /// 用于下载手机端的文件
        /// </summary>
        /// <param name="json"></param>
        /// <returns></returns>
        public SocketResult SendJsonReceiveFile(SocketModel json)
        {
            SocketResult tmp = Connect();
            if (!tmp.Result)
                return tmp;

            try
            {
                SendJson(json);

                return ReceiveFile();
            }
            catch (Exception e)
            {
                return SocketResult.Error(e.Message);
            }
        }

        /// <summary>
        /// 向服务端发送文件格式数据,返回Json
        /// 向手机端上传文件
        /// </summary>
        /// <param name="json"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public SocketResult SendFileReceiveModel(SocketModel json, string fileName)
        {
            SocketResult tmp = Connect();
            if (!tmp.Result)
                return tmp;

            // 先发送Json 后发送文件
            try
            {
                if (!File.Exists(fileName))
                {
                    return SocketResult.Error("文件不存在,无法发送文件");
                }

                SendJson(json);

                SendFile(fileName);

                return CheckReceiveJson(json);
            }
            catch (Exception e)
            {
                return SocketResult.Error(e.Message);
            }
        }


        private SocketResult Connect()
        {
            if (!this.Connected && this.ConnectServer().Result)
            {
                return SocketResult.Error("设备已断开连接");
            }
            return SocketResult.Success();
        }


        private void SendFile(string fileName)
        {
            using (FileStream fs = File.OpenRead(fileName))
            {
                if (fs.Length > int.MaxValue)
                {
                    fs.Close();
                    throw new Exception("文件过大,无法发送");
                }

                this.mClient.Send(BitConverter.GetBytes(fs.Length));
                this.mClient.Send(BitConverter.GetBytes(FILE_TYPE));

                while (fs.Position < fs.Length - 1)
                {
                    byte[] tempBuffer = new byte[102400];
                    int tempLen = fs.Read(tempBuffer, 0, tempBuffer.Length);
                    // 空文件 不必Send
                    if (tempLen > 0)
                        this.mClient.Send(tempBuffer, 0, tempLen, SocketFlags.None);
                }
                fs.Close();
            }
        }

        private SocketResult ReceiveFile()
        {
            string tempDownloadFile = Path.GetTempFileName();
            try
            {
                using (FileStream fsDownload = File.Create(tempDownloadFile))
                {
                    if (!this.Read(fsDownload, FILE_TYPE))
                    {
                        LogTools.Info("接收数据失败", "Receive File");
                        return SocketResult.Error("接收数据失败");
                    }

                    string tempFile = Path.GetTempFileName();

                    if (fsDownload.Length > 12)
                    {
                        fsDownload.Seek(12, SeekOrigin.Begin);
                        using (FileStream fs = File.Create(tempFile))
                        {
                            // 循环写入 每次100K
                            while (fsDownload.Position < fsDownload.Length - 1)
                            {
                                byte[] tempBuffer = new byte[102400];
                                int tempLen = fsDownload.Read(tempBuffer, 0, tempBuffer.Length);
                                fs.Write(tempBuffer, 0, tempLen);
                            }
                            fs.Flush();
                            fs.Close();
                        }
                    }

                    fsDownload.Close();

                    LogTools.Info("接收文件成功", "Receive File");

                    // 文件下载成功后 将临时文件 文件全路径返回
                    SocketResult result = SocketResult.Success();
                    result.Model = new SocketModel();
                    result.Model.AddData(SocketModel.PathKey, tempFile);
                    return result;
                }
            }
            catch (Exception ex)
            {
                LogTools.Execption(ex, "Receive File");
                throw ex;
            }
            finally
            {
                try
                {
                    File.Delete(tempDownloadFile);
                }
                catch { }
            }
        }

        private void SendJson(SocketModel json)
        {
            byte[] data = JsonTools.SerializeToBuffer(json);
            if (data == null || data.Length == 0)
                throw new ArgumentNullException(" data is empty ");

            string log = string.Format(" Cmd:[{0}] JSON:[{1}] ", json.Cmd.ToString().PadRight(10, ' '), JsonTools.SerializeToString(json));
            LogTools.Info(log, "Send JSON");

            this.mClient.Send(BitConverter.GetBytes((long)data.Length));
            this.mClient.Send(BitConverter.GetBytes(JSON_TYPE));
            this.mClient.Send(data);
        }

        private SocketResult ReceiveJson()
        {
            try
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    if (!this.Read(ms, JSON_TYPE) || ms.Length <= 12)
                    {
                        LogTools.Info("接收数据失败", "Receive JSON");
                        return SocketResult.Error("接收数据失败");
                    }

                    SocketResult socketResult = null;

                    byte[] buffer = new byte[ms.Length - 12];
                    ms.Seek(12, SeekOrigin.Begin);
                    ms.Read(buffer, 0, (int)ms.Length - 12);

                    SocketModel model = JsonTools.DeserializeToTFromBuffer<SocketModel>(buffer);

                    string log = string.Format(" JSON:[{0}] ", JsonTools.SerializeToString(model));
                    LogTools.Info(log, "Receive JSON");

                    if (model == null || model.Result == 0)
                    {
                        socketResult = SocketResult.Error(model == null ? "数据格式错误" : model.Msg);
                        socketResult.Model = model;
                        return socketResult;
                    }

                    socketResult = SocketResult.Success();
                    socketResult.Model = model;
                    return socketResult;
                }
            }
            catch (Exception ex)
            {
                LogTools.Execption(ex, "Receive JSON");
                throw ex;
            }
        }

        private SocketResult CheckReceiveJson(SocketModel json)
        {
            SocketResult result = ReceiveJson();

            if (result.Result && json.Cmd != result.Model.Cmd)
            {
                result.Result = false;
                result.Msg = "问答命令不一致";
                LogTools.Monitor(string.Format(" SendModel.Cmd:[{0}] ", json.Cmd), "问答命令不一致");
            }

            return result;
        }


        private bool Read(Stream stream, int type)
        {
            while (true)
            {
                long next = GetNextCount(stream);
                if (next < 0)
                {
                    this.DisConnect();
                    return false;
                }

                if (next == 0)
                {
                    stream.Seek(8, SeekOrigin.Begin);
                    byte[] typeBuffer = new byte[4];
                    stream.Read(typeBuffer, 0, 4);
                    if (type != BitConverter.ToInt32(typeBuffer, 0))
                    {
                        this.DisConnect();
                        return false;
                    }
                    break;
                }

                long len = stream.Length;
                ReadBuffer(stream, (int)next);

                // 判断本次读取是否成功
                if (stream.Length == len)
                {
                    this.DisConnect();
                    return false;
                }
            }
            return true;
        }

        private void ReadBuffer(Stream stream, int next)
        {
            try
            {
                byte[] buffer = new byte[next];

                int len = 0;

                if (this.mClient.Connected)
                    len = this.mClient.Receive(buffer, next, SocketFlags.None);

                if (len > 0)
                {
                    stream.Seek(0, SeekOrigin.End);
                    stream.Write(buffer, 0, len);
                    stream.Flush();
                }
            }
            catch (Exception)
            { }
        }

        private long GetNextCount(Stream stream)
        {
            // 确定nextCount
            long next = 0;
            if (stream.Length < 12)
            {
                next = 12;
            }
            else
            {
                stream.Seek(0, SeekOrigin.Begin);
                byte[] lenBuffer = new byte[8];
                stream.Read(lenBuffer, 0, 8);
                try
                {
                    long len = BitConverter.ToInt64(lenBuffer, 0);
                    if (len < 0)
                        return -1;
                    next = (len + 12 - stream.Length);
                }
                catch (Exception)
                {
                    return -1;
                }
            }

            // 每次最多读取100K
            if (next > 102400)
                next = 102400;

            return next;
        }

    }

    /// <summary>
    /// Socket命令类别
    /// </summary>
    public enum ESocketCmdType
    {
        /// <summary>
        /// 下载文件
        /// </summary>
        GetFile = 1,

        /// <summary>
        /// 获取手机端的照片列表
        /// </summary>
        GetPicList = 2,

        /// <summary>
        /// 获取手机端的音乐列表
        /// </summary>
        GetMusicList = 3,

        /// <summary>
        /// 获取通讯录列表
        /// </summary>
        GetAddressListList = 4,

        /// <summary>
        /// 获取短信列表
        /// </summary>
        GetSMSList = 5,



        /// <summary>
        /// 上传文件
        /// </summary>
        UploadFile = 999,
    }


    /// <summary>
    /// Socket通讯,Json实体类
    /// </summary>
    public class SocketModel
    {
        public static readonly string DefaultKey = "Default";
        public static readonly string ParamKey = "Param";
        public static readonly string PathKey = "Path";

        /// <summary>
        /// 命令
        /// </summary>
        [JsonProperty("Cmd")]
        public ESocketCmdType Cmd;

        /// <summary>
        /// 1:成功 0:失败
        /// </summary>
        [JsonProperty("Result")]
        public int Result;

        /// <summary>
        /// 提示信息
        /// </summary>
        [JsonProperty("Msg")]
        public string Msg;

        /// <summary>
        /// 命令附带参数
        /// </summary>
        [JsonProperty("Data")]
        public Dictionary<string, object> Data;


        public SocketModel()
        {
            this.Msg = string.Empty;
            this.Data = new Dictionary<string, object>();
        }


        public SocketModel AddData(string key, object value)
        {
            if (this.Data != null && !this.Data.ContainsKey(key))
                this.Data.Add(key, value);

            return this;
        }



        public string GetString(string key)
        {
            if (this.Data != null && this.Data.ContainsKey(key) && this.Data[key] != null)
                return this.Data[key].ToString().Trim();

            return string.Empty;
        }

        public int GetInt(string key)
        {
            int result = -1;
            if (!int.TryParse(GetString(key), out result))
                result = -1;
            return result;
        }

        public double GetDouble(string key)
        {
            double result = -1;
            if (!double.TryParse(GetString(key), out result))
                result = -1;
            return result;
        }

        public T GetObject<T>(string key) where T : class
        {
            if (this.Data != null && this.Data.ContainsKey(key))
                return this.Data[key] as T;

            return null;
        }

        public Dictionary<string, object> GetDictionary(string key)
        {
            if (this.Data != null && this.Data.ContainsKey(key))
                return JsonTools.Deserialize(this.Data[key]);

            return null;
        }

        public Dictionary<string, string> GetDictionaryString(string key)
        {
            if (this.Data != null && this.Data.ContainsKey(key))
                return JsonTools.DeserializeToTFromObject<Dictionary<string, string>>(this.Data[key]);

            return null;
        }

        public T GetObjectFromJson<T>(string key) where T : class
        {
            if (this.Data != null && this.Data.ContainsKey(key))
                return JsonTools.DeserializeToTFromObject<T>(this.Data[key]);

            return null;
        }

    }


    /// <summary>
    /// Socket通讯结果
    /// </summary>
    public class SocketResult
    {
        /// <summary>
        /// 操作是否成功
        /// </summary>
        public bool Result;

        /// <summary>
        /// 失败时的错误提示信息
        /// </summary>
        public string Msg;

        /// <summary>
        /// 服务端返回的数据
        /// </summary>
        public SocketModel Model;

        private SocketResult()
        { }

        public static SocketResult Success()
        {
            SocketResult result = new SocketResult();
            result.Result = true;
            result.Msg = "操作成功";
            return result;
        }

        public static SocketResult Error(string msg)
        {
            SocketResult result = new SocketResult();
            result.Result = false;
            result.Msg = msg;
            return result;
        }

    }


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 C# Socket 通讯类,可以用于客户端和服务器端的通讯: ```csharp using System; using System.Net; using System.Net.Sockets; using System.Text; public class SocketClient { private Socket clientSocket; public SocketClient() { clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); } public void Connect(string ip, int port) { clientSocket.Connect(new IPEndPoint(IPAddress.Parse(ip), port)); } public void Send(string message) { byte[] data = Encoding.UTF8.GetBytes(message); clientSocket.Send(data); } public string Receive() { byte[] data = new byte[1024]; int length = clientSocket.Receive(data); string message = Encoding.UTF8.GetString(data, 0, length); return message; } public void Close() { clientSocket.Close(); } } public class SocketServer { private Socket serverSocket; private Socket clientSocket; public SocketServer() { serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); } public void Bind(string ip, int port) { serverSocket.Bind(new IPEndPoint(IPAddress.Parse(ip), port)); } public void Listen(int backlog) { serverSocket.Listen(backlog); clientSocket = serverSocket.Accept(); } public string Receive() { byte[] data = new byte[1024]; int length = clientSocket.Receive(data); string message = Encoding.UTF8.GetString(data, 0, length); return message; } public void Send(string message) { byte[] data = Encoding.UTF8.GetBytes(message); clientSocket.Send(data); } public void Close() { clientSocket.Close(); serverSocket.Close(); } } ``` 使用示例: 客户端: ```csharp SocketClient client = new SocketClient(); client.Connect("127.0.0.1", 8888); client.Send("Hello, server!"); string message = client.Receive(); Console.WriteLine("Received message: " + message); client.Close(); ``` 服务器端: ```csharp SocketServer server = new SocketServer(); server.Bind("127.0.0.1", 8888); server.Listen(10); string message = server.Receive(); Console.WriteLine("Received message: " + message); server.Send("Hello, client!"); server.Close(); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值