- 浏览: 518576 次
- 性别:
- 来自: 河北
最新评论
-
zrong:
已经支持了。
杂谈:倘若flash支持JPEG XR格式? -
蓝月儿:
anr是这么解释的呀。。。一次面试的笔试题,竟然都不知道是这样 ...
什么是ANR 如何避免它? -
hymer2011:
这是纯jsp的还是基于ssh的?
jsp网上商城源码 -
敲敲大葱头:
好文章,学习了
Android-SDK SearchableDemo--浮动搜索框(SearchManager) -
overkill:
你好,我在使用InstallAnywhere的silent安装 ...
InstallAnyWhere学习笔记 ( by quqi99 )
Download SocketAsyncServerAndClient.zip - 200.2 KB Writing fast, scalable socket server code for TCP/IP is not easy. In order to help you write scalable, high performance socket server code, Microsoft created theSocketAsyncEventArgsclass. A proven way to write scalable, high performance socket code for TCP/IP in Windows can be seen in this article onI/O completion ports. Also, here's a link to a Microsoft page onI/O Completion Ports.SocketAsyncEventArgsuses I/O Completion ports via the asynchronous methods in the .NET Socket class.SocketAsyncEventArgsobject allows us to access the accepting socket with all the functionality of theSocketAsyncEventArgsclass, like working asynchronously, raising the Completed event, setting buffer space, etc. But there are other issues that need to be addressed in order to create dependable socket server code. One issue is buffers. Buffers in TCP are unmanaged, that is, not controlled by the .NET Framework, but by Windows system. So the buffer gets "pinned" to one place in memory, thereby causing memory fragmentation, since the .NET GarbageCollector will not be able to collect that space. This situation is improved by putting all the buffers together in one block of memory, and just reusing that same space over and over. The example in theBufferManagercode on Microsoft's page for theSetBuffermethod shows how to build it. You may have started your research into this topic at Microsoft's main page for theSocketAsyncEventArgsclass. The example code on that page got me started. But it was also confusing. It seems that they have removed some example code about theUserToken property. Also, some of the method names were a bit confusing, as were some of the variable names. Their reason for using a Semaphore was not explained really. While their code for building theBufferManagerwas good, the way that they dealt with theSetBuffermethod in their ProcessReceive method in example code for theSocketAsyncEventArgsclass will pretty much work in only the narrowest of examples. If you send a 10 byte string, and then a 20 byte string, it won't work. Their code sets the buffer to be whatever size you send on the first message from the client. So after the first message it would just send back the first 10 bytes. So, we need a better example of how to get the data and use it. Plus, in the explanation of the example code they said "For example, if a server application needs to have 15 socket accept operations outstanding at all times to support incoming client connection rates, it can allocate 15 reusableSocketAsyncEventArgsobjects for that purpose." But then their example only included reusableSocketAsyncEventArgsobjects for receive/send, not for accept. TheSocketAsyncEventArgsobject for the accept operation would wait until the receive/send finished to do another accept op. Instead we can use a pool, as they mentioned in their explanation, and post accept operations faster. So, this article was done in an attempt to make it clearer how to use theSocketAsyncEventArgsclass. The code in this article was developed on Visual Studio 2008 using .NET 3.5. Pay special attention to the code related to buffers, as buffer-related stuff seems to be an area where people have more difficulty. This article assumes some knowledge of delegates and event handling in Windows. Regarding theSocketAsyncEventArgsclass, Microsoft's website says it requires "Platforms: Windows 7, Windows Vista, Windows XP SP3, Windows Server 2008, Windows Server 2003. (The) .NET Framework Supported in: 4, 3.5 SP1, 3.0 SP1, 2.0 SP1. (The) .NET Framework Client Profile Supported in: 4, 3.5 SP1." If you have experience with socket server code, you can skip this section. For those new to socket programming, there are four main steps in using a socket server with TCP. (It's often described as six parts, but I like to put the first three together into one.) With TCP there is no guarantee that one send operation on the client will be equal to one receive operation on the server. One send operation on the client might be equal to one, two or more receive operations on the server. And the same is true going back to client from server. So you must have some way of determining where a TCP message begins and/or ends. Three possible ways to handle TCP messages are: Also, your communications protocol must include whether there will be a response (send operation) from the server back to the client after each received message or not. Will that response be after one complete received TCP message, or can it be after more than one message? If it is after one message, the code is simpler probably. 1) On the first receive op, receive less bytes than the length of the prefix. Receive/Send operations. In this app the receive and send operations are handled viaSocketAsyncEventArgsobjects that come out of a pool ofSocketAsyncEventArgsobjects that we create forreceive/sendoperations. This is NOT the same pool as we just examined regarding accept operations. To improve performance we have a pool of these objects which do receive and send operations. The number ofSocketAsyncEventArgsobjects in the pool for receive/send operations should probably be equal to the maximum number of concurrent connections allowed. What is our communication protocol in this code? Okay, let's look at the server code. Sometimes in code comments I abbreviate "SocketAsyncEventArgs" as "SAEA".
IntroductionBackground
TCP Protocol and Socket Basics
1)Listenfor connection requests
In order to listen you need to
(a) create a socket.
(b) bind that socket to a port,
(c) listen with that socket.
A client (not a server) can initiate a connection request, by sending a SYN packet. The client doesnotlisten for incoming connections. It always initiates connections by using the Connect or ConnectAsync method. When a client initiates a connection, then the Windows TCP/IP subsystem of the server will respond with SYN, ACK. After the client machine's Windows TCP/IP subsystem responds back with an ACK packet, the connection is established. Windows will handle this TCP/IP stuff for you. In other words, SYN, ACK, PSH, packets, and similar parts of TCP/IP donothave to be coded by you. Very nice. The server's listening socket can maintain a queue of connection requests waiting to be accepted. This queue is called the "backlog". The listening socket passes the connection info to another socket via an "accept" operation, and then gets the next incoming connection in the backlog queue, or if there is none, waits till there is a new connection from a client.
2)Acceptconnection requests
In order to have multiple connections on the same port, the listening socket must pass off the connection info to another socket, which accepts it. The accepting socket isnotbound to the port. You post an accept operation to pass the connection from the listening socket to the accepting socket. The accept operation can be posted before the incoming connection is established, so that the listening socket immediately passes off the new connection info to the accepting socket. The client doesnotneed to perform an accept operation.
3)Receive/Sendvia the connection
After the accept operation has completed you can now receive or send data with that connection. (The sameSocketAsyncEventArgsobject that did the accept operation could also do the receiving or sending, if we post a receive or send on it and have buffer space for it.) In the design of the code below, theSocketAsyncEventArgswhich did the accept operation passes the connection info over to anotherSocketAsyncEventArgsobject to do receiving/sending. (We could also split the receiving and sending into 2 separateSocketAsyncEventArgsobjects, if we wish. One reason to do that might be a need for different buffer sizes for send vs. receive. We would just need to have the connection info in both theSocketAsyncEventArgsobject that sends and theSocketAsyncEventArgsthat receives. And they might need a reference to each other also.)
4)Closethe connection
Either client or server can initiate an operation to close the connection. Usually the client would initiate that. Again, the lower level TCP/IP of the disconnect is handled by Windows operating system. The connection can be closed using the Close method, which destroys the Socket and cleans up its managed and unmanaged resources. You can also close by using the Disconnect or DisconnectAsync method, which allows reuse of the Socket.
1) Prefix every message with an integer that tells the length of the message.
2) All messages be fixed length. And both client and server must know the length before the message is sent.
3) Append every message with a delimiter to show where it ends. And both client and server must know what the delimiter is before the message is sent.
2) After having received part of the prefix on a previous receive op or ops, then receive another part of the prefix, but not all of it.
3) After having received part of the prefix on a previous receive op or ops, then receive the rest of the prefix, but nothing more.
4) After having received part of the prefix on a previous receive op or ops, we then receive the rest of it, plus part of the message.
5) After having received part of the prefix on a previous receive op or ops, we then receive the rest of it, plus all of the message.
6) Receive exactly the number of bytes that are in the prefix, but nothing more.
7) After having received exactly the number of bytes that are in the prefix on a previous receive op or ops, we then receive part of the message.
8) After having received exactly the number of bytes that are in the prefix on a previous receive op or ops, we then receive all of the message.
9) Receive the number of bytes for the prefix plus part of the message, but NOT all of the message.
10) After having received the prefix and part of the message on a previous receive op or ops, we then receive another part of the message, but not all of it.
11) After having received the prefix and part of the message on a previous receive op or ops, we then receive all the rest of the message.
12) Receive the number of bytes for the prefix plus all of the message on the first receive op. This is actually the most common thing that will happen. But all of the above things can happen and do happen. If both client and server have buffer sizes larger than the messages, then the situations above may not happen when running both client and server on the same machine, or even on a LAN. But TCP is unpredictable over the Internet. So your code needs to allow for all of those possibilities.Let's look at some code
Accept operations. In this app the socket which does the accept can be accessed thru aSocketAsyncEventArgsobject, in itsAcceptSocketproperty. On Microsoft'sAcceptSocketpage it says, "If not supplied (set to null) before calling theSocket.AcceptAsync method, a new socket will be created automatically." That's what is done in the code below. We just allow a new Socket object to be created for every new connection. (There is the option of reusing sockets in .NET and having a pool of Socket objects, but so far I have not found it to yield a significant advantage.) We can have a pool of theseSocketAsyncEventArgsobjects, each one containing a separate Socket object, to deal with accept operations. In this pool you do not need one object for each connection the server is maintaining, because after the accept operation completes, a reference to the socket is handed off to anotherSocketAsyncEventArgsobject pretty fast. It doesnotseem to help to put a lot ofSocketAsyncEventArgsobjects in the pool. Again, repeating for clarity, the socket which does the accept operation is inSocketAsyncEventArgs.AcceptSocketproperty of theSocketAsyncEventArgsobjects that comes out of the pool ofSocketAsyncEventArgsobjects that we create for accept operations.
1) One message from client will correspond with one message from the server.
2) After a connection is made the client will send a message first, and then post a receive op to wait for the response from the server. And for each message that the client sends the server will respond with a message to the client. Then it will post another receive op and wait for the next message from the client. In our code the server will make a few changes to the data before responding to the client, so that we do more than just echo data sent by the client, which is what the Microsoft example does. That approach should help you see what happens with the buffers better than just echoing would.
3) We will prefix every message with an integer that tells the length of the message.class Program
{
//You would want a buffer size larger than 25 probably, unless you know the
//data will almost always be less than 25. It is just 25 in our test app.
public static readonly Int32 testBufferSize = 25;
//This is the maximum number of asynchronous accept operations that can be
//posted simultaneously. This determines the size of the pool of
//SocketAsyncEventArgs objects that do accept operations. Note that this
//is NOT the same as the maximum # of connections.
public static readonly Int32 maxSimultaneousAcceptOps = 4;
//The size of the queue of incoming connections for the listen socket.
public static readonly Int32 backlog = 100;
//For the BufferManager
public static readonly Int32 opsToPreAlloc = 2; // 1 for receive, 1 for send
//This variable determines the number of
//SocketAsyncEventArg objects put in the pool of objects for receive/send.
//The value of this variable also affects the Semaphore.
//This app uses a Semaphore to ensure that the max # of connections
//value does not get exceeded.
//Max # of connections to a socket can be limited by the Windows Operating System
//also.
public static readonly Int32 maxNumberOfConnections = 100;
//If this is true, then after a message is received,
//the server will send a message back to the client.
//In our example app, this must be true. The code will not handle false.
public static bool respondToClient = true;
//If this port # will not work for you, it's okay to change it.
public static readonly Int32 port = 4444;
//This number must be the same as the value on the client.
//Tells what size the message prefix will be. Don't change this unless
//you change the code, because 4 is the length of 32 bit integer, which
//is what we are using as prefix.
public static readonly Int32 receivePrefixLength = 4;
public static readonly Int32 sendPrefixLength = 4;
public static Int32 mainTransMissionId = 10001;
//object that will be used to lock the mainTransMissionId
public static object lockerForTid = new object();
public static List<DataHolder> listOfDataHolders;
//object that will be used to lock the listOfDataHolders
public static object lockerForList = new object();
public static Int32 mainSessionId = 1000000001;
//object that will be used to lock the mainSessionId
public static object lockerForSesId = new object();
//If you make this a positive value, it will simulate some delay on the
//receive/send SAEA object after doing a receive operation.
//That would be where you would do some work on the received data,
//before responding to the client.
//This is in milliseconds. So a value of 1000 = 1 second delay.
public static readonly Int32 msDelayAfterGettingMessage = -1;
static void Main(String[] args)
{
try
{
//Just displaying the IP addresses of this machine.
IPAddress[] addressList =
Dns.GetHostEntry(Environment.MachineName).AddressList;
// Get endpoint for the listener.
IPEndPoint localEndPoint =
new IPEndPoint(addressList[addressList.Length - 1], port);
//This object holds a lot of settings that we pass from Main method
//to the SocketListener. In a real app, you might want to read
//these settings from a database or windows registry settings that
//you would create.
SocketListenerSettings theSocketListenerSettings =
new SocketListenerSettings(maxNumberOfConnections, backlog,
maxSimultaneousAcceptOps, receivePrefixLength,
testBufferSize, sendPrefixLength, opsToPreAlloc, localEndPoint);
//instantiate the SocketListener.
SocketListener socketListener =
new SocketListener(theSocketListenerSettings);
string closeString = "z";
string closeCheck = "";
while (closeCheck != closeString)
{
Console.WriteLine("type '" + closeString
+ "' and press Enter to close the program.");
closeCheck = Console.ReadLine();
}
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("port invalid");
}
catch (FormatException)
{
Console.WriteLine("port invalid");
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
}
The primary class is SocketListener.class SocketListener
{
//Buffers for sockets are unmanaged by .NET.
//So memory used for buffers gets "pinned", which makes the
//.NET garbage collector work around it, fragmenting the memory.
//Circumvent this problem by putting all buffers together
//in one block in memory. Then we will assign a part of that space
//to each SocketAsyncEventArgs object, and
//reuse that buffer space each time we reuse the SocketAsyncEventArgs object.
//Create a large reusable set of buffers for all socket operations.
BufferManager theBufferManager;
// the socket used to listen for incoming connection requests
Socket listenSocket;
//A Semaphore has two parameters, the initial number of available slots
// and the maximum number of slots. We'll make them the same.
//This Semaphore is used to keep from going over max connection #.
//(It is not about controlling threading really here.)
Semaphore theMaxConnectionsEnforcer;
//an object that we pass in and which has all the settings the listener needs
SocketListenerSettings socketListenerSettings;
// pool of reusable SocketAsyncEventArgs objects for accept operations
SocketAsyncEventArgsPool poolOfAcceptEventArgs;
// pool of reusable SocketAsyncEventArgs objects for
//receive and send socket operations
SocketAsyncEventArgsPool poolOfRecSendEventArgs;
//_______________________________________________________________________________
// Constructor.
public SocketListener(SocketListenerSettings theSocketListenerSettings)
{
this.socketListenerSettings = theSocketListenerSettings;
//Allocate memory for buffers. We are using a separate buffer space for
//receive and send, instead of sharing the buffer space, like the Microsoft
//example does.
this.theBufferManager =
new BufferManager(this.socketListenerSettings.BufferSize *
this.socketListenerSettings.MaxConnections *
this.socketListenerSettings.OpsToPreAllocate,
this.socketListenerSettings.BufferSize *
this.socketListenerSettings.OpsToPreAllocate);
this.poolOfRecSendEventArgs =
new SocketAsyncEventArgsPool(this.socketListenerSettings.MaxConnections);
this.poolOfAcceptEventArgs =
new SocketAsyncEventArgsPool(this.socketListenerSettings.MaxAcceptOps);
this.theMaxConnectionsEnforcer =
new Semaphore(this.socketListenerSettings.MaxConnections + 1,
this.socketListenerSettings.MaxConnections + 1);
//Microsoft's example called these from Main method, which you
//can easily do if you wish.
Init();
StartListen();
}
//____________________________________________________________________________
// initializes the server by preallocating reusable buffers and
// context objects (SocketAsyncEventArgs objects).
//It is NOT mandatory that you preallocate them or reuse them. But, but it is
//done this way to illustrate how the API can
// easily be used to create reusable objects to increase server performance.
internal void Init()
{
// Allocate one large byte buffer block, which all I/O operations will
//use a piece of. This gaurds against memory fragmentation.
this.theBufferManager.InitBuffer();
// preallocate pool of SocketAsyncEventArgs objects for accept operations
for (Int32 i = 0; i < this.socketListenerSettings.MaxAcceptOps; i++)
{
// add SocketAsyncEventArg to the pool
this.poolOfAcceptEventArgs.Push(CreateNewSaeaForAccept(poolOfAcceptEventArgs));
}
//The pool that we built ABOVE is for SocketAsyncEventArgs objects that do
// accept operations.
//Now we will build a separate pool for SAEAs objects
//that do receive/send operations. One reason to separate them is that accept
//operations do NOT need a buffer, but receive/send operations do.
//ReceiveAsync and SendAsync require
//a parameter for buffer size in SocketAsyncEventArgs.Buffer.
// So, create pool of SAEA objects for receive/send operations.
SocketAsyncEventArgs eventArgObjectForPool;
for (Int32 i = 0; i < this.socketListenerSettings.MaxConnections; i++)
{
//Allocate the SocketAsyncEventArgs object for this loop,
//to go in its place in the stack which will be the pool
//for receive/send operation context objects.
eventArgObjectForPool = new SocketAsyncEventArgs();
// assign a byte buffer from the buffer block to
//this particular SocketAsyncEventArg object
this.theBufferManager.SetBuffer(eventArgObjectForPool);
//Attach the SocketAsyncEventArgs object
//to its event handler. Since this SocketAsyncEventArgs object is
//used for both receive and send operations, whenever either of those
//completes, the IO_Completed method will be called.
eventArgObjectForPool.Completed +=
new EventHandler<SocketAsyncEventArgs>(IO_Completed);
//We can store data in the UserToken property of SAEA object.
DataHoldingUserToken theTempReceiveSendUserToken =
new DataHoldingUserToken(eventArgObjectForPool,
eventArgObjectForPool.Offset, eventArgObjectForPool.Offset +
this.socketListenerSettings.BufferSize,
this.socketListenerSettings.ReceivePrefixLength,
this.socketListenerSettings.SendPrefixLength, i + 1);
//We'll have an object that we call DataHolder, that we can remove from
//the UserToken when we are finished with it. So, we can hang on to the
//DataHolder, pass it to an app, serialize it, or whatever.
theTempReceiveSendUserToken.CreateNewDataHolder();
eventArgObjectForPool.UserToken = theTempReceiveSendUserToken;
// add this SocketAsyncEventArg object to the pool.
this.poolOfRecSendEventArgs.Push(eventArgObjectForPool);
}
}
//____________________________________________________________________________
// This method is called when we need to create a new SAEA object to do
//accept operations. The reason to put it in a separate method is so that
//we can easily add more objects to the pool if we need to.
//You can do that if you do NOT use a buffer in the SAEA object that does
//font-style: italic; color:
发表评论
相关推荐
SocketAsyncEventArgs是.NET Framework中用于实现高性能异步网络通信的类,主要应用于Socket编程。本文将深入探讨C#中使用SocketAsyncEventArgs构建服务端和客户端的相关知识点。 首先,SocketAsyncEventArgs是.NET...
在.NET框架中,异步Socket编程是构建高性能网络应用程序的核心技术。它允许程序在等待网络I/O操作完成时,不阻塞主线程,从而提高应用的响应性和效率。本篇文章将详细探讨如何使用.NET实现一个异步Socket服务器,...
例子主要包括SocketAsyncEventArgs通讯封装、服务端实现日志查看、SCOKET列表、上传、下载、远程文件流、吞吐量协议,用于测试SocketAsyncEventArgs的性能和压力,最大连接数支持65535个长连接,最高命令交互速度...
### 基于VB.NET的异步Socket网络TCP通信知识点详解 #### 一、概述 在计算机网络领域中,Socket编程是一种广泛使用的编程接口,它允许应用程序通过网络进行通信。Socket编程可以支持多种协议,其中最常用的是TCP/IP...
项目用到服务器SocketAsyncEventArgs高并发,尽管百度上千姿百态,还是自己总结写了一个可以接入项目的高性能~~还有用于模拟客户端发送的工具tcpudptest,,更改IP跟端口号就行~~纪念下写了三个多月的通信~~
标题和描述中的知识点聚焦于如何使用C#的Socket类实现UDP协议通信,这涉及到了UDP协议的基本特性以及在C#中的具体实现方法。以下是对这一主题的深入解析: ### UDP协议简介 用户数据报协议(UDP)是互联网协议族中...
首先,C# Socket Server是基于.NET Framework或.NET Core的服务器应用程序,用于接收和处理客户端的网络请求。它通常包括以下步骤:创建Socket实例、绑定到特定的IP地址和端口、监听连接请求,最后接受并处理客户端...
《高性能.NET Socket服务器利用异步Winsock》 在.NET框架中,构建高性能的TCP服务器时,异步Socket编程是至关重要的技术。本文将深入探讨如何使用异步Winsock(Windows Socket API)在C#中创建一个高效且可扩展的...
在C#.NET编程环境中,Socket是用于实现网络通信的核心组件,它基于TCP/IP协议栈,提供了低级别的网络访问能力。本篇文章将深入探讨C#.NET中的Socket编程,以及如何使用Socket进行网络程序开发。 首先,Socket是网络...
本资源“C# Socket高并发_socket_socket并发_c#socket_C#_socket高并发_源码.zip”显然提供了使用C#语言进行Socket高并发编程的示例代码和实践。以下是对这个主题的详细解释: C# Socket编程: C#是微软开发的一种...
SocketAsyncEventArgs是.NET Framework中用于高性能网络通信的一种高级API,主要应用于异步套接字操作。这个例子提供了完整的服务器(Server)和客户端(Client)示例,帮助开发者理解和使用SocketAsyncEventArgs...
在C#中,`System.Net.Sockets.Socket` 类为我们提供了实现Socket通信的接口。 **异步Socket传输** 是一种高效的通信方式,特别是在处理大量并发连接时。与同步传输相比,异步传输不会阻塞线程,因此可以提高应用...
SocketAsyncEventArgs 类是一组增强功能的一部分 System.Net.Sockets.Socket 提供了可供专用的高性能套接字应用程序的替代异步模式的类。 此类被专为需要高性能的网络服务器应用程序。 应用程序可以以独占方式使用...
C# UDP异步通讯 SocketAsyncEventArgs
例子主要包括SocketAsyncEventArgs通讯封装、服务端实现日志查看、SCOKET列表、上传、下载、远程文件流、吞吐量协议,用于测试SocketAsyncEventArgs的性能和压力,最大连接数支持65535个长连接,最高命令交互速度...
我需要大量的设备同时向这个服务器软件发送信息,但是一般情况,在开发中不可能同时提供这么大量的设备,因此需要我们做一个模拟的软件,在网络上搜索了很久,发现都不太符合我个人的需求,那么在翻阅大量大神的文章...
本例程旨在演示如何利用C#来构建这样的高性能、大容量的并发SOCKET应用。 首先,IOCP是一种Windows操作系统提供的多线程I/O调度机制,它能够有效地处理大量并发I/O操作,通过将I/O操作与线程解耦,避免了线程频繁上...
感谢大家对北风之神SOCKET框架的支持。鼓励。下面是北风之神 3.1的更新内容: 修正BUG: 1.ZYSocketSuper 读取 配置文件的最大连接数 读错问题。 2.ZYSocketSuper 无法断开客户端的问题。 3.BuffList 数据包解析...
在.NET框架中,C#语言提供了丰富的库支持来实现网络通信,其中Socket类是核心组件之一,用于创建基于TCP或UDP的客户端和服务器应用程序。本资料包“C#+Socket异步传输,c#socket通信,C#源码.zip”显然是为了演示如何...