自定义SocketTcpServer,虽然现在有很多这样的组件,但是有时候还是需要把它集成在你的框架或者产品中,不需要特别强大的功能,根据需求定制。最基本的一个问题是判断数据包的结束,没有像supersocket那样默认以换行作为一个命令的结束,如果需要可以改善。

     public interface ISocketTcpServer
{
void Listen();
void Stop();
void SendData(byte[] data, Socket client); event ReceiveDataHandler ReceivedDataEvent;
event OnlineChangeHandler OnlineChangeEvent;
event ErrorHandler ErrorEvent;
} public delegate void ReceiveDataHandler(SocketState state); public delegate void OnlineChangeHandler(int onlines, EndPoint client); public delegate void ErrorHandler(string error, EndPoint client); public class SocketTcpServer : ISocketTcpServer
{
private readonly Socket _tcpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public readonly EndPoint LocalPoint;
public readonly List<SocketState> ClientList = new List<SocketState>();
public bool IsListening; public SocketTcpServer(IPEndPoint localPoint)
{
LocalPoint = localPoint;
} public void Listen()
{
_tcpSocket.Bind(LocalPoint);
_tcpSocket.Listen();
_tcpSocket.BeginAccept(AcceptClientCallBack, _tcpSocket);
IsListening = true;
} public void Stop()
{
IsListening = false;
foreach (var state in ClientList)
{
state.ClientSocket.Close();
}
ClientList.Clear();
_tcpSocket.Close();
OnlineChangeEvent?.Invoke(ClientList.Count, new IPEndPoint(IPAddress.Any, ));
} private void AcceptClientCallBack(IAsyncResult ar)
{
var server = ar.AsyncState as Socket;
if (IsListening && server != null)
{
try
{
var client = server.EndAccept(ar);
var clientState = new SocketState()
{
ClientSocket = client,
RemotePoint = client.RemoteEndPoint,
};
var tem = ClientList.FirstOrDefault(x => x.RemotePoint.Equals(clientState.RemotePoint));
if (tem != null)
{
tem.ClientSocket.Close();
ClientList.Remove(tem);
}
ClientList.Add(clientState);
BeginReveive(client);
OnlineChangeEvent?.Invoke(ClientList.Count, client.RemoteEndPoint);
}
catch (Exception error)
{
ErrorEvent?.Invoke(error.Message, null);
}
finally
{
server.BeginAccept(AcceptClientCallBack, server);
}
}
} private void BeginReveive(Socket client)
{
if (client.Connected)
{
var state = new SocketState()
{
ClientSocket = client,
RemotePoint = client.RemoteEndPoint,
};
client.BeginReceiveFrom(
state.Buffer,
,
state.Buffer.Length,
SocketFlags.None,
ref state.RemotePoint,
ReceiveCallback,
state);
}
} private void ReceiveCallback(IAsyncResult ar)
{
var state = ar.AsyncState as SocketState;
try
{
if (state != null && state.ClientSocket.Connected)
{
state.DataLen = state.ClientSocket.EndReceiveFrom(ar, ref state.RemotePoint);
if (state.DataLen == )
{
state.ClientSocket.Close();
var tem = ClientList.FirstOrDefault(x => x.RemotePoint.Equals(state.RemotePoint));
ClientList.Remove(tem);
OnlineChangeEvent?.Invoke(ClientList.Count, state.RemotePoint);
}
else
{
byte[] receivedData = new byte[state.DataLen];
Array.Copy(state.Buffer, , receivedData, , state.DataLen);
state.Buffer = receivedData;
ReceivedDataEvent?.Invoke(state);
}
}
}
catch (Exception error)
{
ErrorEvent?.Invoke(error.Message, state.RemotePoint);
state.ClientSocket.Close();
var tem = ClientList.FirstOrDefault(x => x.RemotePoint.Equals(state.RemotePoint));
ClientList.Remove(tem);
OnlineChangeEvent?.Invoke(ClientList.Count, state.RemotePoint);
}
finally
{
if (state != null) BeginReveive(state.ClientSocket);
}
} public void SendData(byte[] data, Socket client)
{
if (client.Connected)
{
var state = new SocketState()
{
ClientSocket = client,
RemotePoint = client.RemoteEndPoint,
Buffer = data,
DataLen = data.Length,
};
client.BeginSendTo(data, , data.Length, SocketFlags.None, state.RemotePoint, SendCallback, state);
}
} private void SendCallback(IAsyncResult ar)
{
var state = ar.AsyncState as SocketState;
try
{
if (state != null && state.ClientSocket.Connected)
{
state.ClientSocket.EndSendTo(ar);
}
}
catch (Exception error)
{
ErrorEvent?.Invoke(error.Message, state.RemotePoint);
}
} public event ReceiveDataHandler ReceivedDataEvent; public event OnlineChangeHandler OnlineChangeEvent; public event ErrorHandler ErrorEvent;
} public class SocketState
{
public byte[] Buffer = new byte[*];
public Socket ClientSocket;
public int DataLen;
public EndPoint RemotePoint;
}

