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

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

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

一、数据结构:

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 = ,
/// <summary>
/// 心跳
/// </summary>
Heartbeat =
}
}

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; }
}
}

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; }
}
}

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 = ; 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;
}
}
}

二、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();
new Thread(new ThreadStart(delegate()
{
while (true)
{
Socket m_Client;
try
{
m_Client = serverSocket.Accept();
m_Client.SendTimeout = ;
m_Client.ReceiveTimeout = ;
m_Client.SendBufferSize = ;
m_Client.ReceiveBufferSize = ;
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 > )
{
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();
}
}
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 = ;
clientSocket.ReceiveTimeout = ;
clientSocket.SendBufferSize = ;
clientSocket.ReceiveBufferSize = ;
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 = ;
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 = ;
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 - ) / block + ;
for (int i = ; i < count; i++)
{
int currentBlock = block;
if (i == count - )
{
currentBlock = data.Length - block * i;
}
sendTotal = ;
while (sendTotal < currentBlock)
{
int sendOnce = socket.Send(data, i * block + sendTotal, currentBlock - sendTotal, SocketFlags.None);
sendTotal += sendOnce;
Thread.Sleep();
}
Thread.Sleep();
}
}
}
#endregion #region Receive
/// <summary>
/// Receive
/// </summary>
private static byte[] Receive(Socket socket)
{
lock (socket)
{
try
{
int block = ;
byte[] buffer = new byte[block];
int receiveCount = socket.Receive(buffer, , block, SocketFlags.None);
if (receiveCount == )
{
return null;
}
else
{
while (receiveCount < block)
{
int revCount = socket.Receive(buffer, receiveCount, buffer.Length - receiveCount, SocketFlags.None);
receiveCount += revCount;
Thread.Sleep();
}
int dataLength = BitConverter.ToInt32(buffer, );
block = ;
receiveCount = ;
byte[] result = new byte[dataLength];
while (receiveCount < dataLength)
{
int revCount = socket.Receive(result, receiveCount, result.Length - receiveCount, SocketFlags.None);
receiveCount += revCount;
Thread.Sleep();
}
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 != )
{
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:") == )
{
string errMsg = result.ToString().Split(':')[];
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 }
}

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

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);
} public string Test(string str, int n)
{
return str + ":" + n;
} public void Test2(string str, int n)
{
string s = str + n;
} public void UploadFile(string fileName, byte[] fileData, int 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();
}
}
else
{
using (FileStream fs = new FileStream(path + fileName, FileMode.Append, FileAccess.Write))
{
fs.Write(fileData, , fileData.Length);
fs.Close();
}
}
}
}
}

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;
}
}
}

四、客户端接口类代码:

DemoService:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DataStruct;
using Common.Utils;
using System.Reflection;
using Models; namespace ClientService
{
public class DemoService
{
public List<BS_NoticeType_ext> GetList(ref PagerModel pager, out string str)
{
SocketResult result = (SocketResult)ServiceUtil.Request(this.GetType().Name,
MethodBase.GetCurrentMethod().Name,
new object[] { pager, null });
pager = (PagerModel)result.param[];
str = (string)result.param[];
return (List<BS_NoticeType_ext>)result.returnValue;
} public string Test(string str, int n)
{
SocketResult result = (SocketResult)ServiceUtil.Request(this.GetType().Name,
MethodBase.GetCurrentMethod().Name,
new object[] { str, n });
return result.returnValue.ToString();
} public void Test2(string str, int n)
{
SocketResult result = (SocketResult)ServiceUtil.Request(this.GetType().Name,
MethodBase.GetCurrentMethod().Name,
new object[] { str, n });
} public bool UploadFile(string fileName, byte[] fileData, int index)
{
try
{
ServiceUtil.Request(this.GetType().Name,
MethodBase.GetCurrentMethod().Name,
new object[] { fileName, fileData, index });
return true;
}
catch
{
return false;
}
}
}
}

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)
{
SocketResult result = (SocketResult)ServiceUtil.Request(this.GetType().Name,
MethodBase.GetCurrentMethod().Name,
new object[] { str, n });
return result.returnValue.ToString();
}
}
}

五:服务端启动服务:

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 DataStruct;
using DataStruct.Utils;
using Newtonsoft.Json; namespace XXPLServer
{
public partial class Form1 : Form
{
#region 变量
#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)
{
btnStopServer.Enabled = true;
btnStartServer.Enabled = false;
SocketHelper.StartServer();
}
#endregion #region 停止服务
private void btnStopServer_Click(object sender, EventArgs e)
{
btnStopServer.Enabled = false;
btnStartServer.Enabled = true;
SocketHelper.StopServer();
}
#endregion #region Form1_FormClosing
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
SocketHelper.StopServer();
System.Environment.Exit();
}
#endregion }
}

