自定义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;
}
05-08 15:50