声明原文

笔者:竹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. .NET单元测试艺术(2) - 第一个单元测试

    List 2.1 使用[SetUp]和[TearDown]特性 using System; using System.Collections.Generic; using System.Linq; u ...

  2. sql语句like的使用方法

    在SQL结构化查询语言中,LIKE语句有着至关关键的数据. LIKE语句的语法格式是:select * from 表名 where 字段名 like 相应值(子串),它主要是针对字符型字段的,它的作用 ...

  3. springMvc的注解注入方式

    springMvc的注解注入方式 最近在看springMvc的源码,看到了该框架的注入注解的部分觉的有点吃力,可能还是对注解的方面的知识还认识的不够深刻,所以特意去学习注解方面的知识.由于本人也是抱着 ...

  4. MTK6572横屏的调试过程

    电视剧集:系统MTK缺省的系统源代码,Phone模式.底部有三个虚拟按键.需求为,设置成默认横屏,设定一个合理的虚拟按键方案. ------------------------------------ ...

  5. ZOJ3605-Find the Marble(可能性DP)

    Find the Marble Time Limit: 2 Seconds      Memory Limit: 65536 KB Alice and Bob are playing a game. ...

  6. 【甘道夫】官方网站MapReduce代码注释具体实例

    引言 1.本文不描写叙述MapReduce入门知识,这类知识网上非常多.请自行查阅 2.本文的实例代码来自官网 http://hadoop.apache.org/docs/current/hadoop ...

  7. unity3d 学习笔记_____Native2d 刚体、冲击、联合使用

    Mass Mass of the rigidbody. Linear Drag Drag coefficient affecting positional movement. Angular Drag ...

  8. kettle于javascript步骤错误处理

    javascript步骤错误处理 假设你熟悉kettle误差特性转换.你可能想知道javascript步骤如何使用.骤用户界面机制是同样的,在javascript步骤右击,选择"定义错误处理 ...

  9. (一)AngularJS获取贴纸Hello World

    一旦项目使用JQuery原创javascript,最近参加了一个项目,需要使用AngularJS.RequireJS比较框架,如汰渍. 这里写一些博客,记录自己的学习过程,虽然冠以原来的名字,资料,加 ...

  10. MSMQ-发送消息到远程专用队列 实例

    目录 一:MSMQ的一些理论上的知识 二:队列类型(Queue Type) 三:安装消息队列 四:在C#中Messagequeue class 五:MSMQ-发送消息到远程专用队列 六:例子   一. ...