.NET Socket服务编程之-高效连接接入编
在.NET上编写网络服务深入都有2,3年了,而这些时间时如何在.NET里实现网络服务积累了一些经验.在接下来的时间里会把这方面的经验通过博客的方式分享出来.而这一章主要是讲解在如果提高服务连接接入的效率,从而让服务连接接入的并发量有高吞吐的性能.
其实.NET提供了一个非常强大的网络模型给我们使用,而我们只需要把这个模型用好那基于是不存在多大问题.不过由于很多开发人员对这方面并没有了解和深入所以感觉.Net编写一个高效能的服务比较因难.下面通过不同的示例来描述问题的所在从而避免这些问题的出现,让编写的服务更高效.
示例1
try {
listener.Bind(localEndPoint);
listener.Listen(10); // Start listening for connections.
while (true) {
Console.WriteLine("Waiting for a connection...");
// Program is suspended while waiting for an incoming connection.
Socket handler = listener.Accept();
data = null; // An incoming connection needs to be processed.
while (true) {
bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes,0,bytesRec);
if (data.IndexOf("<EOF>") > -1) {
break;
}
} // Show the data on the console.
Console.WriteLine( "Text received : {0}", data); // Echo the data back to the client.
byte[] msg = Encoding.ASCII.GetBytes(data); handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
} } catch (Exception e) {
Console.WriteLine(e.ToString());
}
这是从MSDN得到的一个服务端示例的代码地址来源http://msdn.microsoft.com/en-us/library/6y0e13d3(v=vs.110).aspx以上代码说实话真没多大的参考意义,不过作为一个演示如何构建一个服务监听那还是起到作用;用在服务器应用上是完全不可行,因为这只会导致会话串行,同时只能处理一个.接下来在网上找一个支持连接并发的示例看一下
示例2
namespace SocketServer
{
class Program
{
private static byte[] result = new byte[1024];
private static int myProt = 8885; //端口
static Socket serverSocket;
static void Main(string[] args)
{
//服务器IP地址
IPAddress ip = IPAddress.Parse("127.0.0.1");
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Bind(new IPEndPoint(ip, myProt)); //绑定IP地址:端口
serverSocket.Listen(10); //设定最多10个排队连接请求
Console.WriteLine("启动监听{0}成功", serverSocket.LocalEndPoint.ToString());
//通过Clientsoket发送数据
Thread myThread = new Thread(ListenClientConnect);
myThread.Start();
Console.ReadLine();
} /// <summary>
/// 监听客户端连接
/// </summary>
private static void ListenClientConnect()
{
while (true)
{
Socket clientSocket = serverSocket.Accept();
clientSocket.Send(Encoding.ASCII.GetBytes("Server Say Hello"));
Thread receiveThread = new Thread(ReceiveMessage);
receiveThread.Start(clientSocket);
}
} /// <summary>
/// 接收消息
/// </summary>
/// <param name="clientSocket"></param>
private static void ReceiveMessage(object clientSocket)
{
Socket myClientSocket = (Socket)clientSocket;
while (true)
{
...
int receiveNumber = myClientSocket.Receive(result);
Console.WriteLine("接收客户端{0}消息{1}", myClientSocket.RemoteEndPoint.ToString(), Encoding.ASCII.GetString(result, 0, receiveNumber));
}
}
}
}
以上示例可以接受多个连接同时进行处理,但缺点是非常明显如果服务支撑的连接数比较大的情况那这种方式是不可行.你想象一下如果这个服务端要支撑1W,3W或者10W连接的情况那需要开多少个线程去处理这些连接呢,即使可以这样做那线程的开销也足够让服务器受的了.接下来看MSDN提供的异步示例
示例3
while (true)
{ // Set the event to nonsignaled state.
allDone.Reset(); // Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener ); // Wait until a connection is made before continuing.
allDone.WaitOne();
}
public static void AcceptCallback(IAsyncResult ar) {
// Signal the main thread to continue.
allDone.Set(); // Get the socket that handles the client request.
Socket listener = (Socket) ar.AsyncState;
Socket handler = listener.EndAccept(ar); // Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
这个示例来源于http://msdn.microsoft.com/en-us/library/6y0e13d3(v=vs.110).aspx,其实这个代码已经非常高效的体现我们在编写服务的时候如何实现一个接入监听.此示例用在应用开发上完全胜任的.
改进
以上示例3已经提供非常不错的代码,那是否可以进行一些规范的改进呢.其实在过往的经验中来看是可以,首先我们了解.NET有两种线程,一种是我们常用的而别一种则是IO线程.其实用一些测试工具可以看到AcceptCallback是由IO线程回调,那我们希望回调线程更快速度的释放出来,那我们需要做一些隔离上的规划.其实在很多范例代码中都是一连串地把事件做完,接入->接收->发送.这样一个连贯性的代码实现导致后其线程资源的控制和规划就变得非常因难.
从代码设计可以通过队列把回调线程需要的工作隔离出来,可以让回调线程更快的归队来处理其接接入的工作.当隔离后即使以后连接接入需要加一些逻辑控制也不会影响回调线程的快速回归.这样就可以让整个异步线程资源更高效.
public static void AcceptCallback(IAsyncResult ar) {
// Signal the main thread to continue.
allDone.Set(); // Get the socket that handles the client request.
Socket listener = (Socket) ar.AsyncState;
Socket handler = listener.EndAccept(ar);
Queue.Enqueue(handler);
}
总结
其实队列分离和控制在整个网络通讯实施过程会经常用到,其主要作是处理资源的分块和线程资源控制.毕竟任何一台服务器的资源都是有限的,如何分配线程资源给不同的任何来完成工作是非常重要,毕竟大量线程的开销会对系统造成比较大的压力.
.NET Socket服务编程之-高效连接接入编的更多相关文章
- NET Socket服务编程
smark https://github.com/IKende/ .NET Socket服务编程之-高效连接接入编 在.NET上编写网络服务深入都有2,3年了,而这些时间时如何在.NET里实现网络服务 ...
- Socket网络编程(2)--服务端实现
中秋了,首先祝大家中秋快乐,闲着无事在家整一个socket的聊天程序,有点仿QQ界面,就是瞎折腾,不知道最后是不是能将所有功能实现. 如果你对socket不了解,请看这篇文章:http://www.c ...
- socket 网络编程高速入门(一)教你编写基于UDP/TCP的服务(client)通信
由于UNIX和Win的socket大同小异,为了方便和大众化,这里先介绍Winsock编程. socket 网络编程的难点在入门的时候就是对基本函数的了解和使用,由于这些函数的结构往往比較复杂,參数大 ...
- 基于netty的socket服务端触发了channelInactive方法,但实际连接没有断开的问题
背景: 一个中小型H5游戏,后端使用基于 netty 的socket服务 服务端 分为 分发服务器 & 业务服务器,业务服务器可负载 用户客户端与分发服务器连接 分发服务器再作为客户端与每台业 ...
- nginx 为什么要反向代理 影藏后端 高效连接(给nginx,他自己返回) 端口冲突解决 多个服务
nginx 为什么要反向代理 影藏后端 高效连接(给nginx,他自己返回) 端口冲突解决 多个服务 单机使用反向代理可以根据不同url匹配到不同站点 rsync 的工作原理和应用实例 ...
- Python网络编程基础 ❷ 基于upd的socket服务 TCP黏包现象
TCP的长连接 基于upd的socket服务 TCP黏包现象
- Python网络编程基础 ❸ struct模块 基于upd的socket服务
struct模块 基于upd的socket服务
- 循序渐进Socket网络编程(多客户端、信息共享、文件传输)
循序渐进Socket网络编程(多客户端.信息共享.文件传输) 前言:在最近一个即将结束的项目中使用到了Socket编程,用于调用另一系统进行处理并返回数据.故把Socket的基础知识总结梳理一遍. 1 ...
- Python基础-week07 Socket网络编程
一 客户端/服务器架构 1.定义 又称为C/S架构,S 指的是Server(服务端软件),C指的是Client(客户端软件) 本章的中点就是教大写写一个c/s架构的软件,实现服务端软件和客户端软件基于 ...
随机推荐
- ssh通道技术
所有机器均为Linux操作系统. 机器是A,中间服务器为B,目标服务器是C. 从A可以ssh到B,从B可以ssh到C,但是A不能直接ssh到C. 现在展示利用ssh通道技术从A直接传输文件到C. ...
- 关于php Hash算法的一些整理总结
最近在公司内部的分享交流会上,有幸听到了鸟哥的关于php底层的一些算法的分享,虽然当时有些问题没有特别的明白,但是会后,查阅了各种各样的相关资料,对php的一些核心的hash算法有了进一步的理解和认识 ...
- Docker上运行dotnet core
下载microsoft/dotnet镜像 运行命令: docker pull microsoft/dotnet 如果没有使用阿里镜像加速的,参照这篇先配置好再跑上面命令: http://www.cnb ...
- asp.net GridView控件中诗选全选和全不选功能
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...
- Selenium2+python自动化16-alert\confirm\prompt
前言 不是所有的弹出框都叫alert,在使用alert方法前,先要识别出到底是不是alert.先认清楚alert长什么样子,下次碰到了,就可以用对应方法解决. alert\confirm\prompt ...
- Missing letters
function fearNotLetter(str) { //return str; var arr = str.split(''); var temp = []; var start = str. ...
- UVA 11624 Fire!(广度优先搜索)
题目大意:在一个N*M的迷宫内,J代表某人(只有一个),F代表火(可能不只一个),#代表墙,火每分钟会向四周除了墙以外的地方扩散一层,问人能否在没被火烧到 之前逃出迷宫,若能逃出输出最短时间.很明显的 ...
- 【随笔】ARP和RARP
ARP协议是什么? ARP协议是"Address Resolution Protocol"(地址解析协议)的缩写.在局域网中,网络中实际传输的是"帧",帧里面是 ...
- React Developer Tools 安装小提示
1,在google市场里边,安装React Developer Tools之后,发现是开启的,但是按下F12后,并没有发现react选项 2,后来通过查资料,发现必须是运行react项目的时候,才出现 ...
- mui学习笔记
一.页面刷新问题 1.父页面A跳转到子页面B,B页面修改数据后再跳回A页面,刷新A页面数据 (1).父页面A代码 window.addEventListener("pageflowrefre ...