FileZilla source code analysis 6

Source: Internet
Author: User
Tags ftp client filezilla

FileZillaIt is a fast and reliable FTP client and server-side open source code program with a variety of features and intuitive interfaces. This article analyzes the source code of FileZilla.

CListenSocket is a subclass of the CAsyncSocketEx class and is used to listen to port 21 at startup.

PListenSocket-> Create (nPort, SOCK_STREAM, FD_ACCEPT, NULL)

It can be seen that CListenSocket only processes the FD_ACCEPT message.

Take a look:

Void CListenSocket: OnAccept (int nErrorCode)

{

CAsyncSocketEx socket;

If (! Accept (socket) // The win API: accept method is called here, and a new connection is established. socket is the SOCKET of the new connection.

{

Int nError = WSAGetLastError ();

CStdString str;

Str. Format (_ T ("Failure in CListenSocket: OnAccept (% d)-call to CAsyncSocketEx: Accept failed, errorcode

% D "), nErrorCode, nError );

SendStatus (str, 1 );

SendStatus (_ T ("If you use a firewall, please check your firewall configuration"), 1 );

Return;

}

// Check the permission.

If (! AccessAllowed (socket ))

{

CStdStringA str = "550 No connections allowed from your IP \ r \ n ";

Socket. Send (str, str. GetLength ());

Return;

}

// Check whether the FileZilla Server is locked. That is, a new connection cannot be established.

If (m_bLocked)

{

CStdStringA str = "421 Server is locked, please try again later. \ r \ n ";

Socket. Send (str, str. GetLength ());

Return;

}

// Find the thread with the least load from the available threads below, that is, the thread with the least connection

Int minnum = 255*255*255;

CServerThread * pBestThread = 0 ;;

For (std: list : Iterator iter = m_pThreadList-> begin (); iter! = M_pThreadList-> end (); iter ++)

{

Int num = (* iter)-> GetNumConnections ();

If (num IsReady () // find the thread with the least connection

{

Minnum = num;

PBestThread = * iter;

If (! Num)

Break;

}

}

If (! PBestThread)

{

Char str [] = "421 Server offline .";

Socket. Send (str, strlen (str) + 1 );

Socket. Close ();

Return;

}

/* Disable Nagle algorithm. Most of the time single short strings get

* Transferred over the control connection. Waiting for additional data

* Where there will be most likely none affects performance.

*/

BOOL value = TRUE;

Socket. SetSockOpt (TCP_NODELAY, & value, sizeof (value), IPPROTO_TCP); // set not to use the Nagle algorithm. For details, see the Nagle algorithm section of the TCP protocol.

SOCKET sockethandle = socket. Detach ();

PBestThread-> AddSocket (sockethandle, m_ssl); // transfer the service thread for processing

CAsyncSocketEx: OnAccept (nErrorCode); // The default processing of the parent class is null.

}

It can be seen that the main task of CListenSocket: OnAccept is

1. Create a socket to receive new client connections

2. Perform some check settings, such as permission check and Nagle algorithm settings.

3. Find a backend service thread with the minimum load, which will handle the problem

To better understand the mechanism of the service thread CServerThread, let's first review how the service thread was created at that time.

Create () segment of the CServer class:

For (int I = 0; I <num; I ++) // here num is the number of service threads to be created

{

Int index = GetNextThreadNotificationID (); // obtain a thread ID, that is, in the thread array std: vector

Index in m_threadicationicationids

CServerThread * pThread = new CServerThread (WM_FILEZILLA_SERVERMSG + index );

M_ThreadNotificationIDs [index] = pThread;

// If the create_susponded flag is specified, the thread is created in a susponded state,

// And will not run until the ResumeThread function is called.

// If this value is zero, the thread runs immediately after creation.

If (pThread-> Create (THREAD_PRIORITY_NORMAL, create_suincluded ))

{

PThread-> ResumeThread ();

M_ThreadArray.push_back (pThread );

}

}

Let's take a look at pThread-> Create (THREAD_PRIORITY_NORMAL, create_suincluded). Since CServerThread inherits from CThread, it calls the create of CThread:

BOOL CThread: Create (int nPriority/* = THREAD_PRIORITY_NORMAL */, DWORD dwCreateFlags/* = 0 */)

{

M_hThread = CreateThread (0, 0, ThreadProc, this, dwCreateFlags, & m_dwThreadId); // call win api to create a thread

If (! M_hThread)

{

Delete this;

Return FALSE;

}

: SetThreadPriority (m_hThread, nPriority );

Return TRUE;

}

Note that when creating a thread, the initial state of the specified thread is create_suincluded.

After the creation is successful, call pThread-> ResumeThread ():

DWORD CThread: ResumeThread ()

{

// The following uses the win API: ResumeThread to start this thread. After the thread starts, it will automatically run to the ThreadProc function (specified during create)

DWORD res =: ResumeThread (m_hThread); // after this function, two threads are running, one is the main thread, and the other is the startup thread.

If (! M_started) // The main thread is running here. Because m_started is still 0, the following WaitForSingleObject is used for waiting.

{

WaitForSingleObject (m_hEventStarted, INFINITE );

}

Return res;

}

The newly started thread enters the ThreadProc function:

Dword winapi CThread: ThreadProc (LPVOID lpParameter)

{

// The parameter LPVOID lpParameter specified during CreateThread is this, that is, CThread

Return (CThread *) lpParameter)-> Run ();

}

Run the Run method:

DWORD CThread: Run ()

{

InitInstance (); // here, the CServerThread class overwrites this method, so it enters CServerThread: InitInstance () and carries out some initial memory variables.

Informatization

// The SetEvent function sets the specified event object to the signaled state.

SetEvent (m_hEventStarted); // set the event to active, so that the waiting main thread is revived and the CServer can be started.

M_started = true;

MSG msg;

While (GetMessage (& msg, 0, 0, 0) // enter the message loop of this thread

{

TranslateMessage (& msg );

If (! Msg. hwnd)

OnThreadMessage (msg. message, msg. wParam, msg. lParam); // call OnThreadMessage to process messages

DispatchMessage (& msg );

}

DWORD res = ExitInstance ();

Delete this;

Return res;

}

It can be seen that after the server is started and there is no message at the beginning, the CServerThread enters the block status at GetMessage (). Once a message arrives, the service thread will wake up and then

Process messages.

Next we return to the initial CListenSocket: OnAccept (), and finally call pBestThread-> AddSocket (sockethandle, m_ssl); // The forwarding service thread for processing.

Take a closer look at how the backend service thread processes messages.

Void CServerThread: AddSocket (SOCKET sockethandle, bool ssl)

{

// The method of the parent class is called.

PostThreadMessage (WM_FILEZILLA_THREADMSG, ssl? FTM_NEWSOCKET_SSL: FTM_NEWSOCKET, (LPARAM) sockethandle );

}

Next:

BOOL CThread: PostThreadMessage (UINT message, WPARAM wParam, LPARAM lParam)

{

// Posts a message to the message queue of the specified thread.

BOOL res =: PostThreadMessage (m_dwThreadId, message, wParam, lParam );;

ASSERT (res );

Return res;

}

PostThreadMessage is a windows API that sends a message to the thread m_dwThreadId,

According to the preceding code, the message WM_FILEZILLA_THREADMSG and the FTM_NEWSOCKET and sockethandle parameters are sent to the backend service thread with the minimum load,

Because the background thread is in the GetMessage () block at startup, the background thread wakes up and calls OnThreadMessage to process the WM_FILEZILLA_THREADMSG message.

Through the complete description in this article, you should know the source code of FileZilla and hope to help you!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.