.NET Socket服务编程之-高效连接接入编
来源:互联网 发布:ug软件安装 编辑:程序博客网 时间:2024/05/21 05:58
在.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服务编程之-高效连接接入编
- iOS入门编程之第三方推送服务的接入
- Socket编程之Tcp/Ip协议服务
- socket编程---之单连接服务端实现
- socket之面向连接编程(TCP)
- socket之无连接编程(UDP)
- Socket服务连接池
- Socket.IO连接服务
- python多线程socket编程--多客户端接入
- python多线程socket编程--多客户端接入
- Windows网络编程之面向连接的Socket编程
- Windows网络编程之面向非连接的Socket编程
- Delphi socket连接.net Socket
- asp.net socket连接
- Socket 连接简易编程
- 高效编程之欲擒故纵
- 高效编程之欲擒故纵
- 高效编程之欲擒故纵
- IOS程序中代码获取当前设备电量
- GSL介绍
- 第十三周 OJ平台 C:统计元音字母个数
- IOS委托机制
- PorterDuff.Mode
- .NET Socket服务编程之-高效连接接入编
- LA4851餐厅(求好的坐标的个数)
- 使用SetUnhandledExceptionFilter转储程序崩溃时内存DMP
- 字符编码笔记:ASCII,Unicode和UTF-8
- Ubuntu和Windows系统共享一套鼠键
- Jfinal插入oracle的blod字段
- 转 展望未来,总结过去10年的程序员生涯,给程序员小弟弟小妹妹们的一些总结性忠告
- 基于百度地图的android地理位置获取
- git配置文件