声明原文

笔者:竹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该队列中的数组,圆阵队列,链队列

    /** * 文件名:QueueText.java * 时间:2014年10月22下午9:05:13 * 笔者:维亚康姆维修 */ package chapter3; /** * 类名:ArrayQue ...

  2. (插播)unity的 异常捕捉和 ios Android 崩溃信息的捕捉。

    近期 做些准备性得工作和有意思的事情.所以近期做了一个适合ios和android 错误信息捕捉的unity插件. 两个功能,app崩溃也就是闪退 是开发人员 非常头疼的一件事,还有就是一些莫名得错误 ...

  3. 泛泰A900 刷4.4中国民营TWRP2.7.1.1版本 支持自己主动识别移动版本号(世界上第一)

    因本人手上的A900S已砖, 所以临时弄不了ROM了. 先上传之前已经弄好的刷4.4专用的新版TWRP recovery 2.7.1.1  这个版本号是我自己定义的,为差别之前公布的2.7.0.0版( ...

  4. ubuntu经常使用的命令摘要

    1.df命令 # df -ha 显示所有文件和分区的使用 # df -h /dev/sda1 显示sda1磁盘使用率 # df -T 显示文件系统名称属于每个分区.区的格式类型(比方ext3) 注:h ...

  5. UVA11992 - Fast Matrix Operations(段树部分的变化)

    UVA11992 - Fast Matrix Operations(线段树区间改动) 题目链接 题目大意:给你个r*c的矩阵,初始化为0. 然后给你三种操作: 1 x1, y1, x2, y2, v ...

  6. ACM-凸多边形的计算几何——hrbust1429

    凸多边形 称号:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1429 Descri ...

  7. hdu 4915 Parenthese sequence 多校第五场

    推断一个序列是否是有效是简单的. 可是推断序列是不是有多个解会出问题. 那么从i=0 ~l 假设读到问号,推断该问号成为(能否有效,该问号为)是否有效. 假设都有效,则必有多个解. 假设都无效,则无解 ...

  8. Chromium Graphics: GPUclient的原理和实现分析之间的同步机制-Part I

    摘要:Chromium于GPU多个流程架构的同意GPUclient这将是这次访问的同时GPU维修,和GPUclient这之间可能存在数据依赖性.因此必须提供一个同步机制,以确保GPU订购业务.本文讨论 ...

  9. I Love This Game 2115(结构体)

    Problem Description Do you like playing basketball ? If you are , you may know the NBA Skills Challe ...

  10. A + B Again 2057 有符号的64进位的运算

    Problem Description There must be many A + B problems in our HDOJ , now a new one is coming.Give you ...