C#网络编程系列(两)它Socket同步TCPserver
声明原文
笔者:竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处
文章系列文件夹
C#网络编程系列文章(一)之Socket实现异步TCPserver
C#网络编程系列文章(二)之Socket实现同步TCPserver
C#网络编程系列文章(三)之TcpListener实现异步TCPserver
C#网络编程系列文章(四)之TcpListener实现同步TCPserver
C#网络编程系列文章(五)之Socket实现异步UDPserver
C#网络编程系列文章(六)之Socket实现同步UDPserver
C#网络编程系列文章(七)之UdpClient实现异步UDPserver
C#网络编程系列文章(八)之UdpClient实现同步UDPserver
本文介绍
在上一篇博客中我说了,我将会介绍c#中使用Socket和TcpListener和UdpClient实现各种同步和异步的TCP和UDPserver,这些都是是我自己花了非常多天的时间来总结的。这样一来相信刚接触c#网络编程的朋友们不会像曾经的我一样到处出找资料,到处调试。本次我介绍的是使用Socket来实现的同步的TCPserver,同步的TCPserver和第一篇里面介绍的异步TCPserver的差别就是,在Socket调用Accept的时候是否会堵塞。
同步的TCPserver在接受到一个client的请求的时候通常是开启一个线程去处理和这个client的通信工作,这样的方式的不好的地方就是资源消耗大。可是假如使用线程池的话,事先分配一定数量的线程。性能还是能够。
可是我之所以给出非常多方法实现的server,主要目的就是想測试哪种情况性能比較不错,就眼下来看,异步的模式比較NICE,可是事实上另一种IOCP模式性能是最好的。。。
Socket同步TCPserver
服务端代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading; namespace NetFrame.Net.TCP.Sock.Synchronous
{
/// <summary>
/// 基于socket实现的同步TCPserver
/// </summary>
public class SocketTCPServer
{
#region Fields
/// <summary>
/// server程序同意的最大客户端连接数
/// </summary>
private int _maxClient; /// <summary>
/// 当前的连接的客户端数
/// </summary>
private int _clientCount; /// <summary>
/// server使用的异步socket
/// </summary>
private Socket _serverSock; /// <summary>
/// 客户端会话列表
/// </summary>
private List<SocketClientHandle> _clients; private bool disposed = false; #endregion #region Properties /// <summary>
/// server是否正在执行
/// </summary>
public bool IsRunning { get; private set; }
/// <summary>
/// 监听的IP地址
/// </summary>
public IPAddress Address { get; private set; }
/// <summary>
/// 监听的port
/// </summary>
public int Port { get; private set; }
/// <summary>
/// 通信使用的编码
/// </summary>
public Encoding Encoding { get; set; } #endregion #region 构造函数
/// <summary>
/// 同步Socket TCPserver
/// </summary>
/// <param name="listenPort">监听的port</param>
public SocketTCPServer(int listenPort)
: this(IPAddress.Any, listenPort, 1024)
{
} /// <summary>
/// 同步Socket TCPserver
/// </summary>
/// <param name="localEP">监听的终结点</param>
public SocketTCPServer(IPEndPoint localEP)
: this(localEP.Address, localEP.Port, 1024)
{
} /// <summary>
/// 同步Socket TCPserver
/// </summary>
/// <param name="localIPAddress">监听的IP地址</param>
/// <param name="listenPort">监听的port</param>
/// <param name="maxClient">最大客户端数量</param>
public SocketTCPServer(IPAddress localIPAddress, int listenPort, int maxClient)
{
this.Address = localIPAddress;
this.Port = listenPort;
this.Encoding = Encoding.Default; _maxClient = maxClient;
_clients = new List<SocketClientHandle>();
_serverSock = new Socket(localIPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
} #endregion #region Method
/// <summary>
/// 启动server
/// </summary>
public void Start()
{
if (!IsRunning)
{
IsRunning = true;
_serverSock.Bind(new IPEndPoint(this.Address, this.Port));
Thread thread = new Thread(StartListen);
thread.Start(); }
}
/// <summary>
/// 開始进行监听
/// </summary>
private void StartListen()
{
_serverSock.Listen(1024);
SocketClientHandle handle;
while (IsRunning)
{
if (_clientCount >= _maxClient)
{
//TODO 客户端过多异常
RaiseOtherException(null);
}
else
{
Socket clientSock = _serverSock.Accept();
_clientCount++;
//TODO 创建一个处理客户端的线程并启动
handle = new SocketClientHandle(clientSock);
_clients.Add(handle);
//使用线程池来操作
ThreadPool.QueueUserWorkItem(new WaitCallback(handle.RecevieData)); //Thread pthread;
//pthread = new Thread(new ThreadStart(client.RecevieData));
//pthread.Start();
//这里应该使用线程池来进行
}
} }
/// <summary>
/// 停止server
/// </summary>
public void Stop()
{
if (IsRunning)
{
IsRunning = false;
_serverSock.Close();
//TODO 关闭对全部客户端的连接 }
}
/// <summary>
/// 发送函数
/// </summary>
public void Send(string msg, SocketClientHandle client)
{
//TODO
} /// <summary>
/// 关闭一个与客户端之间的会话
/// </summary>
/// <param name="handle">须要关闭的客户端会话对象</param>
public void Close(SocketClientHandle handle)
{
if (handle != null)
{
_clients.Remove(handle);
handle.Dispose();
_clientCount--;
//TODO 触发关闭事件 }
}
/// <summary>
/// 关闭全部的客户端会话,与全部的客户端连接会断开
/// </summary>
public void CloseAllClient()
{
foreach (SocketClientHandle handle in _clients)
{
Close(handle);
}
_clientCount = 0;
_clients.Clear();
} #endregion #region 事件 /// <summary>
/// 与客户端的连接已建立事件
/// </summary>
public event EventHandler<SocketEventArgs> ClientConnected;
/// <summary>
/// 与客户端的连接已断开事件
/// </summary>
public event EventHandler<SocketEventArgs> ClientDisconnected; /// <summary>
/// 触发客户端连接事件
/// </summary>
/// <param name="state"></param>
private void RaiseClientConnected(SocketClientHandle handle)
{
if (ClientConnected != null)
{
ClientConnected(this, new SocketEventArgs(handle));
}
}
/// <summary>
/// 触发客户端连接断开事件
/// </summary>
/// <param name="client"></param>
private void RaiseClientDisconnected(Socket client)
{
if (ClientDisconnected != null)
{
ClientDisconnected(this, new SocketEventArgs("连接断开"));
}
} /// <summary>
/// 接收到数据事件
/// </summary>
public event EventHandler<SocketEventArgs> DataReceived; private void RaiseDataReceived(SocketClientHandle handle)
{
if (DataReceived != null)
{
DataReceived(this, new SocketEventArgs(handle));
}
} /// <summary>
/// 数据发送事件
/// </summary>
public event EventHandler<SocketEventArgs> CompletedSend; /// <summary>
/// 触发数据发送事件
/// </summary>
/// <param name="state"></param>
private void RaiseCompletedSend(SocketClientHandle handle)
{
if (CompletedSend != null)
{
CompletedSend(this, new SocketEventArgs(handle));
}
} /// <summary>
/// 网络错误事件
/// </summary>
public event EventHandler<SocketEventArgs> NetError;
/// <summary>
/// 触发网络错误事件
/// </summary>
/// <param name="state"></param>
private void RaiseNetError(SocketClientHandle handle)
{
if (NetError != null)
{
NetError(this, new SocketEventArgs(handle));
}
} /// <summary>
/// 异常事件
/// </summary>
public event EventHandler<SocketEventArgs> OtherException;
/// <summary>
/// 触发异常事件
/// </summary>
/// <param name="state"></param>
private void RaiseOtherException(SocketClientHandle handle, string descrip)
{
if (OtherException != null)
{
OtherException(this, new SocketEventArgs(descrip, handle));
}
}
private void RaiseOtherException(SocketClientHandle handle)
{
RaiseOtherException(handle, "");
} #endregion #region Close 未实现
#endregion #region 释放
/// <summary>
/// Performs application-defined tasks associated with freeing,
/// releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
} /// <summary>
/// Releases unmanaged and - optionally - managed resources
/// </summary>
/// <param name="disposing"><c>true</c> to release
/// both managed and unmanaged resources; <c>false</c>
/// to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
try
{
Stop();
if (_serverSock != null)
{
_serverSock = null;
}
}
catch (SocketException)
{
//TODO 异常
}
}
disposed = true;
}
}
#endregion
}
}
对client操作封装的Handle类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets; namespace NetFrame.Net.TCP.Sock.Synchronous
{
/// <summary>
/// Socket server用于处理客户端连接封装的客户端处理类
/// </summary>
public class SocketClientHandle:IDisposable
{
/// <summary>
/// 与客户端相关联的socket
/// </summary>
private Socket _client; /// <summary>
/// 标识是否与客户端相连接
/// </summary>
private bool _is_connect;
public bool IsConnect
{
get { return _is_connect; }
set { _is_connect = value; }
} /// <summary>
/// 数据接受缓冲区
/// </summary>
private byte[] _recvBuffer; public SocketClientHandle(Socket client)
{
this._client = client;
_is_connect = true;
_recvBuffer = new byte[1024 * 1024 * 2];
} #region Method
/// <summary>
/// 接受来自客户端发来的数据
/// </summary>
public void RecevieData(Object state)
{
int len = -1;
while (_is_connect)
{
try
{
len = _client.Receive(_recvBuffer);
}
catch (Exception)
{
//TODO
}
}
} /// <summary>
/// 向客户端发送数据
/// </summary>
public void SendData(string msg)
{
byte[] data = Encoding.Default.GetBytes(msg);
try
{
//有一种比較好的写法
_client.Send(data);
}
catch (Exception)
{
//TODO 处理异常
}
} #endregion #region 事件 //TODO 消息发送事件
//TODO 数据收到事件
//TODO 异常处理事件 #endregion #region 释放
/// <summary>
/// Performs application-defined tasks associated with freeing,
/// releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
_is_connect = false;
if (_client != null)
{
_client.Close();
_client = null;
}
GC.SuppressFinalize(this);
} #endregion
}
}
Socket同步TCPserver的时间參数类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace NetFrame.Net.TCP.Sock.Synchronous
{
/// <summary>
/// 同步Socket TCPserver事件类
/// </summary>
public class SocketEventArgs : EventArgs
{
/// <summary>
/// 提示信息
/// </summary>
public string _msg; /// <summary>
/// client状态封装类
/// </summary>
public SocketClientHandle _handle; /// <summary>
/// 是否已经处理过了
/// </summary>
public bool IsHandled { get; set; } public SocketEventArgs(string msg)
{
this._msg = msg;
IsHandled = false;
}
public SocketEventArgs(SocketClientHandle handle)
{
this._handle = handle;
IsHandled = false;
}
public SocketEventArgs(string msg, SocketClientHandle handle)
{
this._msg = msg;
this._handle = handle;
IsHandled = false;
}
}
}
本文作者:小竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处
版权声明:本文博客原创文章,博客,未经同意,不得转载。
C#网络编程系列(两)它Socket同步TCPserver的更多相关文章
- C#网络编程系列文章(一)之Socket实现异步TCPserver
原创性声明 本文作者:小竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处 文章系列文件夹 C#网络编程 ...
- C#网络编程系列文章(五)之Socket实现异步UDPserver
原创性声明 本文作者:小竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处 文章系列文件夹 C#网络编程 ...
- Socket网络编程系列教程序
C语言的用途相当多,可以用在数据结构.数据库.网络.嵌入式等方面,历经40多年不衰,真是厉害!最近一直想从某一应用方面写一个系列教程,好好地把某一方面讲深讲透. 正好博主对网络方面的编 ...
- 完毕port(CompletionPort)具体解释 - 手把手教你玩转网络编程系列之三
手把手叫你玩转网络编程系列之三 完毕port(Completion Port)具体解释 ...
- TCP/IP网络编程系列之四(初级)
TCP/IP网络编程系列之四-基于TCP的服务端/客户端 理解TCP和UDP 根据数据传输方式的不同,基于网络协议的套接字一般分为TCP和UDP套接字.因为TCP套接字是面向连接的,因此又称为基于流的 ...
- 猫哥网络编程系列:HTTP PEM 万能调试法
注:本文内容较长且细节较多,建议先收藏再阅读,原文将在 Github 上维护与更新. 在 HTTP 接口开发与调试过程中,我们经常遇到以下类似的问题: 为什么本地环境接口可以调用成功,但放到手机上就跑 ...
- 猫哥网络编程系列:详解 BAT 面试题
从产品上线前的接口开发和调试,到上线后的 bug 定位.性能优化,网络编程知识贯穿着一个互联网产品的整个生命周期.不论你是前后端的开发岗位,还是 SQA.运维等其他技术岗位,掌握网络编程知识均是岗位的 ...
- Android网络编程系列 一 TCP/IP协议族
在学习和使用Android网路编程时,我们接触的仅仅是上层协议和接口如Apache的httpclient或者Android自带的httpURlconnection等等.对于这些接口的底层实现我们也有必 ...
- TCP/IP网络编程系列之三(初级)
TCP/IP网络编程系列之三-地址族与数据序列 分配给套接字的IP地址和端口 IP是Internet Protocol (网络协议)的简写,是为首发网络数据而分配给计算机的值.端口号并非赋予计算机值, ...
随机推荐
- java注解(转)
java中元注解有四个: @Retention @Target @Document @Inherited: @Retention:注解的保留位置 @Retention(RetentionPolicy ...
- POJ 3979 分数减法【数学问题的探讨】
将a/b和c/d简化一下就可以了 分数加减法 Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 12588 Accepted ...
- Windows下一个SlikSVN使用
我相信所有的应SVN不熟悉.使用过.可是并非人人都自己配置过SVNserver.以下就是我配置SVNserver的步骤.以及在配置过程中碰见的一些问题,在此记录,希望对你有所帮助. 安装 双击执行&q ...
- Linux 编程学习笔记----文档管理系统
本文从网络上完成的第 Linux在文件系统管理. 1.VFS文件系统概述 linux採用VFS来管理文件系统,并且linux设计的原则之中的一个就是everything is file.因此文件管理系 ...
- IBM Java架构师的技能
一天,群里飘过一个IBM招聘信息.我看过之后,也只是如此而已. 大家好!我是XXX,IBM招聘java架构师,如今还有38个名额 学历大专以上即可,英语能面试交流的.项目有非常多到时候依据您面试会详谈 ...
- 浏览器HTTP缓存原理分析(转)
章节目录 浏览器缓存原理 文字版描述 一图以蔽之 缓存相关首部字段 request缓存相关首部字段 response缓存相关首部字段 实体首部缓存相关字段 缓存配置的一些注意事项 以前项目中遇到了很多 ...
- erlang R17新socket选项{active,N}
erlang R17带来了新的socket选项{active,N} .与{active,once}连同应用层提供的流量控制.为什么会这样选择,{active,once}不能够有效地抑制了很多socke ...
- 第19章 解释器模式(Interpreter Pattern)
原文 第19章 解释器模式(Interpreter Pattern) 解释器模式 导读:解释器模式,平常用的比较的少,所以在写这个模式之前在博客园搜索了一番,看完之后那叫一个头大.篇幅很长,我鼓足了劲 ...
- ASP.NET——RequiredFieldValidator控制和ValidationSummary控制
我们的登录页面,忘记承担损失password然后username,该页面将永远是一个小提醒. 那么我们在网也制作的时候怎样实现这一功能呢?这就用到了RequiredFieldValidator控件和V ...
- JavaScript语言基础知识点图示
原文:JavaScript语言基础知识点图示 一位牛人归纳的JavaScript 语言基础知识点图示. 1.JavaScript 数据类型 2.JavaScript 变量 3.Javascript 运 ...