public string Hello{ Response.Write("test"); Response.End9() } 客户端:2 1 using System; 2 using System.Net; 3 using System.Net.Sockets; 4 using System.Text; 5 6 public class SynchronousSocketClient { 7 8 public static void StartClient() { 9 // Data buffer for incoming data. 10 byte[] bytes = new byte[1024]; 11 12 // Connect to a remote device. 13 try { 14 // Establish the remote endpoint for the socket. 15 // This example uses port 11000 on the local computer. 16 IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName()) 17 IPAddress ipAddress = ipHostInfo.AddressList[0]; 18 IPEndPoint remoteEP = […]
View Details/// <summary>/// 十进制转换为二进制/// </summary>/// <param name="x"></param>/// <returns></returns> public static string DecToBin(string x){string z = null;int X = Convert.ToInt32(x);int i = 0;long a, b = 0;while (X > 0){a = X%2;X = X/2;b = b + a*Pow(10, i);i++;}z = Convert.ToString(b);return z;} /// <summary>/// 16进制转ASCII码/// </summary>/// <param name="hexString"></param>/// <returns></returns> public static string HexToAscii(string hexString){StringBuilder sb = new StringBuilder();for (int i = 0; i <= hexString.Length – 2; i += 2){sb.Append(Convert.ToString(Convert.ToChar(Int32.Parse(hexString.Substring(i, 2),System.Globalization.NumberStyles.HexNumber))));}return sb.ToString();} /// <summary>/// 十进制转换为八进制/// </summary>/// <param name="x"></param>/// <returns></returns> public static string DecToOtc(string x){string z = null;int X = Convert.ToInt32(x);int […]
View Details最近浏览了几篇有关Socket发送消息的文章,发现大家对Socket Send方法理解有所偏差,现将自己在开发过程中对Socket的领悟写出来,以供大家参考。 (一)架构 基于TCP协议的Socket通信,架构类似于B/S架构,一个Socket通信服务器,多个Socket通信客户端。Socket通信服务器启动时,会建立一个侦听Socket,侦听Socket将侦听到的Socket连接传给接受Socket,然后由接受Socket完成接受、发送消息,当Socket存在异常时,断开连接。在实际开发项目中,往往要求Socket通信服务器能提供高效、稳定的服务,一般会用到以下技术:双工通信、完成端口、SAEA、池、多线程、异步等。特别是池,用的比较多,池一般包括一下几种: 1)Buffer池,用于集中管控Socket缓冲区,防止内存碎片。 2)SAEA池,用于集中管控Socket,重复利用Socket。 3)SQL池,用于分离网络服务层与数据访问层(SQL的执行效率远远低于网络层执行效率)。 4)线程池,用于从线程池中调用空闲线程执行业务逻辑,进一步提高网络层运行效率。 (二)Send 主服务器接受Socket为一端口,客户端Socket为一端口,这两个端口通过TCP协议建立连接,通信基础系统负责管理此连接,它有两个功能: 1)发送消息 2)接受消息 Socket的Send方法,并非大家想象中的从一个端口发送消息到另一个端口,它仅仅是拷贝数据到基础系统的发送缓冲区,然后由基础系统将发送缓冲区的数据到连接的另一端口。值得一说的是,这里的拷贝数据与异步发送消息的拷贝是不一样的,同步发送的拷贝,是直接拷贝数据到基础系统缓冲区,拷贝完成后返回,在拷贝的过程中,执行线程会IO等待, 此种拷贝与Socket自带的Buffer空间无关,但异步发送消息的拷贝,是将Socket自带的Buffer空间内的所有数据,拷贝到基础系统发送缓冲区,并立即返回,执行线程无需IO等待,所以异步发送在发送前必须执行SetBuffer方法,拷贝完成后,会触发你自定义回调函数ProcessSend,在ProcessSend方法中,调用SetBuffer方法,重新初始化Buffer空间。 口说无凭,下面给个例子: 服务器端: 客户端: 解释: 客户端第一次发送数据:1234567890。 客户端第一个接受数据:1234567890,该数据由服务端用Send同步方法发送返回。 客户端第二个接受数据:1234567890,该数据由服务端用Send异步方法发送返回。 以上似乎没什么异常,好,接下来,我只发送abc。 客户端第一个接受数据:abc,理所当然,没什么问题。 客户端第二个接受数据:abc4567890!为什么呢?应该是abc才对呀! 好,现在为大家解释一下: 异步发送是将其Buffer空间中所有数据拷贝到基础系统发送缓冲区,第一次拷贝1234567890到发送缓冲区,所以收到1234567890,第二次拷贝abc到发送缓冲区,替换了先前的123,所以收到abc4567890,大家明白的? 源码: BufferManager
1 |
<div><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System.Collections.Generic;<br /></span><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System.Net.Sockets;<br /><br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> This class creates a single large buffer which can be divided up <br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> and assigned to SocketAsyncEventArgs objects for use with each <br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> socket I/O operation. <br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> This enables bufffers to be easily reused and guards against <br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> fragmenting heap memory.<br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> <br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> The operations exposed on the BufferManager class are not thread safe.</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> BufferManager<br />{<br /> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> m_numBytes; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> the total number of bytes controlled by the buffer pool</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">byte</span><span style="color: rgb(0, 0, 0);">[] m_buffer; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> the underlying byte array maintained by the Buffer Manager</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> Stack</span><span style="color: rgb(0, 0, 0);"><</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">></span><span style="color: rgb(0, 0, 0);"> m_freeIndexPool; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> </span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> m_currentIndex;<br /> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> m_bufferSize;<br /><br /> </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> BufferManager(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> totalBytes, </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> bufferSize)<br /> {<br /> m_numBytes </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> totalBytes;<br /> m_currentIndex </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 128);">0</span><span style="color: rgb(0, 0, 0);">;<br /> m_bufferSize </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> bufferSize;<br /> m_freeIndexPool </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Stack</span><span style="color: rgb(0, 0, 0);"><</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">></span><span style="color: rgb(0, 0, 0);">();<br /> }<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Allocates buffer space used by the buffer pool</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> InitBuffer()<br /> {<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> create one big large buffer and divide that <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> out to each SocketAsyncEventArg object</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> m_buffer </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">byte</span><span style="color: rgb(0, 0, 0);">[m_numBytes];<br /> }<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Assigns a buffer from the buffer pool to the <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> specified SocketAsyncEventArgs object<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> <returns>true if the buffer was successfully set, else false</returns></span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">bool</span><span style="color: rgb(0, 0, 0);"> SetBuffer(SocketAsyncEventArgs args)<br /> {<br /><br /> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (m_freeIndexPool.Count </span><span style="color: rgb(0, 0, 0);">></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 128);">0</span><span style="color: rgb(0, 0, 0);">)<br /> {<br /> args.SetBuffer(m_buffer, m_freeIndexPool.Pop(), m_bufferSize);<br /> }<br /> </span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br /> {<br /> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> ((m_numBytes </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);"> m_bufferSize) </span><span style="color: rgb(0, 0, 0);"><</span><span style="color: rgb(0, 0, 0);"> m_currentIndex)<br /> {<br /> </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">false</span><span style="color: rgb(0, 0, 0);">;<br /> }<br /> args.SetBuffer(m_buffer, m_currentIndex, m_bufferSize);<br /> m_currentIndex </span><span style="color: rgb(0, 0, 0);">+=</span><span style="color: rgb(0, 0, 0);"> m_bufferSize;<br /> }<br /> </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">;<br /> }<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Removes the buffer from a SocketAsyncEventArg object. <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> This frees the buffer back to the buffer pool</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> FreeBuffer(SocketAsyncEventArgs args)<br /> {<br /> m_freeIndexPool.Push(args.Offset);<br /> args.SetBuffer(</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(128, 0, 128);">0</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(128, 0, 128);">0</span><span style="color: rgb(0, 0, 0);">);<br /> }<br /><br />}<br /></span></div> |
SocketAsyncEventArgsPool
1 |
<div><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System;<br /></span><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System.Collections.Generic;<br /></span><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System.Net.Sockets;<br /><br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Represents a collection of reusable SocketAsyncEventArgs objects. </span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> SocketAsyncEventArgsPool<br />{<br /> Stack</span><span style="color: rgb(0, 0, 0);"><</span><span style="color: rgb(0, 0, 0);">SocketAsyncEventArgs</span><span style="color: rgb(0, 0, 0);">></span><span style="color: rgb(0, 0, 0);"> m_pool;<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Initializes the object pool to the specified size<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> The "capacity" parameter is the maximum number of <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> SocketAsyncEventArgs objects the pool can hold</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> SocketAsyncEventArgsPool(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> capacity)<br /> {<br /> m_pool </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Stack</span><span style="color: rgb(0, 0, 0);"><</span><span style="color: rgb(0, 0, 0);">SocketAsyncEventArgs</span><span style="color: rgb(0, 0, 0);">></span><span style="color: rgb(0, 0, 0);">(capacity);<br /> }<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Add a SocketAsyncEventArg instance to the pool<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">The "item" parameter is the SocketAsyncEventArgs instance <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> to add to the pool</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> Push(SocketAsyncEventArgs item)<br /> {<br /> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (item </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">) { </span><span style="color: rgb(0, 0, 255);">throw</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> ArgumentNullException(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">Items added to a SocketAsyncEventArgsPool cannot be null</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">); }<br /> </span><span style="color: rgb(0, 0, 255);">lock</span><span style="color: rgb(0, 0, 0);"> (m_pool)<br /> {<br /> m_pool.Push(item);<br /> }<br /> }<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Removes a SocketAsyncEventArgs instance from the pool<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> and returns the object removed from the pool</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> SocketAsyncEventArgs Pop()<br /> {<br /> </span><span style="color: rgb(0, 0, 255);">lock</span><span style="color: rgb(0, 0, 0);"> (m_pool)<br /> {<br /> </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> m_pool.Pop();<br /> }<br /> }<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> The number of SocketAsyncEventArgs instances in the pool</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> Count<br /> {<br /> </span><span style="color: rgb(0, 0, 255);">get</span><span style="color: rgb(0, 0, 0);"> { </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> m_pool.Count; }<br /> }<br /><br />}</span></div> |
1 |
<div><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System;<br /></span><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System.Collections.Generic;<br /></span><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System.Linq;<br /></span><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System.Text;<br /></span><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System.Net.Sockets;<br /><br /></span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> AsyncUserToken<br />{<br /> </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> Socket Socket;<br />}<br /></span></div> |
Server
1 |
<div><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System;<br /></span><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System.Threading;<br /></span><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System.Net.Sockets;<br /></span><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System.Net;<br /></span><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System.Text;<br /><br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Implements the connection logic for the socket server. <br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> After accepting a connection, all data read from the client <br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> is sent back to the client. The read and echo back to the client pattern <br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> is continued until the client disconnects.</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> Server<br />{<br /> </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> m_numConnections; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> the maximum number of connections the sample is designed to handle simultaneously </span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> m_receiveBufferSize;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> buffer size to use for each socket I/O operation </span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> BufferManager m_bufferManager; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> represents a large reusable set of buffers for all socket operations</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> opsToPreAlloc </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 128);">2</span><span style="color: rgb(0, 0, 0);">; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> read, write (don't alloc buffer space for accepts)</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> Socket listenSocket; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> the socket used to listen for incoming connection requests<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> pool of reusable SocketAsyncEventArgs objects for write, read and accept socket operations</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> SocketAsyncEventArgsPool m_readWritePool;<br /> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> m_totalBytesRead; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> counter of the total # bytes received by the server</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> m_numConnectedSockets; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> the total number of clients connected to the server </span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> Semaphore m_maxNumberAcceptedClients;<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Create an uninitialized server instance. <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> To start the server listening for connection requests<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> call the Init method followed by Start method <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> <param name="numConnections">the maximum number of connections the sample is designed to handle simultaneously</param><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> <param name="receiveBufferSize">buffer size to use for each socket I/O operation</param></span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> Server(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> numConnections, </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> receiveBufferSize)<br /> {<br /> m_totalBytesRead </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 128);">0</span><span style="color: rgb(0, 0, 0);">;<br /> m_numConnectedSockets </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 128);">0</span><span style="color: rgb(0, 0, 0);">;<br /> m_numConnections </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> numConnections;<br /> m_receiveBufferSize </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> receiveBufferSize;<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> allocate buffers such that the maximum number of sockets can have one outstanding read and <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">write posted to the socket simultaneously </span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> m_bufferManager </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> BufferManager(receiveBufferSize </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> numConnections </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> opsToPreAlloc,<br /> receiveBufferSize);<br /><br /> m_readWritePool </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> SocketAsyncEventArgsPool(numConnections);<br /> m_maxNumberAcceptedClients </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Semaphore(numConnections, numConnections);<br /> }<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Initializes the server by preallocating reusable buffers and <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> context objects. These objects do not need to be preallocated <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> or reused, but it is done this way to illustrate how the API can <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> easily be used to create reusable objects to increase server performance.<br /> </span><span style="color: rgb(0, 128, 0);">//<br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> Init()<br /> {<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Allocates one large byte buffer which all I/O operations use a piece of. This gaurds <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> against memory fragmentation</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> m_bufferManager.InitBuffer();<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> preallocate pool of SocketAsyncEventArgs objects</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> SocketAsyncEventArgs readWriteEventArg;<br /><br /> </span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> i </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 128);">0</span><span style="color: rgb(0, 0, 0);">; i </span><span style="color: rgb(0, 0, 0);"><</span><span style="color: rgb(0, 0, 0);"> m_numConnections; i</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">)<br /> {<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">Pre-allocate a set of reusable SocketAsyncEventArgs</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> readWriteEventArg </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> SocketAsyncEventArgs();<br /> readWriteEventArg.Completed </span><span style="color: rgb(0, 0, 0);">+=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> EventHandler</span><span style="color: rgb(0, 0, 0);"><</span><span style="color: rgb(0, 0, 0);">SocketAsyncEventArgs</span><span style="color: rgb(0, 0, 0);">></span><span style="color: rgb(0, 0, 0);">(IO_Completed);<br /> readWriteEventArg.UserToken </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> AsyncUserToken();<br /> <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> assign a byte buffer from the buffer pool to the SocketAsyncEventArg object</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> m_bufferManager.SetBuffer(readWriteEventArg);<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> add SocketAsyncEventArg to the pool</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> m_readWritePool.Push(readWriteEventArg);<br /> }<br /><br /> }<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Starts the server such that it is listening for <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> incoming connection requests. <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> <param name="localEndPoint">The endpoint which the server will listening <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> for connection requests on</param></span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> Start(IPEndPoint localEndPoint)<br /> {<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> create the socket which listens for incoming connections</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> listenSocket </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);<br /> listenSocket.Bind(localEndPoint);<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> start the server with a listen backlog of 100 connections</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> listenSocket.Listen(</span><span style="color: rgb(128, 0, 128);">100</span><span style="color: rgb(0, 0, 0);">);<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> post accepts on the listening socket</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> StartAccept(</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">);<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">Console.WriteLine("{0} connected sockets with one outstanding receive posted to each....press any key", m_outstandingReadCount);</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> Console.WriteLine(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">Press any key to terminate the server process....</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br /> Console.ReadKey();<br /> }<br /><br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Begins an operation to accept a connection request from the client <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> <param name="acceptEventArg">The context object to use when issuing <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> the accept operation on the server's listening socket</param></span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> StartAccept(SocketAsyncEventArgs acceptEventArg)<br /> {<br /> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (acceptEventArg </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">)<br /> {<br /> acceptEventArg </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> SocketAsyncEventArgs();<br /> acceptEventArg.Completed </span><span style="color: rgb(0, 0, 0);">+=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> EventHandler</span><span style="color: rgb(0, 0, 0);"><</span><span style="color: rgb(0, 0, 0);">SocketAsyncEventArgs</span><span style="color: rgb(0, 0, 0);">></span><span style="color: rgb(0, 0, 0);">(AcceptEventArg_Completed);<br /> }<br /> </span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br /> {<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> socket must be cleared since the context object is being reused</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> acceptEventArg.AcceptSocket </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;<br /> }<br /><br /> m_maxNumberAcceptedClients.WaitOne();<br /> </span><span style="color: rgb(0, 0, 255);">bool</span><span style="color: rgb(0, 0, 0);"> willRaiseEvent </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> listenSocket.AcceptAsync(acceptEventArg);<br /> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 0);">!</span><span style="color: rgb(0, 0, 0);">willRaiseEvent)<br /> {<br /> ProcessAccept(acceptEventArg);<br /> }<br /> }<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> This method is the callback method associated with Socket.AcceptAsync <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> operations and is invoked when an accept operation is complete<br /> </span><span style="color: rgb(0, 128, 0);">//<br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> AcceptEventArg_Completed(</span><span style="color: rgb(0, 0, 255);">object</span><span style="color: rgb(0, 0, 0);"> sender, SocketAsyncEventArgs e)<br /> {<br /> ProcessAccept(e);<br /> }<br /><br /> </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> ProcessAccept(SocketAsyncEventArgs e)<br /> {<br /> Interlocked.Increment(</span><span style="color: rgb(0, 0, 255);">ref</span><span style="color: rgb(0, 0, 0);"> m_numConnectedSockets);<br /> Console.WriteLine(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">Client connection accepted. There are {0} clients connected to the server</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,<br /> m_numConnectedSockets);<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Get the socket for the accepted client connection and put it into the <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">ReadEventArg object user token</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> SocketAsyncEventArgs readEventArgs </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> m_readWritePool.Pop();<br /> ((AsyncUserToken)readEventArgs.UserToken).Socket </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> e.AcceptSocket;<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> As soon as the client is connected, post a receive to the connection</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">bool</span><span style="color: rgb(0, 0, 0);"> willRaiseEvent </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> e.AcceptSocket.ReceiveAsync(readEventArgs);<br /> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 0);">!</span><span style="color: rgb(0, 0, 0);">willRaiseEvent)<br /> {<br /> ProcessReceive(readEventArgs);<br /> }<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Accept the next connection request</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> StartAccept(e);<br /> }<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> This method is called whenever a receive or send operation is completed on a socket <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> <param name="e">SocketAsyncEventArg associated with the completed receive operation</param></span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> IO_Completed(</span><span style="color: rgb(0, 0, 255);">object</span><span style="color: rgb(0, 0, 0);"> sender, SocketAsyncEventArgs e)<br /> {<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> determine which type of operation just completed and call the associated handler</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">switch</span><span style="color: rgb(0, 0, 0);"> (e.LastOperation)<br /> {<br /> </span><span style="color: rgb(0, 0, 255);">case</span><span style="color: rgb(0, 0, 0);"> SocketAsyncOperation.Receive:<br /> ProcessReceive(e);<br /> </span><span style="color: rgb(0, 0, 255);">break</span><span style="color: rgb(0, 0, 0);">;<br /> </span><span style="color: rgb(0, 0, 255);">case</span><span style="color: rgb(0, 0, 0);"> SocketAsyncOperation.Send:<br /> ProcessSend(e);<br /> </span><span style="color: rgb(0, 0, 255);">break</span><span style="color: rgb(0, 0, 0);">;<br /> </span><span style="color: rgb(0, 0, 255);">default</span><span style="color: rgb(0, 0, 0);">:<br /> </span><span style="color: rgb(0, 0, 255);">throw</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> ArgumentException(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">The last operation completed on the socket was not a receive or send</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br /> }<br /><br /> }<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> This method is invoked when an asynchronous receive operation completes. <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> If the remote host closed the connection, then the socket is closed. <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> If data was received then the data is echoed back to the client.<br /> </span><span style="color: rgb(0, 128, 0);">//<br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> ProcessReceive(SocketAsyncEventArgs e)<br /> {<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> check if the remote host closed the connection</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> AsyncUserToken token </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (AsyncUserToken)e.UserToken;<br /> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (e.BytesTransferred </span><span style="color: rgb(0, 0, 0);">></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 128);">0</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">&&</span><span style="color: rgb(0, 0, 0);"> e.SocketError </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> SocketError.Success)<br /> {<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">increment the count of the total bytes receive by the server</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> Interlocked.Add(</span><span style="color: rgb(0, 0, 255);">ref</span><span style="color: rgb(0, 0, 0);"> m_totalBytesRead, e.BytesTransferred);<br /> Console.WriteLine(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">The server has read a total of {0} bytes</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, m_totalBytesRead);<br /><br /><br /> Int32 BytesToProcess </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> e.BytesTransferred;<br /> Byte[] bt </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Byte[BytesToProcess];<br /> Buffer.BlockCopy(e.Buffer, e.Offset, bt, </span><span style="color: rgb(128, 0, 128);">0</span><span style="color: rgb(0, 0, 0);">, BytesToProcess);<br /> </span><span style="color: rgb(0, 0, 255);">string</span><span style="color: rgb(0, 0, 0);"> strReceive </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Encoding.Default.GetString(bt);<br /><br /><br /> Send(token.Socket, bt, </span><span style="color: rgb(128, 0, 128);">0</span><span style="color: rgb(0, 0, 0);">, bt.Length, </span><span style="color: rgb(128, 0, 128);">1000</span><span style="color: rgb(0, 0, 0);">);<br /><br /><br /> Thread.Sleep(</span><span style="color: rgb(128, 0, 128);">1000</span><span style="color: rgb(0, 0, 0);">);<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">echo the data received back to the client<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">e.SetBuffer(e.Offset, e.BytesTransferred);</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">bool</span><span style="color: rgb(0, 0, 0);"> willRaiseEvent </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> token.Socket.SendAsync(e);<br /> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 0);">!</span><span style="color: rgb(0, 0, 0);">willRaiseEvent)<br /> {<br /> ProcessSend(e);<br /> }<br /><br /> }<br /> </span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br /> {<br /> CloseClientSocket(e);<br /> }<br /> }<br /><br /><br /> </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> Send(Socket socket, </span><span style="color: rgb(0, 0, 255);">byte</span><span style="color: rgb(0, 0, 0);">[] buffer, </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> offset, </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> size, </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> timeout)<br /> {<br /> socket.SendTimeout </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 128);">0</span><span style="color: rgb(0, 0, 0);">;<br /> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> startTickCount </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Environment.TickCount;<br /> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> sent </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 128);">0</span><span style="color: rgb(0, 0, 0);">; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> how many bytes is already sent</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">do</span><span style="color: rgb(0, 0, 0);"><br /> {<br /> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (Environment.TickCount </span><span style="color: rgb(0, 0, 0);">></span><span style="color: rgb(0, 0, 0);"> startTickCount </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> timeout)<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">throw new Exception("Timeout.");</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);"><br /> {<br /> sent </span><span style="color: rgb(0, 0, 0);">+=</span><span style="color: rgb(0, 0, 0);"> socket.Send(buffer, offset </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> sent, size </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);"> sent, SocketFlags.None);<br /> }<br /> </span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);"> (SocketException ex)<br /> {<br /> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (ex.SocketErrorCode </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> SocketError.WouldBlock </span><span style="color: rgb(0, 0, 0);">||</span><span style="color: rgb(0, 0, 0);"><br /> ex.SocketErrorCode </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> SocketError.IOPending </span><span style="color: rgb(0, 0, 0);">||</span><span style="color: rgb(0, 0, 0);"><br /> ex.SocketErrorCode </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> SocketError.NoBufferSpaceAvailable)<br /> {<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> socket buffer is probably full, wait and try again</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> Thread.Sleep(</span><span style="color: rgb(128, 0, 128);">30</span><span style="color: rgb(0, 0, 0);">);<br /> }<br /> </span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br /> </span><span style="color: rgb(0, 0, 255);">throw</span><span style="color: rgb(0, 0, 0);"> ex; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> any serious error occurr</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> }<br /> } </span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);"> (sent </span><span style="color: rgb(0, 0, 0);"><</span><span style="color: rgb(0, 0, 0);"> size);<br /> }<br /><br /><br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> This method is invoked when an asynchronous send operation completes. <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> The method issues another receive on the socket to read any additional <br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> data sent from the client<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> <param name="e"></param></span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> ProcessSend(SocketAsyncEventArgs e)<br /> {<br /> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (e.SocketError </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> SocketError.Success)<br /> {<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">e.SetBuffer(e.Offset, 10);<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> done echoing data back to the client</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> AsyncUserToken token </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (AsyncUserToken)e.UserToken;<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> read the next block of data send from the client</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">bool</span><span style="color: rgb(0, 0, 0);"> willRaiseEvent </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> token.Socket.ReceiveAsync(e);<br /> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 0);">!</span><span style="color: rgb(0, 0, 0);">willRaiseEvent)<br /> {<br /> ProcessReceive(e);<br /> }<br /> }<br /> </span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br /> {<br /> CloseClientSocket(e);<br /> }<br /> }<br /><br /> </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> CloseClientSocket(SocketAsyncEventArgs e)<br /> {<br /> AsyncUserToken token </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> e.UserToken </span><span style="color: rgb(0, 0, 255);">as</span><span style="color: rgb(0, 0, 0);"> AsyncUserToken;<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> close the socket associated with the client</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);"><br /> {<br /> token.Socket.Shutdown(SocketShutdown.Send);<br /> }<br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> throws if client process has already closed</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);"> (Exception) { }<br /> token.Socket.Close();<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> decrement the counter keeping track of the total number of clients connected to the server</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> Interlocked.Decrement(</span><span style="color: rgb(0, 0, 255);">ref</span><span style="color: rgb(0, 0, 0);"> m_numConnectedSockets);<br /> m_maxNumberAcceptedClients.Release();<br /> Console.WriteLine(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">A client has been disconnected from the server. There are {0} clients connected to the server</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, m_numConnectedSockets);<br /><br /> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Free the SocketAsyncEventArg so they can be reused by another client</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> m_readWritePool.Push(e);<br /> }<br /><br />}</span></div> |
Program
1 |
<div><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System;<br /></span><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System.Net;<br /></span><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System.Collections.Generic;<br /></span><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);"> System.IO;<br /><br /></span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> Program<br />{<br /> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> Main(</span><span style="color: rgb(0, 0, 255);">string</span><span style="color: rgb(0, 0, 0);">[] args)<br /> {<br /> IPEndPoint iep </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> IPEndPoint(IPAddress.Parse(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">10.1.20.6</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">), </span><span style="color: rgb(128, 0, 128);">1333</span><span style="color: rgb(0, 0, 0);">);<br /><br /> Server objServer </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Server(</span><span style="color: rgb(128, 0, 128);">1000</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(128, 0, 128);">10</span><span style="color: rgb(0, 0, 0);">);<br /> objServer.Init();<br /> objServer.Start(iep);<br /> }<br />}<br /></span></div> |
http://www.cnblogs.com/tianzhiliang/archive/2010/09/08/1821623.html
View Details其实只要用到Socket联接,基本上就得使用Thread,是交叉使用的。C#封装的Socket用法基本上不算很复杂,只是不知道托管之后的Socket有没有其他性能或者安全上的问题。在C#里面能找到的最底层的操作也就是socket了,概念不做解释。程序模型如下:WinForm程序 : 启动端口侦听;监视Socket联接情况;定期关闭不活动的联接;Listener:处理Socket的Accept函数,侦听新链接,建立新Thread来处理这些联接(Connection)。Connection:处理具体的每一个联接的会话。 1:WinForm如何启动一个新的线程来启动Listener://start the serverprivate void btn_startServer_Click(object sender, EventArgs e){//this.btn_startServer.Enabled = false;Thread _createServer = new Thread(new ThreadStart(WaitForConnect));_createServer.Start();}//wait all connectionsprivate void WaitForConnect(){SocketListener listener = new SocketListener(Convert.ToInt32(this.txt_port.Text));listener.StartListening();}因为侦听联接是一个循环等待的函数,所以不可能在WinForm的线程里面直接执行,不然Winform也就是无法继续任何操作了,所以才指定一个新的线程来执行这个函数,启动侦听循环。这一个新的线程是比较简单的,基本上没有启动的参数,直接指定处理函数就可以了。2:Listener如何启动循环侦听,并且启动新的带有参数的线程来处理Socket联接会话。先看如何建立侦听:(StartListening函数)IPEndPoint localEndPoint = new IPEndPoint(_ipAddress, _port);// Create a TCP/IP socket. Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);// Bind the socket to the local endpoint and listen for incoming connections. try{listener.Bind(localEndPoint);listener.Listen(20);//20 trucks // Start listening for connections. while (true){// here will be suspended while waiting for a new connection. Socket connection = listener.Accept();Logger.Log("Connect", connection.RemoteEndPoint.ToString());//log it, new connection……}}……基本步骤比较简单:建立本机的IPEndPoint对象,表示以本机为服务器,在指定端口侦听;然后绑定到一个侦听Socket上;进入while循环,等待新的联接;如果有新的联接,那么建立新的socket来对应这个联接的会话。值得注意的就是这一句联接代码:listener.Accept()。执行这一句的时候,程序就在这个地方等待,直到有新的联检请求的时候程序才会执行下一句。这是同步执行,当然也可以异步执行。 新的联接Socket建立了(Accept之后),对于这些新的socket该怎么办呢?他们依然是一个循环等待,所以依然需要建立新的Thread给这些Socket去处理会话(接收/发送消息),而这个Thread就要接收参数了。Thread本身是不能接收参数的,为了让它可以接收参数,可以采用定义新类,添加参数作为属性的方法来解决。因为每一个Socket是一个Connection周期,所以我定义了这么一个类public class Connection。这个类至少有这样一个构造函数public Connection(Socket socket); 之所以这么做,就是为了把Socket参数传给这个Connection对象,然后好让Listener启动这个Thread的时候,Thread可以知道他正在处理哪一个Socket。具体处理的方法:(在Listener的StartListening函数,ocket connection […]
View DetailsTCP与UDP区别 TCP—传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。 UDP—用户数据报协议,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快 Overview TCP (Transmission Control Protocol) is the most commonly used protocol on the Internet. The reason for this is because TCP offers error correction. When the TCP protocol is used there is a "guaranteed delivery." This is due largely in part to a method called "flow control." Flow control determines when data needs to be re-sent, and stops the flow of data until previous packets are successfully transferred. This works because if a packet of data is sent, a collision may occur. When this […]
View Details