Socket通信.docx
- 文档编号:12891559
- 上传时间:2023-04-22
- 格式:DOCX
- 页数:20
- 大小:201.06KB
Socket通信.docx
《Socket通信.docx》由会员分享,可在线阅读,更多相关《Socket通信.docx(20页珍藏版)》请在冰豆网上搜索。
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
usingSystem.Collections.Generic;
usingSystem.Net.Sockets;
//Thisclasscreatesasinglelargebufferwhichcanbedividedup
//andassignedtoSocketAsyncEventArgsobjectsforusewitheach
//socketI/Ooperation.
//Thisenablesbuffferstobeeasilyreusedandguardsagainst
//fragmentingheapmemory.
//
//TheoperationsexposedontheBufferManagerclassarenotthreadsafe.
classBufferManager
{
intm_numBytes;//thetotalnumberofbytescontrolledbythebufferpool
byte[]m_buffer;//theunderlyingbytearraymaintainedbytheBufferManager
Stack
intm_currentIndex;
intm_bufferSize;
publicBufferManager(inttotalBytes,intbufferSize)
{
m_numBytes=totalBytes;
m_currentIndex=0;
m_bufferSize=bufferSize;
m_freeIndexPool=newStack
}
//Allocatesbufferspaceusedbythebufferpool
publicvoidInitBuffer()
{
//createonebiglargebufferanddividethat
//outtoeachSocketAsyncEventArgobject
m_buffer=newbyte[m_numBytes];
}
//Assignsabufferfromthebufferpooltothe
//specifiedSocketAsyncEventArgsobject
//
//
publicboolSetBuffer(SocketAsyncEventArgsargs)
{
if(m_freeIndexPool.Count>0)
{
args.SetBuffer(m_buffer,m_freeIndexPool.Pop(),m_bufferSize);
}
else
{
if((m_numBytes-m_bufferSize) { returnfalse; } args.SetBuffer(m_buffer,m_currentIndex,m_bufferSize); m_currentIndex+=m_bufferSize; } returntrue; } //RemovesthebufferfromaSocketAsyncEventArgobject. //Thisfreesthebufferbacktothebufferpool publicvoidFreeBuffer(SocketAsyncEventArgsargs) { m_freeIndexPool.Push(args.Offset); args.SetBuffer(null,0,0); } } SocketAsyncEventArgsPool usingSystem; usingSystem.Collections.Generic; usingSystem.Net.Sockets; //RepresentsacollectionofreusableSocketAsyncEventArgsobjects. classSocketAsyncEventArgsPool { Stack //Initializestheobjectpooltothespecifiedsize // //The"capacity"parameteristhemaximumnumberof //SocketAsyncEventArgsobjectsthepoolcanhold publicSocketAsyncEventArgsPool(intcapacity) { m_pool=newStack } //AddaSocketAsyncEventArginstancetothepool // //The"item"parameteristheSocketAsyncEventArgsinstance //toaddtothepool publicvoidPush(SocketAsyncEventArgsitem) { if(item==null){thrownewArgumentNullException("ItemsaddedtoaSocketAsyncEventArgsPoolcannotbenull");} lock(m_pool) { m_pool.Push(item); } } //RemovesaSocketAsyncEventArgsinstancefromthepool //andreturnstheobjectremovedfromthepool publicSocketAsyncEventArgsPop() { lock(m_pool) { returnm_pool.Pop(); } } //ThenumberofSocketAsyncEventArgsinstancesinthepool publicintCount { get{returnm_pool.Count;} } } usingSystem; usingSystem.Collections.Generic; usingSystem.Net.Sockets; //RepresentsacollectionofreusableSocketAsyncEventArgsobjects. classSocketAsyncEventArgsPool { Stack //Initializestheobjectpooltothespecifiedsize // //The"capacity"parameteristhemaximumnumberof //SocketAsyncEventArgsobjectsthepoolcanhold publicSocketAsyncEventArgsPool(intcapacity) { m_pool=newStack } //AddaSocketAsyncEventArginstancetothepool // //The"item"parameteristheSocketAsyncEventArgsinstance //toaddtothepool publicvoidPush(SocketAsyncEventArgsitem) { if(item==null){thrownewArgumentNullException("ItemsaddedtoaSocketAsyncEventArgsPoolcannotbenull");} lock(m_pool) { m_pool.Push(item); } } //RemovesaSocketAsyncEventArgsinstancefromthepool //andreturnstheobjectremovedfromthepool publicSocketAsyncEventArgsPop() { lock(m_pool) { returnm_pool.Pop(); } } //ThenumberofSocketAsyncEventArgsinstancesinthepool publicintCount { get{returnm_pool.Count;} } } Server usingSystem; usingSystem.Threading; usingSystem.Net.Sockets; usingSystem.Net; usingSystem.Text; //Implementstheconnectionlogicforthesocketserver. //Afteracceptingaconnection,alldatareadfromtheclient //issentbacktotheclient.Thereadandechobacktotheclientpattern //iscontinueduntiltheclientdisconnects. classServer { privateintm_numConnections;//themaximumnumberofconnectionsthesampleisdesignedtohandlesimultaneously privateintm_receiveBufferSize;//buffersizetouseforeachsocketI/Ooperation BufferManagerm_bufferManager;//representsalargereusablesetofbuffersforallsocketoperations constintopsToPreAlloc=2;//read,write(don'tallocbufferspaceforaccepts) SocketlistenSocket;//thesocketusedtolistenforincomingconnectionrequests //poolofreusableSocketAsyncEventArgsobjectsforwrite,readandacceptsocketoperations SocketAsyncEventArgsPoolm_readWritePool; intm_totalBytesRead;//counterofthetotal#bytesreceivedbytheserver intm_numConnectedSockets;//thetotalnumberofclientsconnectedtotheserver Semaphorem_maxNumberAcceptedClients; //Createanuninitializedserverinstance. //Tostarttheserverlisteningforconnectionrequests //calltheInitmethodfollowedbyStartmethod // // // publicServer(intnumConnections,intreceiveBufferSize) { m_totalBytesRead=0; m_numConnectedSockets=0; m_numConnections=numConnections; m_receiveBufferSize=receiveBufferSize; //allocatebufferssuchthatthemaximumnumberofsocketscanhaveoneoutstandingreadand //writepostedtothesocketsimultaneously m_bufferManager=newBufferManager(receiveBufferSize*numConnections*opsToPreAlloc, receiveBufferSize); m_readWritePool=newSocketAsyncEventArgsPool(numConnections); m_maxNumberAcceptedClients=newSemaphore(numConnections,numConnections); } //Initializestheserverbypreallocatingreusablebuffersand //contextobjects.Theseobjectsdonotneedtobepreallocated //orreused,butitisdonethiswaytoillustratehowtheAPIcan //easilybeusedtocreatereusableobjectstoincreaseserverperformance. // publicvoidInit() { //AllocatesonelargebytebufferwhichallI/Ooperationsuseapieceof.Thisgaurds //againstmemoryfragmentation m_bufferManager.InitBuffer(); //preallocatepoolofSocketAsyncEventArgsobjects SocketAsyncEventArgsreadWriteEventArg; for(inti=0;i { //Pre-allocateasetofreusableSocketAsyncEventArgs readWriteEventArg=newSocketAsyncEventArgs(); readWriteEventArg.Completed+=newEventHandler readWriteEventArg.UserToken=newAsyncUserToken(); //assignabytebufferfromthebufferpooltotheSocketAsyncEventArgobject m_bufferManager.SetBuffer(readWriteEventArg); //addSocketAsyncEventArgtothepool m_readWritePool.Push(readWriteEventArg); } } //Startstheserversuchthatitislisteningfor //incomingconnectionrequests. // // //forconnectionrequestson publicvoidStart(IPEndPointlocalEndPoint) { //createthesocketwhichlistensforincomingconnections listenSocket=newSocket(localEndPoint.AddressFamily,SocketType.Stream,ProtocolType.Tcp); listenSocket.Bind(localEndPoint); //starttheserverwithalistenbacklogof100connections listenSocket.Listen(100); //postacceptsonthelisteningsocket StartAccept(null); //Console.WriteLine("{0}connectedsocketswithoneoutstandingreceivepostedtoeach....pressanykey",m_outstandingReadCount); Console.WriteLine("Pressanykeytoterminatetheserverprocess...."); Console.ReadKey(); } //Beginsanoperationtoacceptaconnectionrequestfromtheclient // // //theacceptoperationontheserver'slisteningsocket publicvoidStartAccept(SocketAsyncEventArgsacceptEventArg) { if(acceptEventArg==null) { acc
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Socket 通信