C# .NET Socket封装
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封装的更多相关文章
- ACE - 代码层次及Socket封装
原文出自http://www.cnblogs.com/binchen-china,禁止转载. ACE源码约10万行,是c++中非常大的一个网络编程代码库,包含了网络编程的边边角角.在实际使用时,并不是 ...
- 跨平台的游戏客户端Socket封装,调整
原文链接:http://www.cnblogs.com/lancidie/archive/2013/04/13/3019359.html 头文件: #pragma once #ifdef WIN32 ...
- Linux C socket 封装
/************************************************************************** * Linux C socket 封装 * 声明 ...
- web前端socket封装库--giraffe
摘要: 最近在做前端的socket消息推送,使用了socket.io.js的最新版本.使用过的都知道socket.io.js是基于消息类型来通信的,如果消息类型多了就很难维护.所以本人就对socket ...
- 一个高性能异步socket封装库的实现思路 (c#)
前言 socket是软件之间通讯最常用的一种方式.c#实现socket通讯有很多中方法,其中效率最高就是异步通讯. 异步通讯实际是利用windows完成端口(IOCP)来处理的,关于完成端口实现原理, ...
- python进阶__用socket封装TCP
想要理解socket协议,点击链接,出门左转 一.TCP 通信的服务器端编程的基本步骤: 服务器端先创建一个 socket 对象. 服务器端 socket 将自己绑定到指定 IP 地址和端口. 服务器 ...
- 从零开始—Socket系统调用和多态封装
1 重新搭建实验环境 前面都是用实验楼环境做的实验,偷的懒总是要还的,这一次重装环境前后花了十几个小时,踩了无数的坑. 1.1 Ubuntu和LINUX内核的区别 Ubuntu是基于LINUX内核编写 ...
- C++ Socket 简单封装
以下代码一部分来自于<网络多人游戏架构与编程>, 其它的都是我瞎写的. 备忘. 一个简单的Socket封装,没有做什么高级的操作(比如IO完成端口等等). 1 #pragma once 2 ...
- 试解析Tomcat运行原理(一)--- socket通讯
关于这篇文章也确实筹划了很久,今天决定开篇写第一篇,说起tomcat首先很容易联想到IIS,因为我最开始使用的就是.net技术,我第一次使用asp写学生成绩管理系统后,很茫然如何让别人都能看到或者说使 ...
随机推荐
- 解决读取iphone名称中文乱码问题
#region 解决中文乱码 Ethan 2016-01-06 [DllImport("iTunesMobileDevice.dll", CallingConvention = C ...
- 如何知道SQL Server机器上有多少个NUMA节点
如何知道SQL Server机器上有多少个NUMA节点 文章出处: How can you tell how many NUMA nodes your SQL Server has? http://i ...
- 剑指Offer面试题:6.用两个栈实现队列
一.题目:用两个栈实现队列 题目:用两个栈实现一个队列.队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能. 原文是使用 ...
- SQL Agent服务无法启动如何破
问题现象 从阿里云上镜像过来的一台的数据库服务器,SQL Agent服务启动不了,提示服务启动后停止.(原数据库服务器是正常的,怀疑跟镜像有关) 如下是系统日志和SQL Agent的日志 SQLSer ...
- Go语言实战 - revel框架教程之用户注册
用户注册.登录和注销是任何一个网站都必然会有的功能,可以说,这是重新造轮子做多的领域,每个做网站的人应该都做过很多遍.见微知著,从这么一个小功能其实就可以看到所使用的web框架中的大部分东西. 今天就 ...
- 特邀美国EMC实战专家Mark来华授课
“轻松搞定EMC-PCB和系统设计”课程介绍 本次课程特邀美国EMC领域权威专家Mark Montrose主讲,将涵盖满足产品电磁兼容性和信号完整性的基本原理.课程涉及多个领域,不仅仅针对PCB设计, ...
- Docker实践:安装wordpress
本文将示例如何使用Docker来安装wordpress.使用三种方法: 1.基于官方的wordpress镜像使用docker run实现: 2.基于官方的wordpress镜像使用fig命令编排工具实 ...
- 在Thinkphp3.2.3框架下实现自动获取客户端IP地址的get_client_ip()函数
在Thinkphp框架下使用get_client_ip()函数获取客户端IP地址十分方便: 一行代码便可以实现:$ip = get_client_ip(); 但当我们测试时会遇到后台获取的IP地址显示 ...
- 谈谈关键字strictfp
Java语言中的其中一个设计目标是可移植性.无论在哪个虚拟机上运行,同一个计算应该得到同样的结果.对于浮点数的算术运算,实现这样的可移植性是相当困难的.double 类型使用 64 位存储一个 do ...
- 编译opengl编程指南第八版示例代码通过
最近在编译opengl编程指南第八版的示例代码,如下 #include <iostream> #include "vgl.h" #include "LoadS ...