码迷,mamicode.com
首页 > Windows程序 > 详细

C# .NET Socket封装

时间:2016-07-06 13:23:47      阅读:328      评论:0      收藏:0      [点我收藏+]

标签:

    Socket封装,支持多客户端。

    封装所要达到的效果,是可以像下面这样使用Socket和服务端通信,调用服务端的方法:

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

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 obj = assembly.CreateInstance("DataService." + socketData.className);
            Type type = obj.GetType();
            return type.GetMethod(socketData.functionName).Invoke(obj, socketData.funParam);
        }
    }
}
View Code

二、服务端Socket通信:

技术分享
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Common.Utils;
using CommonDll;
using DataService;
using DataStruct;
using DataStruct.Utils;
using Newtonsoft.Json;

namespace XXPLServer
{
    public partial class Form1 : Form
    {
        #region 变量
        private Socket m_ServerSocket;
        private List<Socket> m_ClientList = new List<Socket>();
        #endregion

        #region Form1构造函数
        public Form1()
        {
            InitializeComponent();
        }
        #endregion

        #region Form1_Load
        private void Form1_Load(object sender, EventArgs e)
        {

        }
        #endregion

        #region 启动服务
        private void btnStartServer_Click(object sender, EventArgs e)
        {
            try
            {
                btnStartServer.Enabled = false;
                btnStopServer.Enabled = true;
                int port = Convert.ToInt32(ConfigurationManager.AppSettings["ServerPort"]);
                IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, port);
                m_ServerSocket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                m_ServerSocket.Bind(ipEndPoint);
                m_ServerSocket.Listen(10);
                new Thread(new ThreadStart(delegate()
                {
                    while (true)
                    {
                        Socket m_Client;
                        try
                        {
                            m_Client = m_ServerSocket.Accept();
                            m_Client.SendTimeout = 20000;
                            m_Client.ReceiveTimeout = 20000;
                            m_ClientList.Add(m_Client);
                            LogUtil.Log("监听到新的客户端,当前客户端数:" + m_ClientList.Count);
                        }
                        catch { break; }

                        DateTime lastHeartbeat = DateTime.Now;
                        new Thread(new ThreadStart(delegate()
                        {
                            try
                            {
                                while (true)
                                {
                                    byte[] inBuffer = new byte[m_Client.ReceiveBufferSize];
                                    int receiveCount;
                                    try
                                    {
                                        receiveCount = m_Client.Receive(inBuffer, m_Client.ReceiveBufferSize, SocketFlags.None);//如果接收的消息为空 阻塞 当前循环 
                                    }
                                    catch { break; }
                                    if (receiveCount != 0)
                                    {
                                        SocketData data = (SocketData)SerializeUtil.Deserialize(inBuffer);
                                        if (data.cmdType != CmdType.Heartbeat)
                                        {
                                            object obj = FunctionUtil.RunFunction(Application.StartupPath, data);
                                            m_Client.Send(SerializeUtil.Serialize(obj));
                                            LogUtil.Log("接收客户端数据,并向客户端返回数据");
                                        }
                                        else
                                        {
                                            lastHeartbeat = DateTime.Now;
                                        }
                                    }
                                    else
                                    {
                                        m_ClientList.Remove(m_Client);
                                        LogUtil.Log("客户端正常关闭,当前客户端数:" + m_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);
                            }
                        })).Start();

                        //检测客户端
                        new Thread(new ThreadStart(delegate()
                        {
                            try
                            {
                                while (true)
                                {
                                    DateTime now = DateTime.Now;
                                    if (now.Subtract(lastHeartbeat).TotalSeconds > 20)
                                    {
                                        m_ClientList.Remove(m_Client);
                                        LogUtil.Log("客户端已失去连接,当前客户端数:" + m_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 停止服务
        private void btnStopServer_Click(object sender, EventArgs e)
        {
            btnStopServer.Enabled = false;
            btnStartServer.Enabled = true;
            foreach (Socket socket in m_ClientList)
            {
                if (socket.Connected) socket.Disconnect(false);
                socket.Close();
                socket.Dispose();
            }
            if (m_ServerSocket != null)
            {
                if (m_ServerSocket.Connected) m_ServerSocket.Disconnect(false);
                m_ServerSocket.Close();
                m_ServerSocket.Dispose();
            }
            LogUtil.Log("服务已停止");
        }
        #endregion

        #region Form1_FormClosing
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            foreach (Socket socket in m_ClientList)
            {
                if (socket.Connected) socket.Disconnect(false);
                socket.Close();
                socket.Dispose();
            }
            if (m_ServerSocket != null)
            {
                if (m_ServerSocket.Connected) m_ServerSocket.Disconnect(false);
                m_ServerSocket.Close();
                m_ServerSocket.Dispose();
            }
            LogUtil.Log("服务已停止");
        }
        #endregion

    }
}
View Code

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

DemoService:

技术分享
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DataService
{
    /// <summary>
    /// socket服务
    /// </summary>
    public class DemoService
    {
        public string Test(string str, int n)
        {
            return str + "" + n;
        }

        public void Test2(string str, int n)
        {
            string s = str + n;
        }
    }
}
View Code

DemoService2:

技术分享
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DataService
{
    public class DemoService2
    {
        public string RunTest(string str, int n)
        {
            return str + "" + n;
        }
    }
}
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;
using CommonDll;

namespace Common.Utils
{
    /// <summary>
    /// 服务
    /// </summary>
    public class ServiceUtil
    {
        public static Socket clientSocket;
        public static object _lock = new object();

        /// <summary>
        /// 连接服务器
        /// </summary>
        public static void ConnectServer()
        {
            if (clientSocket == null || !clientSocket.Connected)
            {
                if (clientSocket != null)
                {
                    clientSocket.Close();
                    clientSocket.Dispose();
                }
                string ip = ConfigurationManager.AppSettings["ServerIP"];
                IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(ip), 3001);
                clientSocket = new Socket(ipep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                clientSocket.SendTimeout = 20000;
                clientSocket.ReceiveTimeout = 20000;
                clientSocket.Connect(ipep);
            }
        }

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

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

                    byte[] inBuffer = new byte[clientSocket.ReceiveBufferSize];
                    int count = clientSocket.Receive(inBuffer, clientSocket.ReceiveBufferSize, SocketFlags.None);//如果接收的消息为空 阻塞 当前循环 
                    if (count > 0)
                    {
                        return SerializeUtil.Deserialize(inBuffer);
                    }
                    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;
                }
            }
        }

        /// <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 ServiceUtil.Request(data);
        }
    }
}
View Code

六、客户端接口类代码:

DemoService:

技术分享
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DataStruct;
using Common.Utils;
using System.Reflection;

namespace ClientService
{
    public class DemoService
    {
        public string Test(string str, int n)
        {
            object result = ServiceUtil.Request(this.GetType().Name,
                 MethodBase.GetCurrentMethod().Name,
                 new object[] { str, n });
            return result.ToString();
        }

        public void Test2(string str, int n)
        {
            object result = ServiceUtil.Request(this.GetType().Name,
                 MethodBase.GetCurrentMethod().Name,
                 new object[] { str, n });
        }
    }
}
View Code

DemoService2:

技术分享
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Common.Utils;
using DataStruct;

namespace ClientService
{
    public class DemoService2
    {
        public string RunTest(string str, int n)
        {
            object result = ServiceUtil.Request(this.GetType().Name,
                MethodBase.GetCurrentMethod().Name,
                new object[] { str, n });
            return result.ToString();
        }
    }
}
View Code

六:客户端测试代码:

技术分享
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Common.Utils;
using CommonDll;
using DataStruct;
using ClientService;

namespace XXPLClient
{
    public partial class Form1 : Form
    {
        #region 变量
        private System.Timers.Timer m_timer;
        #endregion

        #region Form1构造函数
        public Form1()
        {
            InitializeComponent();
        }
        #endregion

        #region Form1_Load
        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                //连接服务器
                ServiceUtil.ConnectServer();
            }
            catch (Exception ex)
            {
                MessageBox.Show("连接服务器失败:" + ex.Message);
            }

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

        private void btnTest_Click(object sender, EventArgs e)
        {
            try
            {
                DemoService demoService = new DemoService();
                DemoService2 demoService2 = new DemoService2();
                MessageBox.Show(demoService.Test("测试DemoService", 1) + "\r\n" + demoService2.RunTest("测试DemoService2", 2));
            }
            catch (Exception ex)
            {
                LogUtil.LogError(ex.Message);
                MessageBox.Show(ex.Message);
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            m_timer.Stop();
            if (ServiceUtil.clientSocket != null)
            {
                if (ServiceUtil.clientSocket.Connected) ServiceUtil.clientSocket.Disconnect(false);
                ServiceUtil.clientSocket.Close();
                ServiceUtil.clientSocket.Dispose();
            }
        }

    }
}
View Code

 

C# .NET Socket封装

标签:

原文地址:http://www.cnblogs.com/s0611163/p/5646414.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!