最近浏览了几篇有关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 DetailsLinQ to Objects是LinQ家庭的核心,其它的LinQ也使用了与LinQ to Objects相同的查询句法。最终编译器都是把LinQ句法翻译成扩展方法的链式表达式,同时把扩展方法中的lambda表达式转换成匿名类中的匿名方法,然后再把查询表达式编译成MSIL。 LinQ to SQL、LinQ to DataSets、LinQ to Entities和LinQ to XML则不是把查询表达式转换成MSIL,而是把查询表达式树转换成相应的特定查询语言。LinQ to SQL会生成T-SQL,LinQ to Entities会生成eSQL,LinQ to XML会生成XPath语句等。 LinQ标准查询操作符列表 《图1》 在VS2008及以后的版本中提供了LinQ的查询样例程序。 \Programe Files\Microsoft Visual Studio 2008(10.0 VS2010)\Samples\1033文件夹下有个压缩包CSharpSamples.zip,解压它,继续打开其中的文件夹 .\LinqSamples\SampleQueries\SampleQueries.sln,打开此解决方案,运行该项目,界面如下 《图2》 在左边选择示例,右侧上方会出现相应的LinQ代码,右侧下方会出现代码的运行结果。通过这个样例程序,我们可以学习LinQ的各种用法。 下面我们来学习LinQ常用操作符 一、筛选操作符Where 根据谓词对源序列的内容进行筛选,类似于SQL中的where子句。 1.简单where表达式 使用扩展方法 var query1 = CustomerList.Where(c => c.Country == “USA”); 使用查询表达式语法 query1 = from c in CustomerList where c.Country == “USA” select c; 使用扩展方法需要向where方法中传入lambda表达式。 2.复合where表达式 所谓的复合where表达式就是使用&&或||操作符对数据进行筛选 使用扩展方法 var query2 = CustomerList.Where(c => c.Country == “USA” && c.Orders.Any()); 使用查询表达式语法 query2 = from c in CustomerList where c.Country == “USA” […]
View Details集合 Request.ClientCertificate(key[SubField])所有客户证书的信息的集合。对于Key,该集合具有如下的关键字: Subject证书的主题。包含所有关于证书收据的信息。能和所有的子域后缀一起使用。 Issuer证书的发行人。包含所有关于证书验证的信息。除了CN外,能和所有的子域后缀一起使用。 VadidFrom证书发行的日期。使用VBScript格式。 ValidUntil该证书不在有效的时间。 SerialNumber包含该证书的序列号。 Certificate包含整个证书内容的二进制流,使用ASN.1格式。 对于SubField,Subject和Issuer关键字可以具有如下的子域后缀:(比如:SubjectOU或IssuerL) C起源国家。 O公司或组织名称。 OU组织单元。 CN用户的常规名称。 L局部。 S州(或省)。 T个人或公司的标题。 GN给定名称。 I初始。 当文件cervbs.inc(VBScript使用)或cerjavas.inc(Jscript使用)通过使用#INCLUDE导向包含在你的Active Server Page里时,下面两个标志可以使用: ceCertPresent指明客户证书是否存在,其值为TRUE或FALSE。 ceUnrecongnizedIssure指明在该链表中的最后的证书的发行者是否未知,其值为TRUE或FALSE。 Request.Cookies(Cookie[(key).Attribute]) Cookie的集合。允许获得浏览器的Cookie。Cookie指明返回那一个Cookie。Key用于从Cookie字典中返回具有某一关键字的Cookie值。对于Attribute,你能使用属性HasKeys来确定某一Cookie是否具有子关键字。HasKeys的值为TRUE或FALSE。 Request.Form(Parameter)[(Index).Count] 填写在HTML的表单中所有的数据的集合。Parameter是在HTML表单中某一元素的名称。当某一参数具有不止一个值(比如,当在<SELECT>中使用MULTIPLE属性时)时,使用Index。当某一参数具有多值时,Count指明多值个数。 Request.QueryString(Varible)[(Index).Count] 查询字符串的所有值的集合。Varible是在查询字符串某一变量的名称。当某一变量具有多于一个值时,使用Index。当某一参数具有多值时,Count指明值的个数。 Request.ServerVaribles(Server Environment Variable) 环境变量的集合。允许读取HTTP头。你可以通过使用HTTP_前缀来读取任何头信息。比如,HTTP_USER_AGENT接受客户代理HTTP头(浏览器类型)。除此外,你可以使用下表所示的变量获得任何环境信息。 ALL_HTTP客户端发送的所有HTTP标头,他的结果都有前缀HTTP_。 ALL_RAW客户端发送的所有HTTP标头,其结果和客户端发送时一样,没有前缀HTTP_ APPL_MD_PATH应用程序的元数据库路径。 APPL_PHYSICAL_PATH与应用程序元数据库路径相应的物理路径。 AUTH_PASSWORD当使用基本验证模式时,客户在密码对话框中输入的密码。 AUTH_TYPE这是用户访问受保护的脚本时,服务器用于检验用户的验证方法。 AUTH_USER代验证的用户名。 CERT_COOKIE唯一的客户证书ID号。 CERT_FLAG客户证书标志,如有客户端证书,则bit0为0。如果客户端证书验证无效,bit1被设置为1。 CERT_ISSUER用户证书中的发行者字段。 CERT_KEYSIZE安全套接字层连接关键字的位数,如128。 CERT_SECRETKEYSIZE服务器验证私人关键字的位数。如1024。 CERT_SERIALNUMBER客户证书的序列号字段。 CERT_SERVER_ISSUER服务器证书的发行者字段 CERT_SERVER_SUBJECT服务器证书的主题字段。 CERT_SUBJECT客户端证书的主题字段。 CONTENT_LENGTH客户端发出内容的长度。 CONTENT_TYPE客户发送的form内容或HTTP PUT的数据类型。 GATEWAY_INTERFACE服务器使用的网关界面。 HTTPS如果请求穿过安全通道(SSL),则返回ON。如果请求来自非安全通道,则返回OFF。 HTTPS_KEYSIZE安全套接字层连接关键字的位数,如128。 HTTPS_SECRETKEYSIZE服务器验证私人关键字的位数。如1024。 HTTPS_SERVER_ISSUER服务器证书的发行者字段。 HTTPS_SERVER_SUBJECT服务器证书的主题字段。 INSTANCE_IDIIS实例的ID号。 INSTANCE_META_PATH响应请求的IIS实例的元数据库路径。 LOCAL_ADDR返回接受请求的服务器地址。 LOGON_USER用户登录Windows NT的帐号 PATH_INFO客户端提供的路径信息。 PATH_TRANSLATED通过由虚拟至物理的映射后得到的路径。 QUERY_STRING查询字符串内容。 REMOTE_ADDR发出请求的远程主机的IP地址。 REMOTE_HOST发出请求的远程主机名称。 REQUEST_METHOD提出请求的方法。比如GET、HEAD、POST等等。 SCRIPT_NAME执行脚本的名称。 SERVER_NAME服务器的主机名、DNS地址或IP地址。 SERVER_PORT接受请求的服务器端口号。 SERVER_PORT_SECURE如果接受请求的服务器端口为安全端口时,则为1,否则为0。 SERVER_PROTOCOL服务器使用的协议的名称和版本。 SERVER_SOFTWARE应答请求并运行网关的服务器软件的名称和版本。 URL提供URL的基本部分。 方法 Request.BinaryRead(Count) 接收一个HTML表单的未经过处理的内容。当调用此方法时,Count指明要接收多少字节。在调用此方法后,Count指明实际上接收到多少个字节。 属性 Request.TotalBytes 查询体的长度,以字节为单位。
View Details当使用ASP进行Web编程时,你发现确实修改了程序代码,确认没有改错,却发现输出的Webyemi8an没有变化,这就是服务端将此ASP文件加入了页面缓存。 清楚页面缓存有一下几种方法; 1.在ASP页面首部加入一下代码: Response.Buffer=True Response.ExpiresAbsolute=Now()-1 Response.Expires=0 Response.CacheControl=“no-cache” Response.AddHeader “Pragma”,“no-Cache” 2.在HTML代码中加入下面的代码,不过这些代码似乎不能解决刷新无效的问题,因为这些代码只是针对客户端的页面缓存而已,只具有清楚客户端的页面缓存的功能。 <HEAD> <META HTTP-EQUIV="Pragma" CONTENT="no-cache"> <META HTTP-EQUIV="Cache-Control" CONTENT="no-cache"> <META HTTP-EQUIV="Expires" CONTENT="no-cache"> </HEAD> 3.如果一个ASP文件是url.asp,那么在访问的时候,脚本链接应该为: <input type="button" onclick="window.location.href=’url.asp?’+Math.random()" value="提交"/>
View Details今天在项目中一个页面使用 System.Web.UI.ScriptManager.RegisterStartupScript(this, GetType(), "js", "alert('OK');", true);的时候发现没用,检查发现脚本没用注册到页面, check页面发现了问题,<form method="post"> 没用ruanat,更详细的信息请参看MSDN关于这个方法参数的介绍
View DetailsVS2010安装项目的系统必备中没有.NET 2.0,不过我们可以从VS2008的程序文件中找到 .NET 2.0 的系统必备安装包。 安装了VS2008 的 C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages 下的 DotNetFX 文件夹,就是 .NET 2.0 的系统必备安装包。把 DotNetFX 文件夹复制到安装了 VS2010 的 C:\Program Files\Microsoft SDKs\Windows\v7.0A\Bootstrapper\Packages下,然后在VS2010中就可以选择 .NET 2.0 的系统必备了。 原文:http://www.cnblogs.com/anjou/archive/2011/05/08/2040675.html
View DetailsPage.ClientScript.RegisterStartupScript 与 Page.ClientScript.RegisterClientScriptBlock 被用来注册脚本块。第一个是 RegisterStartupScript 方法。当您有一个想要在页面加载时启动的 JavaScript 函数时,最好使用该类。就此列举一例,在 Visual Studio 2005 中创建一个包含两个按钮的 ASP.NET 页面。Button1 和 Button2 分别为这两个按钮的 ID。然后,在 Page_Load 事件内部嵌入以下代码 C#:
1 |
Page.ClientScript.RegisterStartupScript(this.GetType(), "MyScript", "function AlertHello() { alert('你好,ASP.NET'); }", true); |
1 |
Button1.Attributes["onclick"] = "AlertHello()";Button2.Attributes["onclick"] = "AlertHello()"; |
RegisterStartupScript 方法的两个可能结构如下: • RegisterStartupScript (type, key, script) • RegisterStartupScript (type, key, script, script tag specification) 在上例中,您指定了类型 Me.GetType()、关键字及包含的脚本,然后是一个值为 True 的布尔值(以便 .NET 自动使用 <script> 标记将脚本嵌入 ASP.NET 页面中)。Page.ClientScript.RegisterStartupScript 与 Page.ClientScript.RegisterClientScriptBlock 之间的区别 主要区别在于:RegisterStartupScript 方法是将 JavaScript 嵌入到 ASP.NET 页面的底部,恰好位于关闭元素 </form> 的前面。RegisterClientScriptBlock方法是将 JavaScript 嵌入到页面中开启元素 <form> 的紧后面。那么,这有何不同呢?正如我们将要看到的,这有很大的不同。 就此列举一例,以下是在页面加载到浏览器时,将焦点置于该页面上的一个文本框中的方法 – 使用利用了 RegisterStartupScript 方法:
1 |
Page.ClientScript.RegisterStartupScript(this.GetType(), "Testing", "document.forms[0]['<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">txtText</strong>'].focus();", True) |
由于在浏览器运行到页面底部并执行此小段 JavaScript 时,就已生成了页面上的文本框,并已将其放到了页面中,因此,此方法运行正常。但是,如果不按照上述方法,而编写如下代码(使用 RegisterClientScriptBlock 方法):
1 |
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "Testing", "document.forms[0]['<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">txtText'</strong>].focus();", True) |
文本框控件将不会获得焦点,且会在页面上生成一个 JavaScript 错误(如图 1 所示)。 图 1. 执行 JavaScript 时出错 出错的原因在于,浏览器将先遇到 JavaScript,而后文本框才会出现在页面中。因此,JavaScript 将无法找到 txtText。 原文出处:http://blog.csdn.net/jiahello/archive/2009/06/29/4305855.aspx
View Detailsconst 的概念就是一个包含不能修改的值的变量。
1 |
常数表达式是在编译时可被完全计算的表达式。因此不能从一个变量中提取的值来初始化常量。如果 const int a = b+1;b是一个变量,显然不能再编译时就计算出结果,所以常量是不可以用变量来初始化的。 readonly 允许把一个字段设置成常量,但可以执行一些运算,可以确定它的初始值。因为 readonly 是在计算时执行的,当然它可以用某些变量初始化。readonly 是实例成员,所以不同的实例可以有不同的常量值,这使readonly更灵活。readonly 关键字与 const 关键字不同。1. const 字段只能在该字段的声明中初始化。 readonly 字段可以在声明或构造函数中初始化。因此,根据所使用的构造函数,readonly 字段可能具有不同的值。2. const 字段是编译时常数,而 readonly 字段可用于运行时常数。3. const 默认就是静态的,而 readonly 如果设置成静态的就必须显示声明。4.const 对于引用类型的常数,可能的值只能是 string 和 null。 readonly可以是任何类型总结const只能在初期就使用常量初始化好。对于每一次编译后的结果,const的值是固定的,而readonly的值是可以在运行的时候才确定值的~~FROM URL:<a href="http://zhidao.baidu.com/question/286719961.html">http://zhidao.baidu.com/question/286719961.html</a> |
PHP5.2.17 官方下载: http://windows.php.net/downloads/releases/php-5.4.3-Win32-VC9-x86.zip 首先安装好IIS7 安装的时候 要注意三个地方打得勾 注: CGI 会在IIS7+PHP_5.3.5的环境中用到 ISAPI扩展和ISAPI筛选器 用在IIS7+PHP_5.2.17 下面开始添加IIS的PHP支持 IIS7+PHP_5.3.5 1. 将下载回来的php_5.3.5解压到 C:\php目录(也可以放在其他地方,但是后面应该做相应修改) 2. 将php.ini-development改名为php.ini 3. 修改php.ini 查找date.timezone 修改为date.timezone = “Asia/Shanghai”(这里必须改,不然会出警告) 找到Windows Extensions开启 所需模块,如:php_curl.dll php_mysql.dll php_mysqli.dll php_xmlrpc.dll 只要去掉前面的 分号 保存就可以了 4. 添加<模块映射> 这里的路径按你的实际情况填写. 5. 在网站根目录新建一个phpinfo.php的文本文件 内容为: <?php phpinfo();?> 6. 测试,打开浏览器看结果:localhost/phpinfo.php,如果能看到类似下面的页面就说明你成功了: 好了,到现在 已经可以成功的运行PHP程序了. IIS7+PHP_5.2.17 于之前安装IIS的时候已经选上了isapi扩展和isapi筛选,这里就不用另外再添加角色服务了,直接开始 先修改php.ini文件.. 把c:\php下的php.ini-dist (需先设置显示扩展名)改名成php.ini,用记事本打开 找到extension_dir = “./”,然后把里面的./改成c:\php(根据自己的实际情况修改路径) 1. 添加应用程序池 2. 添加isapi和cgi限制 3. 添加isapi筛选器 4. 添加脚本映射 5. 测试(之前已经创建了phpinfo.php) 跟之前一样 打开localhost/phpinfo.php 查看效果:
View Details