• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

C#.NETSocket封装

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

    Socket封装,支持多客户端支持大文件传输支持多线程并发,对较大的Socket包进行分块传输

    封装所要达到的效果,是可以像下面这样使用Socket和服务端通信,调用服务端的方法,让你在使用Socket的时候,感觉不到Socket的存在,就像是调用本地方法一样,并且支持ref参数和out参数

DemoService demoService = new DemoService();
DemoService2 demoService2 = new DemoService2();
string result = demoService.Test("测试DemoService", 1);
demoService.Test2("测试DemoService", 1);
string result2 = demoService2.RunTest("测试DemoService2", 2);

一、数据结构:

CmdType:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DataStruct
{
    /// <summary>
    /// cmd类型
    /// </summary>
    public enum CmdType
    {
        /// <summary>
        /// 执行方法
        /// </summary>
        RunFunction = 1,
        /// <summary>
        /// 心跳
        /// </summary>
        Heartbeat = 2
    }
}
View Code

SocketData:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DataStruct
{
    /// <summary>
    /// Socket数据
    /// </summary>
    [Serializable]
    public class SocketData
    {
        /// <summary>
        /// 命令类型
        /// </summary>
        public CmdType cmdType { get; set; }
        /// <summary>
        /// 类名
        /// </summary>
        public string className { get; set; }
        /// <summary>
        /// 方法名
        /// </summary>
        public string functionName { get; set; }
        /// <summary>
        /// 方法参数
        /// </summary>
        public object[] funParam { get; set; }
    }
}
View Code

SocketResult:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DataStruct
{
    /// <summary>
    /// Socket返回
    /// </summary>
    [Serializable]
    public class SocketResult
    {
        /// <summary>
        /// 方法返回值
        /// </summary>
        public object returnValue { get; set; }
        /// <summary>
        /// 方法参数
        /// </summary>
        public object[] param { get; set; }
    }
}
View Code

FunctionUtil(根据SocketData执行服务端的方法):

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace DataStruct.Utils
{
    /// <summary>
    /// 执行方法
    /// </summary>
    public class FunctionUtil
    {
        /// <summary>
        /// 执行方法
        /// </summary>
        public static object RunFunction(string applicationPath, SocketData socketData)
        {
            Assembly assembly = Assembly.LoadFile(Path.Combine(applicationPath, "DataService.dll"));
            object classObj = assembly.CreateInstance("DataService." + socketData.className);
            Type type = classObj.GetType();
            MethodInfo methodInfo = type.GetMethod(socketData.functionName);
            ParameterInfo[] parameterInfoArr = methodInfo.GetParameters();
            object result = methodInfo.Invoke(classObj, socketData.funParam);
            SocketResult socketResult = new SocketResult();
            socketResult.returnValue = result;
            socketResult.param = new object[socketData.funParam.Length];
            object paramObj;
            for (int i = 0; i < parameterInfoArr.Length; i++)
            {
                paramObj = socketData.funParam[i];
                if (parameterInfoArr[i].ParameterType.IsByRef || parameterInfoArr[i].IsOut)
                {
                    socketResult.param[i] = paramObj;
                }
                else
                {
                    socketResult.param[i] = null;
                }
            }
            return socketResult;
        }
    }
}
View Code

二、Socket通信封装:

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using DataStruct.Utils;

namespace DataStruct
{
    /// <summary>
    /// Socket封装
    /// </summary>
    public static class SocketHelper
    {
        #region 变量
        private static object _lockSend = new object();
        private static Socket serverSocket;
        private static Socket clientSocket;
        private static List<Socket> clientList = new List<Socket>();
        private static System.Timers.Timer heartbeatTimer;
        #endregion

