打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

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

系列目录

第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(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(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(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 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    }

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

由于公众号文章字数有限,您可以接着阅读下一篇:《服务器端编程心得(八)——高性能服务器架构设计总结4——以flamigo服务器代码为例》。

系列目录

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

第02篇 Reactor模式

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

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

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

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

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

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

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

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

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

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
16.5 MFC WinSocket实例
MFC中如何将焦点设置到指定控件上
CAsyncSocket,CSocket内幕及其用法
CSocket网络编程
VC++中有关句柄和指针及其转换
VC编程小技巧之框架窗口及其他
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服