Socket封装,支持多客户端,支持大文件传输,支持多线程并发,对较大的Socket包进行分块传输。
封装所要达到的效果,是可以像下面这样使用Socket和服务端通信,调用服务端的方法,让你在使用Socket的时候,感觉不到Socket的存在,就像是调用本地方法一样,并且支持ref参数和out参数:
DemoService demoService = new DemoService();DemoService2 demoService2 = DemoService2();string result = demoService.Test("测试DemoService",1);demoService.Test2();string result2 = demoService2.RunTest(测试DemoService22);
一、数据结构:
CmdType:
using System; System.Collections.Generic; System.linq; System.Text; System.Threading.Tasks;namespace DataStruct{ /// <summary> /// cmd类型 </summary> public enum CmdType { <summary> 执行方法 </summary> RunFunction = , 心跳 </summary> Heartbeat = 2 }}VIEw Code
SocketData:
Socket数据 </summary> [Serializable] class SocketData { 命令类型 </summary> public CmdType cmdType { get; set; } 类名 string classname { 方法名 string functionname { 方法参数 object[] funParam { ; } }}VIEw Code
SocketResult:
System.Text; Socket返回 SocketResult { 方法返回值 object returnValue { object[] param { ; } }}VIEw Code
FunctionUtil(根据SocketData执行服务端的方法):
System.IO; System.Reflection; DataStruct.Utils{ 执行方法 FunctionUtil { static object RunFunction(string applicationPath,SocketData socketData) { Assembly assembly = Assembly.Loadfile(Path.Combine(applicationPath,1)">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 = SocketResult(); socketResult.returnValue = result; socketResult.param = new object[socketData.funParam.Length]; 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通信封装:
System.Configuration; System.Net; System.Net.sockets; System.Threading; DataStruct.Utils; Socket封装 SocketHelper { #region 变量 private object _lockSend = (); static Socket serverSocket; Socket clIEntSocket; static List<Socket> clIEntList = new List<Socket> System.Timers.Timer heartbeatTimer; #endregion #region 启动服务 启动服务 voID StartServer() { try { int port = Convert.ToInt32(ConfigurationManager.AppSettings[ServerPort]); IPEndPoint ipEndPoint = IPEndPoint(IPAddress.Any,port); serverSocket = Socket(ipEndPoint.AddressFamily,SocketType.Stream,ProtocolType.Tcp); serverSocket.Bind(ipEndPoint); serverSocket.Listen(10); new Thread(new ThreadStart(delegate() { while (true) { Socket m_ClIEnt; { m_ClIEnt = serverSocket.Accept(); m_ClIEnt.SendTimeout = 20000; m_ClIEnt.ReceiveTimeout = ; m_ClIEnt.SendBufferSize = 10240; m_ClIEnt.ReceiveBufferSize = ; clIEntList.Add(m_ClIEnt); LogUtil.Log(监听到新的客户端,当前客户端数: clIEntList.Count); } catch { break; } DateTime lastHeartbeat = DateTime.Now; () { { ) { byte[] receiveByteArr = ; { receiveByteArr = Receive(m_ClIEnt); } ; } if (receiveByteArr != ) { SocketData data = (SocketData)SerializeUtil.Deserialize(receiveByteArr); if (data.cmdType != CmdType.Heartbeat) { object obj = ; { 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(接收客户端数据,并向客户端返回数据); } { lastHeartbeat = DateTime.Now; LogUtil.Log(收到心跳包,客户端连接正常); } } { clIEntList.Remove(m_ClIEnt); LogUtil.Log(客户端正常关闭,当前客户端数: clIEntList.Count); if (m_ClIEnt.Connected) m_ClIEnt.disconnect(false); m_ClIEnt.Close(); m_ClIEnt.dispose(); ; } } } (Exception ex) { LogUtil.LogError(ex.Message + ex.StackTrace); { Send(m_ClIEnt,1)">error: ex.Message)); } { } } })).Start(); //检测客户端 ) { DateTime Now = DateTime.Now; if (Now.Subtract(lastHeartbeat).TotalSeconds > 300) { clIEntList.Remove(m_ClIEnt); LogUtil.Log(客户端已失去连接,当前客户端数:; } Thread.Sleep(500); } } (Exception ex) { LogUtil.LogError(检测客户端出错: ex.StackTrace); } })).Start(); } })).Start(); LogUtil.Log(服务已启动); } (Exception ex) { LogUtil.LogError(启动服务出错: ex.StackTrace); } } #region 停止服务 停止服务 StopServer() { foreach (Socket socket in clIEntList) { if (socket.Connected) socket.disconnect(); socket.Close(); socket.dispose(); } clIEntList.Clear(); if (serverSocket != ) { if (serverSocket.Connected) serverSocket.disconnect(); serverSocket.Close(); serverSocket.dispose(); } LogUtil.Log(服务已停止停止服务出错:#region 连接服务器 连接服务器 ConnectServer() { if (clIEntSocket == null || !clIEntSocket.Connected) { if (clIEntSocket != ) { clIEntSocket.Close(); clIEntSocket.dispose(); } string ip = ConfigurationManager.AppSettings[ServerIP]; ]); IPEndPoint ipep = IPEndPoint(IPAddress.Parse(ip),port); clIEntSocket = Socket(ipep.AddressFamily,ProtocolType.Tcp); clIEntSocket.SendTimeout = ; clIEntSocket.ReceiveTimeout = ; clIEntSocket.SendBufferSize = ; clIEntSocket.ReceiveBufferSize = ; clIEntSocket.Connect(ipep); LogUtil.Log(已连接服务器); } } 连接服务器失败: ex.Message); } } #region 断开服务器 断开服务器 disconnectServer() { if (clIEntSocket.Connected) clIEntSocket.disconnect(); clIEntSocket.Close(); clIEntSocket.dispose(); } LogUtil.Log(已断开服务器断开服务器失败:#region 心跳 StartHeartbeat() { heartbeatTimer = System.Timers.Timer(); heartbeatTimer.Interval = 5000; heartbeatTimer.Elapsed += new System.Timers.ElapsedEventHandler((obj,eea) => { SocketData data = SocketData(); data.cmdType = CmdType.Heartbeat; Send(clIEntSocket,SerializeUtil.Serialize(data)); } (Exception ex) { LogUtil.LogError(向服务器发送心跳包出错: ex.Message); } }); heartbeatTimer.Start(); } #region 停止心跳 StopHeartbeat() { heartbeatTimer.Stop(); } #region Send Send 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(); } Thread.Sleep(); int block = int count = (data.Length - 1) / block + 0; i < count; i++int currentBlock = block; if (i == count - ) { currentBlock = data.Length - block * i; } sendTotal = ; currentBlock) { int sendOnce = socket.Send(data,i * block + sendTotal,currentBlock - sendOnce; Thread.Sleep(); } Thread.Sleep(); } } } #region Receive Receive [] Receive(Socket socket) { (socket) { { 4byte[] buffer = [block]; int receiveCount = socket.Receive(buffer,block,SocketFlags.None); if (receiveCount == ) { return ; } { while (receiveCount < block) { int revCount = socket.Receive(buffer,receiveCount,buffer.Length - receiveCount,SocketFlags.None); receiveCount += revCount; Thread.Sleep(); } int dataLength = BitConverter.ToInt32(buffer,1)">); block = ; receiveCount = ; byte[] result = [dataLength]; dataLength) { int revCount = socket.Receive(result,result.Length - { SerializeUtil.Deserialize(result); } (Exception ex) { LogUtil.LogError(数据检验失败!); string aa = ex.Message; } result; } } 接收数据出错: ex.StackTrace); ; } } } #region IsZero IsZero bool IsZero(bool bl = ; foreach (byte b data) { if (b != ; } } LogUtil.LogError(接收的字节数组内容全是0); bl; } #region 请求 请求 Request(SocketData data) { { ConnectServer(); Send(clIEntSocket,SerializeUtil.Serialize(data)); ; receiveByteArr = Receive(clIEntSocket); SerializeUtil.Deserialize(receiveByteArr); if (result.GetType() == typeof(string) && result.ToString().IndexOf(") == string errMsg = result.ToString().Split(':')[]; LogUtil.LogError(errMsg); throw Exception(errMsg); } result; } ); clIEntSocket.Close(); clIEntSocket.dispose(); Request(data); } } (Exception ex) { ); LogUtil.LogError(ex.Message); throw ex; } } #region Request 请求 object Request(string classname,1)">string methodname,1)">[] param) { SocketData data = SocketData(); data.classname = classname; data.functionname = methodname; data.funParam = param; Request(data); } #endregion }}VIEw Code
三、服务端的服务接口类:
DemoService:
System.Threading.Tasks; DAL; Models; DataService{ socket服务 DemoService { public List<BS_NoticeType_ext> GetList(ref PagerModel pager,1)">out str) { NoticeTypeDal noticeTypeDal = NoticeTypeDal(); str = 测试123return noticeTypeDal.GetList(ref pager); } string Test(string str,1)">int n) { return str + : n; } voID Test2(string s = str +voID Uploadfile(string filename,1)">byte[] fileData,1)"> index) { string path = @"C:\documents and Settings\administrator\桌面\XXPLServer\files\string path = @"D:\_临时文件\文件\"; string path = @"C:\Users\administrator\Desktop\suxtest\file\"; string path = @"C:\documents and Settings\administrator\桌面\Server\上传文件\"; if (index == ) { using (fileStream fs = new fileStream(path + filename,fileMode.Create,fileAccess.Write)) { fs.Write(fileData,fileData.Length); fs.Close(); } } VIEw CodeDemoService2:
DataService{ DemoService2 { string RunTest( n; } }}VIEw Code四、客户端接口类代码:
DemoService:
DataStruct; Common.Utils; ClIEntService{ str) { SocketResult result = (SocketResult)ServiceUtil.Request(this.GetType().name,MethodBase.GetCurrentMethod().name,object[] { pager,1)"> }); pager = (PagerModel)result.param[]; str = (string)result.param[]; return (List<BS_NoticeType_ext>)result.returnValue; } n) { SocketResult result = (SocketResult)ServiceUtil.Request([] { str,n }); result.returnValue.ToString(); } bool Uploadfile( { ServiceUtil.Request([] { filename,fileData,index }); ; } ; } } }}VIEw CodeDemoService2:
DataStruct; result.returnValue.ToString(); } }}VIEw Code五:服务端启动服务:
System.ComponentModel; System.Data; System.Drawing; System.Runtime.Serialization.Formatters.Binary; System.windows.Forms; DataStruct.Utils; Newtonsoft.Json; XXPLServer{ partial Form1 : Form { #region Form1构造函数 public Form1() { InitializeComponent(); } #region Form1_Load voID Form1_Load( sender,EventArgs e) { } #region 启动服务 voID btnStartServer_Click(; btnStartServer.Enabled = ; SocketHelper.StartServer(); } #region 停止服务 voID btnStopServer_Click(; SocketHelper.StopServer(); } #region Form1_FormClosing voID Form1_FormClosing(); } }}VIEw Code六:客户端测试代码:
CommonDll; ClIEntService; System.Diagnostics; XXPLClIEnt{ 连接服务器 SocketHelper.StartHeartbeat(); 心跳 } voID btnTest_Click(0; i < 1; i++new ParameterizedThreadStart((obj) =>int j = 0; j < 1; j++) { DemoService demoService = DemoService(); DemoService2 demoService2 = DemoService2(); string str = demoService.Test(1) + " + demoService2.RunTest(); MessageBox.Show(str); } } (Exception ex) { LogUtil.LogError(ex.Message); MessageBox.Show(ex.Message); } })).Start(); } } voID btnUpload_Click(if (openfileDialog1.ShowDialog() == DialogResult.OK) { 1048576byte[] barr = [block]; filename; fileStream(openfileDialog1.filename,fileMode.Open,fileAccess.Read)) { filename = Path.Getfilename(fs.name); long count = (fs.Length - ; DemoService demoService = DemoService(); ) { if (i != count - ) { fs.Read(barr,barr.Length); } { int len = (int)(fs.Length - block * i); barr = [len]; fs.Read(barr,1)">bool bl = demoService.Uploadfile(filename,barr,i + ); while (!bl) { bl = demoService.Uploadfile(filename,1)">); LogUtil.LogError(发生错误,重发); Thread.Sleep(20); } Thread.Sleep(); } fs.Close(); } MessageBox.Show(成功); })).Start(); } (Exception ex) { MessageBox.Show(ex.Message); } } } voID button1_Click( { DemoService demoService = DemoService(); PagerModel pager = PagerModel(); pager.page = ; pager.rows = str; List<BS_NoticeType_ext> List = demoService.GetList(ref pager,1)">out str); MessageBox.Show(string.Format(数据总条数:{0}\r\n页数:{1}\r\nout参数值:{2}\r\n第一条数据:{3}].name)); } string ss = ex.Message; } } }}VIEw Code七:大文件分块上传:
服务端DemoService添加如下方法:
index){ ; string path = @"D:\_临时文件\文件\"; string path = @"C:\Users\administrator\Desktop\suxtest\file\"; string path = @"C:\documents and Settings\administrator\桌面\Server\上传文件\"; ) { { VIEw Code客户端DemoService添加如下方法:
{ ServiceUtil.Request(; } ; }}VIEw Code客户端选择文件上传:
DialogResult.OK) { { [block]; filename; Path.Getfilename(fs.name); ; ) { fs.Read(barr,barr.Length); } { i); barr = [len]; fs.Read(barr,barr.Length); } DemoService demoService = DemoService(); ); bl) { bl = demoService.Uploadfile(filename,1)">); LogUtil.LogError(); Thread.Sleep(); } Thread.Sleep(); } fs.Close(); } MessageBox.Show(); })).Start(); } (Exception ex) { MessageBox.Show(ex.Message); } }}VIEw Code总结
以上是内存溢出为你收集整理的C# .NET Socket封装全部内容,希望文章能够帮你解决C# .NET Socket封装所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)