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写学生成绩管理系统后,很茫然如何让别人都能看到或者说使 ...
随机推荐
- [转]runtime 消息机制
原文地址:http://www.jianshu.com/p/f6300eb3ec3d 一.关于runtime 之前在项目中有遇到过用runtime解决改变全局字体的问题,所以再一次感受到了runtim ...
- 网站压力负载测试工具:Web版已逝,只好送大伙单机版
前言: 最近老板资金周转出了点问题,工资好久没发了,于是暂闲置在家,静待老板弄到钱东山再起的消息: QQ群里,偶尔不时的会有人问,原来的分布式网站负载工具怎么下载不了啦?或者不能用啦?之类的问题. 我 ...
- 10年微软MVP路(如何成为一个MVP?)
搞微软技术的,大家或多或少都有听说过微软的"最有价值专家"(MVP), 从2006年到2015年连续10年ASP.NET/IIS MVP.当年很多一起搞微软技术的朋友都转搞其他非微 ...
- 剑指Offer面试题:18.二叉树的镜像
一.题目:二叉树的镜像 题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像.例如下图所示,左图是原二叉树,而右图则是该二叉树的镜像. 该二叉树节点的定义如下,采用C#语言描述: public c ...
- 关于printf错用格式化字符串导致double和long double输出错误的小随笔
[题外话] 以前用HUSTOJ给学校搭建Online Judge,所有的评测都是在Linux下进行的.后来为了好往学校服务器上部署,所以大家重新做了一套Online Judge,Web和Judge都是 ...
- 使用border做三角形
网站上经常会使用一些三角形,除了图片的方式,实际上利用border我们可以做出纯CSS的三角形.我们知道border是个边抖可以单独设置,当四个边相交的时候他们是什么时候改变的? .t0{ margi ...
- S1293和S2220KTV项目结束
1.界面原型(前台的界面搭建一下) 2.数据库 3.架构设计 4.约定的文件抽取 2015年7月20日下午 歌星点歌三界面的联动,数据动态加载 01.点击第一个LIstView,弹出第二个ListVi ...
- SSH实战 · AJAX异步校验
前台JS代码 /*异步验证用户名的输入格式以及是否存在*/ function CheckUsername(){ /*取到用户名输入框*/ var nametxt = documen ...
- Leetcode-268 Missing Number
#268. Missing Number Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find ...
- 免费获取WP之类的开发者权限或免费使用Azure 2015-10-19
上一次弄wp真机调试的时候,卡住了,这里讲一下怎么解决(http://www.cnblogs.com/dunitian/p/4870959.html) 进这个网址注册一下:https://www.dr ...