        #region 启动服务
        /// <summary>
        /// 启动服务
        /// </summary>
        public static void StartServer()
        {
            try
            {
                int port = Convert.ToInt32(ConfigurationManager.AppSettings["ServerPort"]);
                IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, port);
                serverSocket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                serverSocket.Bind(ipEndPoint);
                serverSocket.Listen(10);
                new Thread(new ThreadStart(delegate()
                {
                    while (true)
                    {
                        Socket m_Client;
                        try
                        {
                            m_Client = serverSocket.Accept();
                            m_Client.SendTimeout = 20000;
                            m_Client.ReceiveTimeout = 20000;
                            m_Client.SendBufferSize = 10240;
                            m_Client.ReceiveBufferSize = 10240;
                            clientList.Add(m_Client);
                            LogUtil.Log("监听到新的客户端,当前客户端数:" + clientList.Count);
                        }
                        catch { break; }

                        DateTime lastHeartbeat = DateTime.Now;
                        new Thread(new ThreadStart(delegate()
                        {
                            try
                            {
                                while (true)
                                {
                                    byte[] receiveByteArr = null;
                                    try
                                    {
                                        receiveByteArr = Receive(m_Client);
                                    }
                                    catch { break; }
                                    if (receiveByteArr != null)
                                    {
                                        SocketData data = (SocketData)SerializeUtil.Deserialize(receiveByteArr);
                                        if (data.cmdType != CmdType.Heartbeat)
                                        {
                                            object obj = null;
                                            try
                                            {
                                                obj = FunctionUtil.RunFunction(System.Windows.Forms.Application.StartupPath, data);
                                            }
                                            catch (Exception ex)
                                            {
                                                LogUtil.LogError("执行方法出错:" + ex.Message + "\r\n" + ex.StackTrace);
                                                Send(m_Client, SerializeUtil.Serialize("error:执行服务端方法出错"));
                                            }
                                            Send(m_Client, SerializeUtil.Serialize(obj));
                                            LogUtil.Log("接收客户端数据,并向客户端返回数据");
                                        }
                                        else
                                        {
                                            lastHeartbeat = DateTime.Now;
                                            LogUtil.Log("收到心跳包,客户端连接正常");
                                        }
                                    }
                                    else
                                    {
                                        clientList.Remove(m_Client);
                                        LogUtil.Log("客户端正常关闭,当前客户端数:" + clientList.Count);
                                        if (m_Client.Connected) m_Client.Disconnect(false);
                                        m_Client.Close();
                                        m_Client.Dispose();
                                        break;
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                LogUtil.LogError(ex.Message + "\r\n" + ex.StackTrace);
                                try
                                {
                                    Send(m_Client, SerializeUtil.Serialize("error:" + ex.Message));
                                }
                                catch { }
                            }
                        })).Start();

                        //检测客户端
                        new Thread(new ThreadStart(delegate()
                        {
                            try
                            {
                                while (true)
                                {
                                    DateTime now = DateTime.Now;
                                    if (now.Subtract(lastHeartbeat).TotalSeconds > 300)
                                    {
                                        clientList.Remove(m_Client);
                                        LogUtil.Log("客户端已失去连接,当前客户端数:" + clientList.Count);
                                        if (m_Client.Connected) m_Client.Disconnect(false);
                                        m_Client.Close();
                                        m_Client.Dispose();
                                        break;
                                    }
                                    Thread.Sleep(500);
                                }
                            }
                            catch (Exception ex)
                            {
                                LogUtil.LogError("检测客户端出错:" + ex.Message + "\r\n" + ex.StackTrace);
                            }
                        })).Start();
                    }
                })).Start();
                LogUtil.Log("服务已启动");
            }
            catch (Exception ex)
            {
                LogUtil.LogError("启动服务出错:" + ex.Message + "\r\n" + ex.StackTrace);
            }
        }
        #endregion

        #region 停止服务
        /// <summary>
        /// 停止服务
        /// </summary>
        public static void StopServer()
        {
            try
            {
                foreach (Socket socket in clientList)
                {
                    if (socket.Connected) socket.Disconnect(false);
                    socket.Close();
                    socket.Dispose();
                }
                clientList.Clear();
                if (serverSocket != null)
                {
                    if (serverSocket.Connected) serverSocket.Disconnect(false);
                    serverSocket.Close();
                    serverSocket.Dispose();
                }
                LogUtil.Log("服务已停止");
            }
            catch (Exception ex)
            {
                LogUtil.LogError("停止服务出错:" + ex.Message + "\r\n" + ex.StackTrace);
            }
        }
        #endregion

        #region 连接服务器
        /// <summary>
        /// 连接服务器
        /// </summary>
        public static void ConnectServer()
        {
            try
            {
                if (clientSocket == null || !clientSocket.Connected)
                {
                    if (clientSocket != null)
                    {
                        clientSocket.Close();
                        clientSocket.Dispose();
                    }
                    string ip = ConfigurationManager.AppSettings["ServerIP"];
                    int port = Convert.ToInt32(ConfigurationManager.AppSettings["ServerPort"]);
                    IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(ip), port);
                    clientSocket = new Socket(ipep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                    clientSocket.SendTimeout = 20000;
                    clientSocket.ReceiveTimeout = 20000;
                    clientSocket.SendBufferSize = 10240;
                    clientSocket.ReceiveBufferSize = 10240;
                    clientSocket.Connect(ipep);
                    LogUtil.Log("已连接服务器");
                }
            }
            catch (Exception ex)
            {
                LogUtil.LogError("连接服务器失败:" + ex.Message);
            }
        }
        #endregion

        #region 断开服务器
        /// <summary>
        /// 断开服务器
        /// </summary>
        public static void DisconnectServer()
        {
            try
            {
                if (clientSocket != null)
                {
                    if (clientSocket.Connected) clientSocket.Disconnect(false);
                    clientSocket.Close();
                    clientSocket.Dispose();
                }
                LogUtil.Log("已断开服务器");
            }
            catch (Exception ex)
            {
                LogUtil.LogError("断开服务器失败:" + ex.Message);
            }
        }
        #endregion

        #region 心跳
        public static void StartHeartbeat()
        {
            heartbeatTimer = new System.Timers.Timer();
            heartbeatTimer.Interval = 5000;
            heartbeatTimer.Elapsed += new System.Timers.ElapsedEventHandler((obj, eea) =>
            {
                try
                {
                    SocketData data = new SocketData();
                    data.cmdType = CmdType.Heartbeat;
                    Send(clientSocket, SerializeUtil.Serialize(data));
                }
                catch (Exception ex)
                {
                    LogUtil.LogError("向服务器发送心跳包出错:" + ex.Message);
                }
            });
            heartbeatTimer.Start();
        }
        #endregion

        #region 停止心跳
        public static void StopHeartbeat()
        {
            heartbeatTimer.Stop();
        }
        #endregion

        #region Send
        /// <summary>
        /// Send
        /// </summary>
        public static void Send(Socket socket, byte[] data)
        {
            lock (_lockSend)
            {
                byte[] lenArr = BitConverter.GetBytes(data.Length);
                int sendTotal = 0;
                while (sendTotal < lenArr.Length)
                {
                    int sendOnce = socket.Send(lenArr, sendTotal, lenArr.Length - sendTotal, SocketFlags.None);
                    sendTotal += sendOnce;
                    Thread.Sleep(1);
                }
                Thread.Sleep(1);

                int block = 10240;
                int count = (data.Length - 1) / block + 1;
                for (int i = 0; i < count; i++)
                {
                    int currentBlock = block;
                    if (i == count - 1)
                    {
                        currentBlock = data.Length - block * i;
                    }
                    sendTotal = 0;
                    while (sendTotal < currentBlock)
                    {
                        int sendOnce = socket.Send(data, i * block + sendTotal, currentBlock - sendTotal, SocketFlags.None);
                        sendTotal += sendOnce;
                        Thread.Sleep(1);
                    }
                    Thread.Sleep(1);
                }
            }
        }
        #endregion

        #region Receive
        /// <summary>
        /// Receive
        /// </summary>
        private static byte[] Receive(Socket socket)
        {
            lock (socket)
            {
                try
                {
                    int block = 4;
                    byte[] buffer = new byte[block];
                    int receiveCount = socket.Receive(buffer, 0, block, SocketFlags.None);
                    if (receiveCount == 0)
                    {
                        return null;
                    }
                    else
                    {
                        while (receiveCount < block)
                        {
                            int revCount = socket.Receive(buffer, receiveCount, buffer.Length - receiveCount, SocketFlags.None);
                            receiveCount += revCount;
                            Thread.Sleep(1);
                        }
                        int dataLength = BitConverter.ToInt32(buffer, 0);
                        block = 10240;
                        receiveCount = 0;
                        byte[] result = new byte[dataLength];
                        while (receiveCount < dataLength)
                        {
                            int revCount = socket.Receive(result, receiveCount, result.Length - receiveCount, SocketFlags.None);
                            receiveCount += revCount;
                            Thread.Sleep(1);
                        }
                        try
                        {
                            SerializeUtil.Deserialize(result);
                        }
                        catch (Exception ex)
                        {
                            LogUtil.LogError("数据检验失败!");
                            string aa = ex.Message;
                        }
                        return result;
                    }
                }
                catch (Exception ex)
                {
                    LogUtil.LogError("接收数据出错:" + ex.Message + "\r\n" + ex.StackTrace);
                    return null;
                }
            }
        }
        #endregion

        #region IsZero
        /// <summary>
        /// IsZero
        /// </summary>
        private static bool IsZero(byte[] data)
        {
            bool bl = true;
            foreach (byte b in data)
            {
                if (b != 0)
                {
                    return false;
                }
            }
            LogUtil.LogError("接收的字节数组内容全是0");
            return bl;
        }
        #endregion

        #region 请求
        /// <summary>
        /// 请求
        /// </summary>
        public static object Request(SocketData data)
        {
            try
            {
                ConnectServer();

                Send(clientSocket, SerializeUtil.Serialize(data));

                byte[] receiveByteArr = null;
                receiveByteArr = Receive(clientSocket);
                if (receiveByteArr != null)
                {
                    object result = SerializeUtil.Deserialize(receiveByteArr);
                    if (result.GetType() == typeof(string) && result.ToString().IndexOf("error:") == 0)
                    {
                        string errMsg = result.ToString().Split(':')[1];
                        LogUtil.LogError(errMsg);
                        throw new Exception(errMsg);
                    }
                    return result;
                }
                else
                {
                    if (clientSocket.Connected) clientSocket.Disconnect(false);
                    clientSocket.Close();
                    clientSocket.Dispose();
                    return Request(data);
                }
            }
            catch (Exception ex)
            {
                if (clientSocket.Connected) clientSocket.Disconnect(false);
                LogUtil.LogError(ex.Message);
                throw ex;
            }
        }
        #endregion

        #region Request 请求
        /// <summary>
        /// 请求
        /// </summary>
        public static object Request(string className, string methodName, object[] param)
        {
            SocketData data = new SocketData();
            data.className = className;
            data.functionName = methodName;
            data.funParam = param;
            return Request(data);
        }
        #endregion

    }
}
View Code

三、服务端的服务接口类:

DemoService:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using DAL;
using Models;

namespace DataService
{
    /// <summary>
    /// socket服务
    /// </summary>
    public class DemoService
    {
        public List<BS_NoticeType_ext> GetList(ref PagerModel pager, out string str)
        {
            NoticeTypeDal noticeTypeDal = new NoticeTypeDal();
            str = "测试123";
            return noticeTypeDal.GetList(ref pager);
        }

        
                      

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
C#实现USB接口的程序代码发布时间:2022-07-10
下一篇:
C#文件夹拷贝迭代发布时间:2022-07-10
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap