声明原文

笔者:竹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. Team Foundation Server 2015使用教程--团队项目创建

  2. HTML5学习笔记简明版(10):过时的元素和属性

    被遗弃的元素(Element) 这个小节里列出的元素在HTML5里将不再使用,现有文档升级到 HTML5的话能够使用一些替代方案.比如parser section 能够处理isindex 元素的功能. ...

  3. 工厂模式IDAL具体解释

    IDAL 一. IDAL主要功能: 1.这全然是"工厂模式"的一部分实现而已 2.这是一组接口类,当中包含了每一个要公开的数据訪问方法.为每一个数据库产品单独编写的DAL(数据訪问 ...

  4. Initialising Memories

    The file_name and memory_nameare memory_start and memory_finish are optional, it missed out they def ...

  5. Dp_F Pku1157

    <span style="color:#000099;">/* F - 简单dp Time Limit:1000MS Memory Limit:10000KB 64bi ...

  6. [LeetCode] 032. Longest Valid Parentheses (Hard) (C++)

    指数:[LeetCode] Leetcode 指标解释 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 032. Lon ...

  7. Mencached使用

    Mencached使用小记 该文章简单记录一下在Windows平台下安装与配置Memcached的方法,Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载. ...

  8. Java 实现装饰(Decorator)模式

    在Java在.io反映非常多类包下是典型的装饰格局,例如: new BufferedOutputStream(OutputStream out) new BufferedInputStream(Inp ...

  9. 从头开始学JavaScript (三)——数据类型

    原文:从头开始学JavaScript (三)--数据类型 一.分类 基本数据类型:undefined.null.string.Boolean.number 复杂数据类型:object object的属 ...

  10. 左右linuxserver自己主动重启过程监控和简单的解决方案

    转载请注明出处:帘卷西风的专栏(http://blog.csdn.net/ljxfblog) 本周開始,新手游进行删档封測阶段,前两天表现还好,今天更新后出现几次宕机行为.比較影响玩家的測试和体验,我 ...