首页 > 程序开发 > 综合编程 > 其他综合 >

C# .NET Socket封装

2016-07-07

C NET Socket封装 DemoService demoService = new DemoService(); DemoService2 demoService2 = new DemoService2(); string result = demoService Test( "测试DemoService ", 1); demoService Test2( "测试DemoService ", 1);

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
{
    /// 
    /// cmd类型
    /// 
    public enum CmdType
    {
        /// 
        /// 执行方法
        /// 
        RunFunction = 1,
        /// 
        /// 心跳
        /// 
        Heartbeat = 2
    }
}
View Code

SocketData:

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

namespace DataStruct
{
    /// 
    /// Socket数据
    /// 
    [Serializable]
    public class SocketData
    {
        /// 
        /// 命令类型
        /// 
        public CmdType cmdType { get; set; }
        /// 
        /// 类名
        /// 
        public string className { get; set; }
        /// 
        /// 方法名
        /// 
        public string functionName { get; set; }
        /// 
        /// 方法参数
        /// 
        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
{
    /// 
    /// 执行方法
    /// 
    public class FunctionUtil
    {
        /// 
        /// 执行方法
        /// 
        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 m_ClientList = new List();
        #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
{
    /// 
    /// socket服务
    /// 
    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
{
    /// 
    /// 服务
    /// 
    public class ServiceUtil
    {
        public static Socket clientSocket;
        public static object _lock = new object();

        /// 
        /// 连接服务器
        /// 
        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);
            }
        }

        /// 
        /// 请求
        /// 
        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;
                }
            }
        }

        /// 
        /// 请求
        /// 
        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

七:大文件分块上传:

服务端DemoService添加如下方法:

\\
public void UploadFile(string fileName, byte[] fileData, int index)
{
    string path = @"C:\Users\Administrator\Desktop\suxtest\file\";
    //string path = @"C:\Documents and Settings\Administrator\桌面\Debug\file\";
    if (index == 1)
    {
        using (FileStream fs = new FileStream(path + fileName, FileMode.Create, FileAccess.Write))
        {
            fs.Write(fileData, 0, fileData.Length);
            fs.Close();
        }
    }
    else
    {
        using (FileStream fs = new FileStream(path + fileName, FileMode.Append, FileAccess.Write))
        {
            fs.Write(fileData, 0, fileData.Length);
            fs.Close();
        }
    }
}
View Code

客户端DemoService添加如下方法:

\\
public bool UploadFile(string fileName, byte[] fileData, int index)
{
    try
    {
        object result = ServiceUtil.Request(this.GetType().Name,
                MethodBase.GetCurrentMethod().Name,
                new object[] { fileName, fileData, index });
        return true;
    }
    catch
    {
        return false;
    }
}
View Code

客户端选择文件上传:

\\
private void btnUpload_Click(object sender, EventArgs e)
{
    if (openFileDialog1.ShowDialog() == DialogResult.OK)
    {
        try
        {
            new Thread(new ParameterizedThreadStart((obj) =>
            {
                byte[] bArr = new byte[102400];
                string fileName;
                using (FileStream fs = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read))
                {
                    fileName = Path.GetFileName(fs.Name);
                    long count = (fs.Length - 1) / 102400 + 1;

                    for (int i = 0; i < count; i++)
                    {
                        if (i != count - 1)
                        {
                            fs.Read(bArr, 0, bArr.Length);
                        }
                        else
                        {
                            int len = (int)(fs.Length - 102400 * i);
                            bArr = new byte[len];
                            fs.Read(bArr, 0, bArr.Length);
                        }
                        DemoService demoService = new DemoService();
                        bool bl = demoService.UploadFile(fileName, bArr, i + 1);
                        while (!bl)
                        {
                            bl = demoService.UploadFile(fileName, bArr, i + 1);
                            LogUtil.LogError("发生错误,重发");
                            Thread.Sleep(20);
                        }
                        Thread.Sleep(20);
                    }
                    fs.Close();
                }

                MessageBox.Show("成功");
            })).Start();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
}

相关文章
最新文章
热点推荐