SocketTcpServer的更多相关文章

  1. C#网络编程系列(两)它Socket同步TCPserver

    声明原文 笔者:竹zz  本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处 文章系列文件夹 C#网络编程系列文 ...

  2. Unity C# 自定义TCP传输协议以及封包拆包、解决粘包问题

    本文只是初步实现了一个简单的TCP自定协议,更为复杂的协议可以根据这种方式去扩展. TCP协议,通俗一点的讲,它是一种基于socket传输的由发送方和接收方事先协商好的一种消息包组成结构,主要由消息头 ...

  3. QT创建TCP Socket通信

    最近在学习QT,了解到QT可以进行SOCKET网络通信,进行学习,并建立一个简单的聊天DEMO.为了测试是否能与VS2012下的程序进行通信,在VS2012下建立一个客户端程序,进行通信测试,发现可以 ...

  4. Android之socket服务端

    import java.io.DataInputStream; import java.io.IOException; import java.io.PrintWriter; import java. ...

  5. 8.9.网络编程_Socket 远程调用机制

    1.网络编程 1.1.网络编程概述: 通过通信线路(有线或无线)可以把不同地理位置且相互独立的计算机连同其外部设备连接起来,组成计算机网络.在操作系统.网络管理软件及网络 通信协议的管理和协调下,可以 ...

  6. 1、Socket通信

    [TCP] 服务器端:无目标插座升级为有目标插座后,就可以通过有目标的插座收发数据 客户端: 实战:此案例有利于理解Socket的工作流程. 缺点:服务器只能接收1个客户端的连接,因为只写了一个Acc ...

随机推荐

  1. laravel 控制器方法里存get值 和 blade 模板获得闪存值的方法

    //get 方式把id传到路由 <a href="/admin/reply/add/{{$comment -> id}}" class="btn btn-bl ...

  2. python核心编程第六章练习6-15

    转换.(a)给出两个可识别格式的日期,比如MM/DD/YY或者DD/MM/YY格式.计算出两个日期之间的天数.(b)给出一个人的生日,计算此人从出生到现在的天数,包括所有的闰月.(c)还是上面的例子, ...

  3. js 原生对象排序

    //对象属性排序 function compare(propertyName) { return function (object1, object2) { var value1 = object1[ ...

  4. 在python中使用matplotlib中的Matplotlib-Animation “No MovieWriters Available”

    在使用官方的示例代码中,一部分使用了ffmpeg 在执行时会报如题一样的错误 解决: 下载windows的版本,解压,然后将bin目录加入系统环境变量的路径中 如:D:\Program Files\f ...

  5. hdu 1532(最大流)

    Drainage Ditches Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  6. ios 打包

    /usr/bin/xcodebuild -scheme Moon -sdk iphoneos -workspace Moon.xcworkspace -configuration Release cl ...

  7. NodeJS利用mongoose模糊查询MongoDB

    在Node.js中,直接硬编码可以 Posts.where('title',/答案/); 但是 通过 字符串构造 不行 var qs = '/'+req.query.search+'/'; Posts ...

  8. BZOJ1880: [Sdoi2009]Elaxia的路线

    题意:求最短路最长公共距离. 考虑每一条边,如果满足dis(s1,u)+len+dis(v,t1)==dis(s1,t1) && dis(s2,u)+len+dis(v,t2)==di ...

  9. Spring之JDBC模板jdbcTemplate

    要使用Jdbctemplate 对象来完成jdbc 操作.通常情况下,有三种种方式得到JdbcTemplate 对象.           第一种方式:我们可以在自己定义的DAO 实现类中注入一个Da ...

  10. eventUtil

    var eventUtil = { // 添加句柄 addHandler: function(element, type, handler) { if(element.addEventListener ...