SocketTcpServer
自定义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的更多相关文章
- C#网络编程系列(两)它Socket同步TCPserver
声明原文 笔者:竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处 文章系列文件夹 C#网络编程系列文 ...
- Unity C# 自定义TCP传输协议以及封包拆包、解决粘包问题
本文只是初步实现了一个简单的TCP自定协议,更为复杂的协议可以根据这种方式去扩展. TCP协议,通俗一点的讲,它是一种基于socket传输的由发送方和接收方事先协商好的一种消息包组成结构,主要由消息头 ...
- QT创建TCP Socket通信
最近在学习QT,了解到QT可以进行SOCKET网络通信,进行学习,并建立一个简单的聊天DEMO.为了测试是否能与VS2012下的程序进行通信,在VS2012下建立一个客户端程序,进行通信测试,发现可以 ...
- Android之socket服务端
import java.io.DataInputStream; import java.io.IOException; import java.io.PrintWriter; import java. ...
- 8.9.网络编程_Socket 远程调用机制
1.网络编程 1.1.网络编程概述: 通过通信线路(有线或无线)可以把不同地理位置且相互独立的计算机连同其外部设备连接起来,组成计算机网络.在操作系统.网络管理软件及网络 通信协议的管理和协调下,可以 ...
- 1、Socket通信
[TCP] 服务器端:无目标插座升级为有目标插座后,就可以通过有目标的插座收发数据 客户端: 实战:此案例有利于理解Socket的工作流程. 缺点:服务器只能接收1个客户端的连接,因为只写了一个Acc ...
随机推荐
- nginx 负载均衡策略
nginx 负载均衡策略 1. 轮询轮询方式是nginx负载均衡的默认策略,根据每个server的权重值来轮流发送请求,例如:upstream backend {server backend1.e ...
- 课时9—popup
内容比较多的时候可以全屏显示,用第一种实现方式,如图1 图1 内容较少的话可以使用第二种实现方式如图2:图2 具体的实现代码如下: .header,.footer,.wrap-page{ positi ...
- Windows 10:解决开机显示C:\WINDOWS\system32\config\systemprofile\Desktop不可用的方法
开机显示C:\WINDOWS\system32\config\systemprofile\Desktop不可用应该是不少网友都遇到过. 近日在使用Windows 10 Build 9926中,也出 ...
- TestLink
TestLink的主要功能包括: 测试需求管理 测试用例管理 测试用例对测试需求的覆盖管理 测试计划的制定 测试用例的执行 大量测试数据的度量和统计功能 TestLink的主要特色包括: 支持多产品或 ...
- 饮水思源——python中常用基础类源码解析
1.bool类 2.int类 3.long类 4.float类 5.str类 6.list类 7.tuple类 8.dict类 9.collections类 Counter类:为hashable对象计 ...
- Ubuntu 安装桌面且远程连接
前言: 一般服务器是不装桌面的,因为会牺牲很多性能,这里就选择很小桌面,牺牲一定性能 这里就采用x2go, 这里是在ubuntu server 14.04 安装成功,其实它是可用于linux所有 ...
- python 多线程和多核
昨天在一个群里面遇到的,使用py做计算,只有1个CPU在跑任务,其它的怠工. 在py3以后,提供了:concurrent.futures mark 如下; 官方文档: 16.6. multiproce ...
- Android开发--ScrollView的应用
1.简介 当内容无法全部显示时,需要采取滚动的方式获取其与内容.其中,ScrollView为垂直滚动控件,HorizontalScrollView为水平滚动控件. 2.构建
- 使用Markdown+Pandoc+LaTex+Beamer制作幻灯片
概述 为什么使用markdown? mardown是一种轻量级的标记语言,语法简单,可读性好,并且容易转化成其他格式的文档, 在技术文档撰写中得到越来越广泛的应用.相信大家对markdown都有一定了 ...
- .htaccess根据IP地址限制访问
屏蔽IP地址 屏蔽IP地址有时是非常必要的,比如对于一个外贸公司网站,来自国内的访问是不会带来任何经济效益的,而且还占用服务器资源,造成访问延迟等问题. 如果要屏蔽某一特定IP可以使用: order ...