六:客户端测试代码:

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 CommonDll;
using DataStruct;
using ClientService;
using System.IO;
using System.Diagnostics;
using Models; namespace XXPLClient
{
public partial class Form1 : Form
{
#region 变量
#endregion #region Form1构造函数
public Form1()
{
InitializeComponent();
}
#endregion #region Form1_Load
private void Form1_Load(object sender, EventArgs e)
{
SocketHelper.ConnectServer(); //连接服务器
SocketHelper.StartHeartbeat(); //心跳
}
#endregion #region Form1_FormClosing
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
SocketHelper.DisconnectServer();
SocketHelper.StopHeartbeat();
System.Environment.Exit();
}
#endregion private void btnTest_Click(object sender, EventArgs e)
{
for (int i = ; i < ; i++)
{
new Thread(new ParameterizedThreadStart((obj) =>
{
try
{
for (int j = ; j < ; j++)
{
DemoService demoService = new DemoService();
DemoService2 demoService2 = new DemoService2();
string str = demoService.Test("测试DemoService", ) + "\r\n" + demoService2.RunTest("测试DemoService2", );
MessageBox.Show(str);
}
}
catch (Exception ex)
{
LogUtil.LogError(ex.Message);
MessageBox.Show(ex.Message);
}
})).Start();
}
} private void btnUpload_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
new Thread(new ParameterizedThreadStart((obj) =>
{
int block = ;
byte[] bArr = new byte[block];
string fileName;
using (FileStream fs = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read))
{
fileName = Path.GetFileName(fs.Name);
long count = (fs.Length - ) / block + ; DemoService demoService = new DemoService();
for (int i = ; i < count; i++)
{
if (i != count - )
{
fs.Read(bArr, , bArr.Length);
}
else
{
int len = (int)(fs.Length - block * i);
bArr = new byte[len];
fs.Read(bArr, , bArr.Length);
}
bool bl = demoService.UploadFile(fileName, bArr, i + );
while (!bl)
{
bl = demoService.UploadFile(fileName, bArr, i + );
LogUtil.LogError("发生错误,重发");
Thread.Sleep();
}
Thread.Sleep();
}
fs.Close();
} MessageBox.Show("成功");
})).Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
} private void button1_Click(object sender, EventArgs e)
{
try
{
DemoService demoService = new DemoService();
PagerModel pager = new PagerModel();
pager.page = ;
pager.rows = ;
string str;
List<BS_NoticeType_ext> list = demoService.GetList(ref pager, out str);
MessageBox.Show(string.Format("数据总条数:{0}\r\n页数:{1}\r\nout参数值:{2}\r\n第一条数据:{3}",
pager.totalRows, pager.pageCount, str, list[].name));
}
catch (Exception ex)
{
string ss = ex.Message;
}
} }
}

七:大文件分块上传:

服务端DemoService添加如下方法:

public void UploadFile(string fileName, byte[] fileData, int 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();
}
}
else
{
using (FileStream fs = new FileStream(path + fileName, FileMode.Append, FileAccess.Write))
{
fs.Write(fileData, , fileData.Length);
fs.Close();
}
}
}

客户端DemoService添加如下方法:

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

客户端选择文件上传:

private void btnUpload_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
new Thread(new ParameterizedThreadStart((obj) =>
{
int block = ;
byte[] bArr = new byte[block];
string fileName;
using (FileStream fs = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read))
{
fileName = Path.GetFileName(fs.Name);
long count = (fs.Length - ) / block + ; for (int i = ; i < count; i++)
{
if (i != count - )
{
fs.Read(bArr, , bArr.Length);
}
else
{
int len = (int)(fs.Length - block * i);
bArr = new byte[len];
fs.Read(bArr, , bArr.Length);
}
DemoService demoService = new DemoService();
bool bl = demoService.UploadFile(fileName, bArr, i + );
while (!bl)
{
bl = demoService.UploadFile(fileName, bArr, i + );
LogUtil.LogError("发生错误,重发");
Thread.Sleep();
}
Thread.Sleep();
}
fs.Close();
} MessageBox.Show("成功");
})).Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}

