声明原文

笔者:竹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的更多相关文章

  1. C#网络编程系列文章(一)之Socket实现异步TCPserver

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

  2. C#网络编程系列文章(五)之Socket实现异步UDPserver

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

  3. Socket网络编程系列教程序

    C语言的用途相当多,可以用在数据结构.数据库.网络.嵌入式等方面,历经40多年不衰,真是厉害!最近一直想从某一应用方面写一个系列教程,好好地把某一方面讲深讲透.         正好博主对网络方面的编 ...

  4. 完毕port(CompletionPort)具体解释 - 手把手教你玩转网络编程系列之三

       手把手叫你玩转网络编程系列之三    完毕port(Completion Port)具体解释                                                    ...

  5. TCP/IP网络编程系列之四(初级)

    TCP/IP网络编程系列之四-基于TCP的服务端/客户端 理解TCP和UDP 根据数据传输方式的不同,基于网络协议的套接字一般分为TCP和UDP套接字.因为TCP套接字是面向连接的,因此又称为基于流的 ...

  6. 猫哥网络编程系列:HTTP PEM 万能调试法

    注:本文内容较长且细节较多,建议先收藏再阅读,原文将在 Github 上维护与更新. 在 HTTP 接口开发与调试过程中,我们经常遇到以下类似的问题: 为什么本地环境接口可以调用成功,但放到手机上就跑 ...

  7. 猫哥网络编程系列:详解 BAT 面试题

    从产品上线前的接口开发和调试,到上线后的 bug 定位.性能优化,网络编程知识贯穿着一个互联网产品的整个生命周期.不论你是前后端的开发岗位,还是 SQA.运维等其他技术岗位,掌握网络编程知识均是岗位的 ...

  8. Android网络编程系列 一 TCP/IP协议族

    在学习和使用Android网路编程时,我们接触的仅仅是上层协议和接口如Apache的httpclient或者Android自带的httpURlconnection等等.对于这些接口的底层实现我们也有必 ...

  9. TCP/IP网络编程系列之三(初级)

    TCP/IP网络编程系列之三-地址族与数据序列 分配给套接字的IP地址和端口 IP是Internet Protocol (网络协议)的简写,是为首发网络数据而分配给计算机的值.端口号并非赋予计算机值, ...

随机推荐

  1. java注解(转)

    java中元注解有四个: @Retention @Target @Document @Inherited:  @Retention:注解的保留位置 @Retention(RetentionPolicy ...

  2. POJ 3979 分数减法【数学问题的探讨】

    将a/b和c/d简化一下就可以了 分数加减法 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12588   Accepted ...

  3. Windows下一个SlikSVN使用

    我相信所有的应SVN不熟悉.使用过.可是并非人人都自己配置过SVNserver.以下就是我配置SVNserver的步骤.以及在配置过程中碰见的一些问题,在此记录,希望对你有所帮助. 安装 双击执行&q ...

  4. Linux 编程学习笔记----文档管理系统

    本文从网络上完成的第 Linux在文件系统管理. 1.VFS文件系统概述 linux採用VFS来管理文件系统,并且linux设计的原则之中的一个就是everything is file.因此文件管理系 ...

  5. IBM Java架构师的技能

    一天,群里飘过一个IBM招聘信息.我看过之后,也只是如此而已. 大家好!我是XXX,IBM招聘java架构师,如今还有38个名额 学历大专以上即可,英语能面试交流的.项目有非常多到时候依据您面试会详谈 ...

  6. 浏览器HTTP缓存原理分析(转)

    章节目录 浏览器缓存原理 文字版描述 一图以蔽之 缓存相关首部字段 request缓存相关首部字段 response缓存相关首部字段 实体首部缓存相关字段 缓存配置的一些注意事项 以前项目中遇到了很多 ...

  7. erlang R17新socket选项{active,N}

    erlang R17带来了新的socket选项{active,N} .与{active,once}连同应用层提供的流量控制.为什么会这样选择,{active,once}不能够有效地抑制了很多socke ...

  8. 第19章 解释器模式(Interpreter Pattern)

    原文 第19章 解释器模式(Interpreter Pattern) 解释器模式 导读:解释器模式,平常用的比较的少,所以在写这个模式之前在博客园搜索了一番,看完之后那叫一个头大.篇幅很长,我鼓足了劲 ...

  9. ASP.NET——RequiredFieldValidator控制和ValidationSummary控制

    我们的登录页面,忘记承担损失password然后username,该页面将永远是一个小提醒. 那么我们在网也制作的时候怎样实现这一功能呢?这就用到了RequiredFieldValidator控件和V ...

  10. JavaScript语言基础知识点图示

    原文:JavaScript语言基础知识点图示 一位牛人归纳的JavaScript 语言基础知识点图示. 1.JavaScript 数据类型 2.JavaScript 变量 3.Javascript 运 ...