首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >(八)高性能服务器架构设计总结3——以flamigo服务器代码为例

(八)高性能服务器架构设计总结3——以flamigo服务器代码为例

作者头像
范蠡
发布2018-07-25 16:04:10
6540
发布2018-07-25 16:04:10
举报

系列目录

第01篇 主线程与工作线程的分工

第02篇 Reactor模式

第03篇 一个服务器程序的架构介绍

第04篇 如何将socket设置为非阻塞模式

第05篇 如何编写高性能日志

第06篇 关于网络编程的一些实用技巧和细节

第07篇 开源一款即时通讯软件的源码

第08篇 高性能服务器架构设计总结1

第09篇 高性能服务器架构设计总结2

第10篇 高性能服务器架构设计总结3

第11篇 高性能服务器架构设计总结4

再看filezilla,一款ftp工具的服务器端,它采用的是Windows的WSAAsyncSelect模型(代码下载地址:https://github.com/baloonwj/filezilla):

  1//Processes event notifications sent by the sockets or the layers  
  2    static LRESULT CALLBACK WindowProc(HWND hWnd,
  3                                       UINT message,
  4                                       WPARAM wParam,
  5                                       LPARAM lParam)  
  6    {  
  7        if (message>=WM_SOCKETEX_NOTIFY)  
  8        {  
  9            //Verify parameters  
 10            ASSERT(hWnd);  
 11            CAsyncSocketExHelperWindow *pWnd=(CAsyncSocketExHelperWindow *)
 12                                              GetWindowLongPtr(hWnd, GWLP_USERDATA);  
 13            ASSERT(pWnd);  
 14            if (!pWnd)  
 15                return 0;  
 16            //Index is within socket storage  
 17            if (message < static_cast<UINT>(WM_SOCKETEX_NOTIFY+pWnd->m_nWindowDataSize)) 
 18            {  
 19                //Lookup socket and verify if it's valid  
 20                CAsyncSocketEx *pSocket=pWnd->m_pAsyncSocketExWindowData[message - WM_SOCKETEX_NOTIFY].m_pSocket;  
 21                SOCKET hSocket = wParam;  
 22                if (!pSocket)  
 23                    return 0;  
 24                if (hSocket == INVALID_SOCKET)  
 25                    return 0;  
 26                if (pSocket->m_SocketData.hSocket != hSocket)  
 27                    return 0;  
 28
 29                int nEvent = lParam & 0xFFFF;  
 30                int nErrorCode = lParam >> 16;  
 31
 32                //Dispatch notification  
 33                if (!pSocket->m_pFirstLayer) {  
 34                    //Dispatch to CAsyncSocketEx instance  
 35                    switch (nEvent)  
 36                    {  
 37                    case FD_READ:  
 38#ifndef NOSOCKETSTATES  
 39                        if (pSocket->GetState() == connecting && !nErrorCode)  
 40                        {  
 41                            pSocket->m_nPendingEvents |= FD_READ;  
 42                            break;  
 43                        }  
 44                        else if (pSocket->GetState() == attached)  
 45                            pSocket->SetState(connected);  
 46                        if (pSocket->GetState() != connected)  
 47                            break;  
 48
 49                        // Ignore further FD_READ events after FD_CLOSE has been received  
 50                        if (pSocket->m_SocketData.onCloseCalled)  
 51                            break;  
 52#endif //NOSOCKETSTATES  
 53
 54#ifndef NOSOCKETSTATES  
 55                        if (nErrorCode)  
 56                            pSocket->SetState(aborted);  
 57#endif //NOSOCKETSTATES  
 58                        if (pSocket->m_lEvent & FD_READ) {  
 59                            pSocket->OnReceive(nErrorCode);  
 60                        }  
 61                        break;  
 62                    case FD_FORCEREAD: //Forceread does not check if there's data waiting  
 63#ifndef NOSOCKETSTATES  
 64                        if (pSocket->GetState() == connecting && !nErrorCode)  
 65                        {  
 66                            pSocket->m_nPendingEvents |= FD_FORCEREAD;  
 67                            break;  
 68                        }  
 69                        else if (pSocket->GetState() == attached)  
 70                            pSocket->SetState(connected);  
 71                        if (pSocket->GetState() != connected)  
 72                            break;  
 73#endif //NOSOCKETSTATES  
 74                        if (pSocket->m_lEvent & FD_READ)  
 75                        {  
 76#ifndef NOSOCKETSTATES  
 77                            if (nErrorCode)  
 78                                pSocket->SetState(aborted);  
 79#endif //NOSOCKETSTATES  
 80                            pSocket->OnReceive(nErrorCode);  
 81                        }  
 82                        break;  
 83                    case FD_WRITE:  
 84#ifndef NOSOCKETSTATES  
 85                        if (pSocket->GetState() == connecting && !nErrorCode)  
 86                        {  
 87                            pSocket->m_nPendingEvents |= FD_WRITE;  
 88                            break;  
 89                        }  
 90                        else if (pSocket->GetState() == attached && !nErrorCode)  
 91                            pSocket->SetState(connected);  
 92                        if (pSocket->GetState() != connected)  
 93                            break;  
 94#endif //NOSOCKETSTATES  
 95                        if (pSocket->m_lEvent & FD_WRITE)  
 96                        {  
 97#ifndef NOSOCKETSTATES  
 98                            if (nErrorCode)  
 99                                pSocket->SetState(aborted);  
100#endif //NOSOCKETSTATES  
101                            pSocket->OnSend(nErrorCode);  
102                        }  
103                        break;  
104                    case FD_CONNECT:  
105#ifndef NOSOCKETSTATES  
106                        if (pSocket->GetState() == connecting)  
107                        {  
108                            if (nErrorCode && pSocket->m_SocketData.nextAddr)  
109                            {  
110                                if (pSocket->TryNextProtocol())  
111                                    break;  
112                            }  
113                            pSocket->SetState(connected);  
114                        }  
115                        else if (pSocket->GetState() == attached && !nErrorCode)  
116                            pSocket->SetState(connected);  
117#endif //NOSOCKETSTATES  
118                        if (pSocket->m_lEvent & FD_CONNECT)  
119                            pSocket->OnConnect(nErrorCode);  
120#ifndef NOSOCKETSTATES  
121                        if (!nErrorCode)  
122                        {  
123                            if ((pSocket->m_nPendingEvents&FD_READ) &&
124                                 pSocket->GetState() == connected)  
125                                pSocket->OnReceive(0);  
126                            if ((pSocket->m_nPendingEvents&FD_FORCEREAD) &&
127                                 pSocket->GetState() == connected)  
128                                pSocket->OnReceive(0);  
129                            if ((pSocket->m_nPendingEvents&FD_WRITE) &&
130                                 pSocket->GetState() == connected)  
131                                pSocket->OnSend(0);  
132                        }  
133                        pSocket->m_nPendingEvents = 0;  
134#endif  
135                        break;  
136                    case FD_ACCEPT:  
137#ifndef NOSOCKETSTATES  
138                        if (pSocket->GetState() != listening &&
139                            pSocket->GetState() != attached)  
140                            break;  
141#endif //NOSOCKETSTATES  
142                        if (pSocket->m_lEvent & FD_ACCEPT)  
143                            pSocket->OnAccept(nErrorCode);  
144                        break;  
145                    case FD_CLOSE:  
146#ifndef NOSOCKETSTATES  
147                        if (pSocket->GetState() != connected &&
148                            pSocket->GetState() != attached)  
149                            break;  
150
151                        // If there are still bytes left to read,
152                        // call OnReceive instead of  
153                        // OnClose and trigger a new OnClose  
154                        DWORD nBytes = 0;  
155                        if (!nErrorCode && pSocket->IOCtl(FIONREAD, &nBytes))  
156                        {  
157                            if (nBytes > 0)  
158                            {  
159                                // Just repeat message.  
160                                pSocket->ResendCloseNotify();  
161                                pSocket->m_SocketData.onCloseCalled = true;  
162                                pSocket->OnReceive(WSAESHUTDOWN);  
163                                break;  
164                            }  
165                        }  
166
167                        pSocket->SetState(nErrorCode ? aborted : closed);  
168#endif //NOSOCKETSTATES  
169                        pSocket->OnClose(nErrorCode);  
170                        break;  
171                    }  
172                }  
173                else //Dispatch notification to the lowest layer  
174                {  
175                    if (nEvent == FD_READ)  
176                    {  
177                        // Ignore further FD_READ events after FD_CLOSE has been received  
178                        if (pSocket->m_SocketData.onCloseCalled)  
179                            return 0;  
180
181                        DWORD nBytes;  
182                        if (!pSocket->IOCtl(FIONREAD, &nBytes))  
183                            nErrorCode = WSAGetLastError();  
184                        if (pSocket->m_pLastLayer)  
185                            pSocket->m_pLastLayer->CallEvent(nEvent, nErrorCode);  
186                    }  
187                    else if (nEvent == FD_CLOSE)  
188                    {  
189                        // If there are still bytes left to read,
190                        // call OnReceive instead of  
191                        // OnClose and trigger a new OnClose  
192                        DWORD nBytes = 0;  
193                        if (!nErrorCode && pSocket->IOCtl(FIONREAD, &nBytes))  
194                        {  
195                            if (nBytes > 0)  
196                            {  
197                                // Just repeat message.  
198                                pSocket->ResendCloseNotify();  
199                                if (pSocket->m_pLastLayer)  
200                                    pSocket->m_pLastLayer->CallEvent(FD_READ, 0);  
201                                return 0;  
202                            }  
203                        }  
204                        pSocket->m_SocketData.onCloseCalled = true;  
205                        if (pSocket->m_pLastLayer)  
206                            pSocket->m_pLastLayer->CallEvent(nEvent, nErrorCode);  
207                    }  
208                    else if (pSocket->m_pLastLayer)  
209                        pSocket->m_pLastLayer->CallEvent(nEvent, nErrorCode);  
210                }  
211            }  
212            return 0;  
213        }  
214        else if (message == WM_USER) //Notification event sent by a layer  
215        {  
216            //Verify parameters, lookup socket and notification message  
217            //Verify parameters  
218            ASSERT(hWnd);  
219            CAsyncSocketExHelperWindow *pWnd=(CAsyncSocketExHelperWindow *)
220                                              GetWindowLongPtr(hWnd, GWLP_USERDATA);  
221            ASSERT(pWnd);  
222            if (!pWnd)  
223                return 0;  
224             //Index is within socket storage  
225            if (wParam >= static_cast<UINT>(pWnd->m_nWindowDataSize))
226            {  
227                return 0;  
228            }  
229
230            CAsyncSocketEx *pSocket = pWnd->m_pAsyncSocketExWindowData[wParam].m_pSocket;  
231            CAsyncSocketExLayer::t_LayerNotifyMsg *pMsg = (CAsyncSocketExLayer::t_LayerNotifyMsg *)lParam;  
232            if (!pMsg || !pSocket || pSocket->m_SocketData.hSocket != pMsg->hSocket)  
233            {  
234                delete pMsg;  
235                return 0;  
236            }  
237            int nEvent=pMsg->lEvent&0xFFFF;  
238            int nErrorCode=pMsg->lEvent>>16;  
239
240            //Dispatch to layer  
241            if (pMsg->pLayer)  
242                pMsg->pLayer->CallEvent(nEvent, nErrorCode);  
243            else  
244            {  
245                //Dispatch to CAsyncSocketEx instance  
246                switch (nEvent)  
247                {  
248                case FD_READ:  
249#ifndef NOSOCKETSTATES  
250                    if (pSocket->GetState() == connecting && !nErrorCode)  
251                    {  
252                        pSocket->m_nPendingEvents |= FD_READ;  
253                        break;  
254                    }  
255                    else if (pSocket->GetState() == attached && !nErrorCode)  
256                        pSocket->SetState(connected);  
257                    if (pSocket->GetState() != connected)  
258                        break;  
259#endif //NOSOCKETSTATES  
260                    if (pSocket->m_lEvent & FD_READ)  
261                    {  
262#ifndef NOSOCKETSTATES  
263                        if (nErrorCode)  
264                            pSocket->SetState(aborted);  
265#endif //NOSOCKETSTATES  
266                        pSocket->OnReceive(nErrorCode);  
267                    }  
268                    break; 
269                //Forceread does not check if there's data waiting  
270                case FD_FORCEREAD:  
271#ifndef NOSOCKETSTATES  
272                    if (pSocket->GetState() == connecting && !nErrorCode)  
273                    {  
274                        pSocket->m_nPendingEvents |= FD_FORCEREAD;  
275                        break;  
276                    }  
277                    else if (pSocket->GetState() == attached && !nErrorCode)  
278                        pSocket->SetState(connected);  
279                    if (pSocket->GetState() != connected)  
280                        break;  
281#endif //NOSOCKETSTATES  
282                    if (pSocket->m_lEvent & FD_READ)  
283                    {  
284#ifndef NOSOCKETSTATES  
285                        if (nErrorCode)  
286                            pSocket->SetState(aborted);  
287#endif //NOSOCKETSTATES  
288                        pSocket->OnReceive(nErrorCode);  
289                    }  
290                    break;  
291                case FD_WRITE:  
292#ifndef NOSOCKETSTATES  
293                    if (pSocket->GetState() == connecting && !nErrorCode)  
294                    {  
295                        pSocket->m_nPendingEvents |= FD_WRITE;  
296                        break;  
297                    }  
298                    else if (pSocket->GetState() == attached && !nErrorCode)  
299                        pSocket->SetState(connected);  
300                    if (pSocket->GetState() != connected)  
301                        break;  
302#endif //NOSOCKETSTATES  
303                    if (pSocket->m_lEvent & FD_WRITE)  
304                    {  
305#ifndef NOSOCKETSTATES  
306                        if (nErrorCode)  
307                            pSocket->SetState(aborted);  
308#endif //NOSOCKETSTATES  
309                        pSocket->OnSend(nErrorCode);  
310                    }  
311                    break;  
312                case FD_CONNECT:  
313#ifndef NOSOCKETSTATES  
314                    if (pSocket->GetState() == connecting)  
315                        pSocket->SetState(connected);  
316                    else if (pSocket->GetState() == attached && !nErrorCode)  
317                        pSocket->SetState(connected);  
318#endif //NOSOCKETSTATES  
319                    if (pSocket->m_lEvent & FD_CONNECT)  
320                        pSocket->OnConnect(nErrorCode);  
321#ifndef NOSOCKETSTATES  
322                    if (!nErrorCode)  
323                    {  
324                        if (((pSocket->m_nPendingEvents&FD_READ) &&
325                              pSocket->GetState() == connected) &&
326                              (pSocket->m_lEvent & FD_READ))  
327                            pSocket->OnReceive(0);  
328                        if (((pSocket->m_nPendingEvents&FD_FORCEREAD) &&
329                              pSocket->GetState() == connected) &&
330                              (pSocket->m_lEvent & FD_READ))  
331                             pSocket->OnReceive(0);  
332                        if (((pSocket->m_nPendingEvents&FD_WRITE) &&
333                              pSocket->GetState() == connected) &&
334                              (pSocket->m_lEvent & FD_WRITE))  
335                            pSocket->OnSend(0);  
336                    }  
337                    pSocket->m_nPendingEvents = 0;  
338#endif //NOSOCKETSTATES  
339                    break;  
340                case FD_ACCEPT:  
341#ifndef NOSOCKETSTATES  
342                    if ((pSocket->GetState() == listening || pSocket->GetState() == attached) && (pSocket->m_lEvent & FD_ACCEPT))  
343#endif //NOSOCKETSTATES  
344                    {  
345                        pSocket->OnAccept(nErrorCode);  
346                    }  
347                    break;  
348                case FD_CLOSE:  
349#ifndef NOSOCKETSTATES  
350                    if ((pSocket->GetState() == connected ||
351                         pSocket->GetState() == attached) &&
352                         (pSocket->m_lEvent & FD_CLOSE))  
353                    {  
354                        pSocket->SetState(nErrorCode?aborted:closed);  
355#else  
356                    {  
357#endif //NOSOCKETSTATES  
358                        pSocket->OnClose(nErrorCode);  
359                    }  
360                    break;  
361                }  
362            }  
363            delete pMsg;  
364            return 0;  
365        }  
366        else if (message == WM_USER+1)  
367        {  
368            // WSAAsyncGetHostByName reply  
369
370            // Verify parameters  
371            ASSERT(hWnd);  
372            CAsyncSocketExHelperWindow *pWnd = (CAsyncSocketExHelperWindow *)
373                                                GetWindowLongPtr(hWnd, GWLP_USERDATA);  
374            ASSERT(pWnd);  
375            if (!pWnd)  
376                return 0;  
377
378            CAsyncSocketEx *pSocket = NULL;  
379            for (int i = 0; i < pWnd->m_nWindowDataSize; ++i) {  
380                pSocket = pWnd->m_pAsyncSocketExWindowData[i].m_pSocket;  
381                if (pSocket && pSocket->m_hAsyncGetHostByNameHandle &&  
382                    pSocket->m_hAsyncGetHostByNameHandle == (HANDLE)wParam &&  
383                    pSocket->m_pAsyncGetHostByNameBuffer)  
384                    break;  
385            }  
386            if (!pSocket || !pSocket->m_pAsyncGetHostByNameBuffer)  
387                return 0;  
388
389            int nErrorCode = lParam >> 16;  
390            if (nErrorCode) {  
391                pSocket->OnConnect(nErrorCode);  
392                return 0;  
393            }  
394
395            SOCKADDR_IN sockAddr{};  
396            sockAddr.sin_family = AF_INET;  
397            sockAddr.sin_addr.s_addr = ((LPIN_ADDR)((LPHOSTENT)pSocket->m_pAsyncGetHostByNameBuffer)->h_addr)->s_addr;  
398
399            sockAddr.sin_port = htons(pSocket->m_nAsyncGetHostByNamePort);  
400
401            BOOL res = pSocket->Connect((SOCKADDR*)&sockAddr, sizeof(sockAddr));  
402            delete [] pSocket->m_pAsyncGetHostByNameBuffer;  
403            pSocket->m_pAsyncGetHostByNameBuffer = 0;  
404            pSocket->m_hAsyncGetHostByNameHandle = 0;  
405
406            if (!res)  
407                if (GetLastError() != WSAEWOULDBLOCK)  
408                    pSocket->OnConnect(GetLastError());  
409            return 0;  
410        }  
411        else if (message == WM_USER + 2)  
412        {  
413            //Verify parameters, lookup socket and notification message  
414            //Verify parameters  
415            if (!hWnd)  
416                return 0;  
417
418            CAsyncSocketExHelperWindow *pWnd=(CAsyncSocketExHelperWindow *)
419                                              GetWindowLongPtr(hWnd, GWLP_USERDATA);  
420            if (!pWnd)  
421                return 0;  
422
423            if (wParam >= static_cast<UINT>(pWnd->m_nWindowDataSize)) //Index is within socket storage  
424                return 0;  
425
426            CAsyncSocketEx *pSocket = pWnd->m_pAsyncSocketExWindowData[wParam].m_pSocket;  
427            if (!pSocket)  
428                return 0;  
429
430            // Process pending callbacks  
431            std::list<t_callbackMsg> tmp;  
432            tmp.swap(pSocket->m_pendingCallbacks);  
433            pSocket->OnLayerCallback(tmp);  
434
435            for (auto & cb : tmp) {  
436                delete [] cb.str;  
437            }  
438        }  
439        else if (message == WM_TIMER)  
440        {  
441            if (wParam != 1)  
442                return 0;  
443
444            ASSERT(hWnd);  
445            CAsyncSocketExHelperWindow *pWnd=(CAsyncSocketExHelperWindow *)
446                                              GetWindowLongPtr(hWnd, GWLP_USERDATA);  
447            ASSERT(pWnd && pWnd->m_pThreadData);  
448            if (!pWnd || !pWnd->m_pThreadData)  
449                return 0;  
450
451            if (pWnd->m_pThreadData->layerCloseNotify.empty())  
452            {  
453                KillTimer(hWnd, 1);  
454                return 0;  
455            }  
456            CAsyncSocketEx* socket = pWnd->m_pThreadData->layerCloseNotify.front();  
457            pWnd->m_pThreadData->layerCloseNotify.pop_front();  
458            if (pWnd->m_pThreadData->layerCloseNotify.empty())  
459                KillTimer(hWnd, 1);  
460
461            if (socket)  
462                PostMessage(hWnd,
463                            socket->m_SocketData.nSocketIndex + WM_SOCKETEX_NOTIFY, 
464                            socket->m_SocketData.hSocket,
465                            FD_CLOSE);  
466            return 0;  
467        }  
468        return DefWindowProc(hWnd, message, wParam, lParam);  
469    } 

关于单个服务程序的框架,我已经介绍完了,如果你能完全理解我要表达的意思,我相信你也能构建出一套高性能服务程序来。

系列目录

第01篇 主线程与工作线程的分工

第02篇 Reactor模式

第03篇 一个服务器程序的架构介绍

第04篇 如何将socket设置为非阻塞模式

第05篇 如何编写高性能日志

第06篇 关于网络编程的一些实用技巧和细节

第07篇 开源一款即时通讯软件的源码

第08篇 高性能服务器架构设计总结1

第09篇 高性能服务器架构设计总结2

第10篇 高性能服务器架构设计总结3

第11篇 高性能服务器架构设计总结4

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-04-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 高性能服务器开发 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
即时通信 IM
即时通信 IM(Instant Messaging)基于腾讯二十余年的 IM 技术积累,支持Android、iOS、Mac、Windows、Web、H5、小程序平台且跨终端互通,低代码 UI 组件助您30分钟集成单聊、群聊、关系链、消息漫游、群组管理、资料管理、直播弹幕和内容审核等能力。适用于直播互动、电商带货、客服咨询、社交沟通、在线课程、企业办公、互动游戏、医疗健康等场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档