C# .NET Socket封装的更多相关文章

  1. ACE - 代码层次及Socket封装

    原文出自http://www.cnblogs.com/binchen-china,禁止转载. ACE源码约10万行,是c++中非常大的一个网络编程代码库,包含了网络编程的边边角角.在实际使用时,并不是 ...

  2. 跨平台的游戏客户端Socket封装,调整

    原文链接:http://www.cnblogs.com/lancidie/archive/2013/04/13/3019359.html 头文件: #pragma once #ifdef WIN32 ...

  3. Linux C socket 封装

    /************************************************************************** * Linux C socket 封装 * 声明 ...

  4. web前端socket封装库--giraffe

    摘要: 最近在做前端的socket消息推送,使用了socket.io.js的最新版本.使用过的都知道socket.io.js是基于消息类型来通信的,如果消息类型多了就很难维护.所以本人就对socket ...

  5. 一个高性能异步socket封装库的实现思路 (c#)

    前言 socket是软件之间通讯最常用的一种方式.c#实现socket通讯有很多中方法,其中效率最高就是异步通讯. 异步通讯实际是利用windows完成端口(IOCP)来处理的,关于完成端口实现原理, ...

  6. python进阶__用socket封装TCP

    想要理解socket协议,点击链接,出门左转 一.TCP 通信的服务器端编程的基本步骤: 服务器端先创建一个 socket 对象. 服务器端 socket 将自己绑定到指定 IP 地址和端口. 服务器 ...

  7. 从零开始—Socket系统调用和多态封装

    1 重新搭建实验环境 前面都是用实验楼环境做的实验,偷的懒总是要还的,这一次重装环境前后花了十几个小时,踩了无数的坑. 1.1 Ubuntu和LINUX内核的区别 Ubuntu是基于LINUX内核编写 ...

  8. C++ Socket 简单封装

    以下代码一部分来自于<网络多人游戏架构与编程>, 其它的都是我瞎写的. 备忘. 一个简单的Socket封装,没有做什么高级的操作(比如IO完成端口等等). 1 #pragma once 2 ...

  9. 试解析Tomcat运行原理(一)--- socket通讯

    关于这篇文章也确实筹划了很久,今天决定开篇写第一篇,说起tomcat首先很容易联想到IIS,因为我最开始使用的就是.net技术,我第一次使用asp写学生成绩管理系统后,很茫然如何让别人都能看到或者说使 ...

随机推荐

  1. 玩转JavaScript OOP[4]——实现继承的12种套路

    概述 在之前的文章中,我们借助构造函数实现了"类",然后结合原型对象实现了"继承",并了解了JavaScript中原型链的概念. 理解这些内容,有助于我们更深入 ...

  2. Mina入门教程(二)----Spring4 集成Mina

    在spring和mina集成的时候,要十分注意一个问题:版本. 这是一个非常严重的问题,mina官网的demo没错,网上很多网友总结的代码也是对的,但是很多人将mina集成到spring中的时候,总是 ...

  3. C#温故知新:《C#图解教程》读书笔记系列

    一.此书到底何方神圣? 本书是广受赞誉C#图解教程的最新版本.作者在本书中创造了一种全新的可视化叙述方式,以图文并茂的形式.朴实简洁的文字,并辅之以大量表格和代码示例,全面.直观地阐述了C#语言的各种 ...

  4. C#图片色彩的纠正-上

    WPF(C#)图片色彩的纠正-上 WPF(C#)图片色彩的纠正-下 前言 对图片进行色彩的纠正,其实与WPF是没有什么关系的,为什么标题又是“WPF(C#)图片色彩的纠正”呢,因为这些图片色彩的纠正功 ...

  5. MySQL 常用的UPDATE操作

    标签:UPDATE 概述 测试环境:mysql 5.6.21 步骤 创建测试表 CREATE TABLE `product` ( `proID` ) NOT NULL AUTO_INCREMENT C ...

  6. SQL分页

    --第一种分页(TOP方式)-- select * from T_Sys_User where User_Id in ( User_Id from T_Sys_User where User_Id n ...

  7. Angular $watch

    如果想在某个属性发生变化的时候执行某些操作,那么scope.$watch是最佳选择 https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$w ...

  8. [erl] erlang 进程注册和注销

    想要注册一个进程,必须先要创建一个进程. 如何创建一个进程,可以使用spawn.spawn_link,它们虽然都能创建进程,但是也有微妙的区别: 1)当前进程中创建一个并行进程,当被生成的进程崩溃时, ...

  9. jsdoc

    一.javascript注释规范 我们在编写javascript文件的时候,一般会添加一些注释.例如一些文件.类.方法和属性都应该用合适的标记和类型进行注释.这里不但方便我们的阅读,也能养成一个好的习 ...

  10. KnockoutJS 3.X API 第七章 其他技术(1) 加载和保存JSON数据

    Knockout允许您实现复杂的客户端交互性,但几乎所有Web应用程序还需要与服务器交换数据,或至少将本地存储的数据序列化. 最方便的交换或存储数据的方式是JSON格式 - 大多数Ajax应用程序今天 ...