1.创建Socket对象
public Socket Socket
{
get;
private set;
}
2.绑定监听端口-Bind
public bool Start(string ipString, int port)
{
IPAddress address = null;
IPAddress.TryParse(ipString, out address);
if (address == null)
{
Loggers.Logger.Info("IP地址格式不正确!" + ipString);
return false;
}
else
{
this.Bind(new IPEndPoint(address, port));
return this.Start(); //函数体在3.监听
}
}
private void Bind(EndPoint local)
{
try
{
this.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.Socket.Bind(local);
}
catch (Exception ex)
{
Loggers.Logger.Info(ex.Message);
return;
}
}
3.监听-Listen
public bool Start()
{
if (this.Socket == null)
{
Loggers.Logger.Error("Socket对象不能为空!");
return false;
}
try
{
//监听队列
this.Backlog = 10;
this.Socket.Listen(this.Backlog);
Loggers.Logger.Info("启动服务成功!" + this.Socket.LocalEndPoint.ToString());
this.State = true;
//循环接收客户端连接,启动线程池!
ThreadPool.QueueUserWorkItem(new WaitCallback(Accept));
this._SysTimer = new System.Timers.Timer();
this._SysTimer.Interval = 30 * 60 * 1000;
this._SysTimer.Elapsed += SysTimer_Elapsed;
this._SysTimer.Start();
return true;
}
catch (Exception ex)
{
Loggers.Logger.Error("启动服务异常:" + ex.ToString());
return false;
}
}
4.循环等待客户端连接-Accpet (注意:开线程池 ↑)
public void Accept(object args)
{
while (this.State && this.Socket != null)
{
try
{
Socket client = this.Socket.Accept();
lock (this._dicSessions)
{
string key = client.RemoteEndPoint.ToString();//Guid.NewGuid().ToString();
if (this._dicSessions.ContainsKey(key) == false)
{
SocketSession session = new SocketSession(key, client);
//接收信息处理函数
session.ReceiveEncoding = this.ReceiveEncoding;
session.RemoteClose += Session_RemoteClose;
session.ReceiveData += Session_ReceiveData;
this._dicSessions.Add(key, session);
if (this.RemoteConnect != null)
this.RemoteConnect(key);
//开始接收数据
session.StartReceive();
}
}
}
catch (Exception ex)
{
Loggers.Logger.Error("接收客户端异常:" + ex.ToString());
}
}
}
程序参考(仅包含服务端Bind、 Listen、 Accept相关代码,接收Receive代码请参考下面的代码)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace SMS_YBS.IOCPSockets
{
//从 Start(string ipString, int port) 函数开始调用
/// <summary>
/// Tcp Server
/// </summary>
public class TcpSocketServer : IDisposable
{
public Socket Socket
{
get;
private set;
}
public int Backlog
{
get; set;
}
public bool State
{
get;
private set;
}
/// <summary>
/// 本地服务器
/// </summary>
public EndPoint Local
{
get;
private set;
}
/// <summary>
/// 接收数据编码格式
/// </summary>
public Encoding ReceiveEncoding
{
get; set;
}
/// <summary>
/// 远程数据
/// </summary>
public event OnRemoteConnectHanlder RemoteConnect = null;
/// <summary>
/// 接收数据
/// </summary>
public event OnReceiveDataHanlder ReceiveData = null;
/// <summary>
/// 关闭远程
/// </summary>
public event OnRemoteCloseHanlder RemoteClose = null;//public event 委托 事件;
private Dictionary<string, SocketSession> _dicSessions = new Dictionary<string, SocketSession>();
/// <summary>
/// 获取连接对象
/// </summary>
public Dictionary<string, SocketSession> Sessions
{
get { return new Dictionary<string, SocketSession>(this._dicSessions); }
}
private System.Timers.Timer _SysTimer = null;
private BackgroundWorker _Worker = null;
private DateTime _RunTime = DateTime.Now;
/// <summary>
/// 绑定地址-
/// </summary>
/// <param name="local"></param>
private void Bind(EndPoint local)
{
try
{
this.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.Socket.Bind(local);
}
catch (Exception ex)
{
Loggers.Logger.Info(ex.Message);
return;
}
}
#region 开始绑定接收连接
/// <summary>
/// 开始绑定接收连接
/// </summary>
/// <param name="ipString"></param>
/// <param name="port"></param>
/// <returns></returns>
public bool Start(string ipString, int port)
{
IPAddress address = null;
IPAddress.TryParse(ipString, out address);
if (address == null)
{
Loggers.Logger.Info("IP地址格式不正确!" + ipString);
return false;
}
else
{
this.Bind(new IPEndPoint(address, port));//IP和端口的整合称为终结点endpoint
return this.Start();
}
}
/// <summary>
/// 开始绑定接收连接
/// </summary>
/// <param name="local"></param>
/// <returns></returns>
//public bool Start(EndPoint local)
//{
// this.Bind(local);
// return this.Start();
//}
/// <summary>
/// 开始绑定接收连接
/// </summary>
/// <returns></returns>
public bool Start()
{
if (this.Socket == null)
{
Loggers.Logger.Error("Socket对象不能为空!");
return false;
}
try
{
this.Backlog = 10;
this.Socket.Listen(this.Backlog);
Loggers.Logger.Info("启动服务成功!" + this.Socket.LocalEndPoint.ToString());
this.State = true;
ThreadPool.QueueUserWorkItem(new WaitCallback(Accept));
//
this._SysTimer = new System.Timers.Timer();
this._SysTimer.Interval = 30 * 60 * 1000;//30分钟检查一次
this._SysTimer.Elapsed += SysTimer_Elapsed;
this._SysTimer.Start();
return true;
}
catch (Exception ex)
{
Loggers.Logger.Error("启动服务异常:" + ex.ToString());
return false;
}
}
private void SysTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (this._Worker != null && this._Worker.IsBusy)
{
Loggers.Logger.Info("检查线程正在运行!");
TimeSpan timeSpan = DateTime.Now - this._RunTime;
if (timeSpan.TotalMinutes < 60)
return;
Loggers.Logger.Info("检查线程超:" + timeSpan.TotalMinutes + "运行中,需要停止重新启动...");
this.CheckClient();
}
}
private void CheckClient()
{
this._RunTime = DateTime.Now;
string[] keys = this._dicSessions.Keys.ToArray();
foreach (var item in keys)
{
try
{
int result = this._dicSessions[item].GetState();
Loggers.Logger.Info("返回结果:" + result);
}
catch (Exception ex)
{
Loggers.Logger.Error("获取状态异常:" + ex.ToString());
this._dicSessions.Remove(item);
}
}
}
public void Accept(object args)
{
while (this.State && this.Socket != null)
{
try
{
Socket client = this.Socket.Accept();
lock (this._dicSessions)
{
string key = client.RemoteEndPoint.ToString();//Guid.NewGuid().ToString();
if (this._dicSessions.ContainsKey(key) == false)
{
SocketSession session = new SocketSession(key, client);
session.ReceiveEncoding = this.ReceiveEncoding;
session.RemoteClose += Session_RemoteClose;
session.ReceiveData += Session_ReceiveData;
this._dicSessions.Add(key, session);
if (this.RemoteConnect != null)
this.RemoteConnect(key);
//开始接收数据
session.StartReceive();
}
}
}
catch (Exception ex)
{
Loggers.Logger.Error("接收客户端异常:" + ex.ToString());
}
}
}
private void Session_ReceiveData(IPEndPoint remote, byte[] buffer, int count)
{
if (this.ReceiveData != null)
this.ReceiveData(remote, buffer, count);
}
private void Session_RemoteClose(string key)
{
if (this._dicSessions.ContainsKey(key))
this._dicSessions.Remove(key);
if (this.RemoteClose != null)
this.RemoteClose(key);
}
#endregion
#region 向远程客户端发送信息
/// <summary>
/// 向远程客户端发送信息
/// </summary>
/// <param name="ipString"></param>
/// <param name="port"></param>
/// <param name="data"></param>
/// <returns></returns>
public int SendTo(string key, byte[] data)
{
if (this._dicSessions.ContainsKey(key) == false)
{
Loggers.Logger.Info("未能找到远程连接:" + key);
return -1;
}
var session = this._dicSessions[key];
return session.Send(data);
}
/// <summary>
/// 向远程客户端发送信息
/// </summary>
/// <param name="ipString"></param>
/// <param name="port"></param>
/// <param name="data"></param>
/// <returns></returns>
public int SendTo(SocketSession session, byte[] data)
{
return session.Send(data);
}
/// <summary>
/// 向远程客户端发送信息
/// </summary>
/// <param name="remote"></param>
/// <param name="data"></param>
/// <returns></returns>
public Dictionary<string, string> SendTo(byte[] data)
{
Dictionary<string, string> list = new Dictionary<string, string>();
if (this._dicSessions.Count <= 0)
{
Loggers.Logger.Info("未能找到远程连接!");
return list;
}
bool success = true;
string[] keys = this._dicSessions.Keys.ToArray();
foreach (var item in keys)
{
try
{
this._dicSessions[item].Send(data);
}
catch (Exception ex)
{
success = false;
Loggers.Logger.Error("发送数据异常:" + ex.ToString());
this._dicSessions.Remove(item);//移除发送失败的远程连接
}
}
//存在发送失败的远程
if (success == false)
{
if (this.RemoteClose != null)
this.RemoteClose(null);
}
return list;
}
/// <summary>
/// 向远程客户端发送信息
/// </summary>
/// <param name="remote"></param>
/// <param name="data"></param>
/// <returns></returns>
public Task<int> SendToAsync(string key, byte[] data)
{
return new Task<int>(() => this.SendTo(key, data));
}
/// <summary>
/// 向远程客户端发送信息
/// </summary>
/// <param name="remote"></param>
/// <param name="data"></param>
/// <returns></returns>
public Task<Dictionary<string, string>> SendToAsync(byte[] data)
{
return Task.Factory.StartNew<Dictionary<string, string>>(() => {
return this.SendTo(data);
});
}
#endregion
/// <summary>
/// 停止监听
/// </summary>
public void Close()
{
this.ClientClose();
if (this.Socket != null)
{
//由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。
//this.Socket.Disconnect(true);
this.Socket.Close(3);
this.Socket.Dispose();
this.Socket = null;
}
}
private void ClientClose()
{
string[] keys = this._dicSessions.Keys.ToArray();
foreach (var item in keys)
{
try
{
Loggers.Logger.Info("开始关闭:" + this._dicSessions[item].Client.RemoteEndPoint.ToString() + "...");
this._dicSessions[item].Close();
this._dicSessions.Remove(item);
Loggers.Logger.Info("关闭成功");
}
catch (Exception ex)
{
Loggers.Logger.Error("关闭异常:" + ex.ToString());
this._dicSessions.Remove(item);
}
}
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
this.Close();
}
}
}
5.接收客户端的消息-Receive (注意:开线程池 ,循环接收)
public bool StartReceive()
{
if (this.Client == null)
{
Loggers.Logger.Error("远程对象不能为空!");
return false;
}
try
{
this.State = true;
ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveThread));
Loggers.Logger.Info(this.Client.LocalEndPoint.ToString() + "启动接收数据成功!");
return true;
}
catch (Exception ex)
{
Loggers.Logger.Error("服务端启动异常:" + ex.ToString());
return false;
}
}
private void ReceiveThread(object state)
{
while (this.State && this.Client != null && this.Client.Connected)
{
try
{
byte[] mBuffer = new byte[10 * 1024];
int count = 0;
if (this.Client.Poll(-1, SelectMode.SelectRead))
{
count = this.Client.Receive(mBuffer);
if (count <= 0)
{
//连接已断开
this.Close();
return;
}
}
if (this.ReceiveEncoding == null)
this.ReceiveEncoding = System.Text.Encoding.UTF8;
//引发事件
if (this.ReceiveData != null)
this.ReceiveData((IPEndPoint)this.Client.RemoteEndPoint, mBuffer, count);
}
catch (Exception ex)
{
//this.State = false;
Loggers.Logger.Error("接收数据异常:" + this.Client.RemoteEndPoint + ex.ToString());
this.Close();
return;
}
}
}