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 ...
随机推荐
- [SoapUI] 同一个Resource不同参数时,在两个step里默认打开总是同一个Resource
当SoapUI里Projects 有两个相同的Resource,只是参数不同时,使用两个Resource创建的step默认打开的总是同一个Resource.我们应当修改method名字为不同,这是So ...
- 转!!log4j基础
log4j组件介绍 Log4j主要有三个组件: Logger:负责供客户端代码调用,执行debug(Object msg).info(Object msg).warn(Object msg).erro ...
- 课时8—弹窗modal
首先弹窗的实现效果如下: 主要实现的代码如下: CSS: .header,.footer,.wrap-page{ position:absolute; left:; right:; backgroun ...
- Echarts的基本用法
首先需要到导入echatrs.js文件 <script src="dist/echarts.js"></script> 路径配置 require.confi ...
- 6/17 Sprint3
首页改进:
- 运用js解决java selenium元素定位问题
一.解决定位并操作uneditable元素 尝试了通过id,xpath等等定位元素后点击都提示Element is not clickable at point 再看了下可以click的元素发现上面有 ...
- Makefile三个有用变量$@,$^,$<
$@:目标文件 $^:所有的依赖文件 $<:第一个依赖文件 使用上面三个变量就可以简化我们的Makefile文件: #简化后的Makefile main : main.o log.o test_ ...
- 转: JSTL SQL标签库 使用
SQL标签库 JSTL提供了与数据库相关操作的标签,可以直接从页面上实现数据库操作的功能,在开发小型网站是可以很方便的实现数据的读取和操作.本章将详细介绍这些标签的功能和使用方法. SQL标签库从功能 ...
- 监听器初始化Job、JobTracker相应TaskTracker心跳、调度器分配task源码级分析
JobTracker和TaskTracker分别启动之后(JobTracker启动流程源码级分析,TaskTracker启动过程源码级分析),taskTracker会通过心跳与JobTracker通信 ...
- wdcp 打开网页显示 Apache 2 Test Page powered by CentOS
是因为更新过系统,安装并更新了系统自带的apache 执行这个命令即可 #ln -sf /www/wdlinux/init.d/httpd /etc/rc.d/init.d/httpd#reboot