Sophie

Sophie

distrib > Mageia > 7 > armv7hl > media > core-updates > by-pkgid > 6ed78e842caa17fd5c94d65d685685e0 > files > 99

qtscxml5-doc-5.12.6-1.mga7.noarch.rpm

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- ftpclient.qdoc -->
  <title>Qt SCXML FTP Client Example | Qt SCXML 5.12.6</title>
  <link rel="stylesheet" type="text/css" href="style/offline-simple.css" />
  <script type="text/javascript">
    document.getElementsByTagName("link").item(0).setAttribute("href", "style/offline.css");
    // loading style sheet breaks anchors that were jumped to before
    // so force jumping to anchor again
    setTimeout(function() {
        var anchor = location.hash;
        // need to jump to different anchor first (e.g. none)
        location.hash = "#";
        setTimeout(function() {
            location.hash = anchor;
        }, 0);
    }, 0);
  </script>
</head>
<body>
<div class="header" id="qtdocheader">
  <div class="main">
    <div class="main-rounded">
      <div class="navigationbar">
        <table><tr>
<td >Qt 5.12</td><td ><a href="qtscxml-index.html">Qt SCXML</a></td><td ><a href="examples-qtscxml.html">Qt SCXML Examples</a></td><td >Qt SCXML FTP Client Example</td></tr></table><table class="buildversion"><tr>
<td id="buildversion" width="100%" align="right"><a href="qtscxml-index.html">Qt 5.12.6 Reference Documentation</a></td>
        </tr></table>
      </div>
    </div>
<div class="content">
<div class="line">
<div class="content mainContent">
<div class="sidebar">
<div class="toc">
<h3><a name="toc">Contents</a></h3>
<ul>
<li class="level1"><a href="#running-the-example">Running the Example</a></li>
<li class="level1"><a href="#compiling-the-state-machine">Compiling the State Machine</a></li>
<li class="level1"><a href="#instantiating-the-state-machine">Instantiating the State Machine</a></li>
<li class="level1"><a href="#communicating-with-an-ftp-server">Communicating with an FTP Server</a></li>
</ul>
</div>
<div class="sidebar-content" id="sidebar-content"></div></div>
<h1 class="title">Qt SCXML FTP Client Example</h1>
<span class="subtitle"></span>
<!-- $$$ftpclient-brief -->
<p>Implements a simple FTP client using a state machine.</p>
<!-- @@@ftpclient -->
<!-- $$$ftpclient-description -->
<div class="descr"> <a name="details"></a>
<p><i>FTP Client</i> uses Qt SCXML to implement a FTP client that can communicate with a FTP service by sending FTP control messages translated from state machine events and by translating server replies into state machine events. The data received from the FTP server is printed on the console.</p>
<p><a href="https://tools.ietf.org/html/rfc959">RFC 959</a> specifies state charts for the command handling of the FTP client. They can be easily translated into SCXML to benefit from SCXML nested states. Connections between the client and server and data transfer are implemented by using C++. In addition, Qt signals and slots are used.</p>
<p>The state machine has the following states:</p>
<p class="centerAlign"><img src="images/ftpclient-statechart.png" alt="" /></p><ul>
<li><i>I</i> as the initial state.</li>
<li><i>B</i> for sending commands.</li>
<li><i>S</i> for success.</li>
<li><i>F</i> for failure.</li>
<li><i>W</i> for waiting for a reply.</li>
<li><i>P</i> for supplying a password upon server request.</li>
</ul>
<p>The state machine is specified in the <i>simpleftp.scxml</i> file and compiled into the <code>FtpClient</code> class that implements the logic of the FTP protocol. It reacts to user input and to replies from the control channel by changing states and sending external events. In addition, we implement a <code>FtpControlChannel</code> class and a <code>FtpDataChannel</code> class that handle TCP sockets and servers and convert line endings.</p>
<a name="running-the-example"></a>
<h2 id="running-the-example">Running the Example</h2>
<p>To run the example from Qt Creator, open the <b>Welcome</b> mode and select the example from <b>Examples</b>. For more information, visit Building and Running an Example.</p>
<a name="compiling-the-state-machine"></a>
<h2 id="compiling-the-state-machine">Compiling the State Machine</h2>
<p>We link against the Qt SCXML module by adding the following line to the <i>.pro</i> file:</p>
<pre class="cpp">

  QT = core scxml network

</pre>
<p>We then specify the state machine to compile:</p>
<pre class="cpp">

  STATECHARTS += simpleftp.scxml

</pre>
<p>The Qt SCXML Compiler, <code>qscxmlc</code>, is run automatically to generate <i>ftpclient.h</i> and <i>ftpclient.cpp</i>, and to add them to the <code>HEADERS</code> and <code>SOURCES</code> variables for compilation.</p>
<a name="instantiating-the-state-machine"></a>
<h2 id="instantiating-the-state-machine">Instantiating the State Machine</h2>
<p>We instantiate the generated <code>FtpClient</code> class, as well as the <code>FtpDataChannel</code> and <code>FtpControlChannel</code> classes in the <i>main.cpp</i> file:</p>
<pre class="cpp">

  <span class="preprocessor">#include &quot;ftpcontrolchannel.h&quot;</span>
  <span class="preprocessor">#include &quot;ftpdatachannel.h&quot;</span>
      ...
  <span class="type">int</span> main(<span class="type">int</span> argc<span class="operator">,</span> <span class="type">char</span> <span class="operator">*</span>argv<span class="operator">[</span><span class="operator">]</span>)
  {
      ...
      <span class="type">QCoreApplication</span> app(argc<span class="operator">,</span> argv);
      FtpClient ftpClient;
      FtpDataChannel dataChannel;
      FtpControlChannel controlChannel;
      ...

</pre>
<a name="communicating-with-an-ftp-server"></a>
<h2 id="communicating-with-an-ftp-server">Communicating with an FTP Server</h2>
<p>We print all data retrieved from the server on the console:</p>
<pre class="cpp">

      <span class="type">QObject</span><span class="operator">::</span>connect(<span class="operator">&amp;</span>dataChannel<span class="operator">,</span> <span class="operator">&amp;</span>FtpDataChannel<span class="operator">::</span>dataReceived<span class="operator">,</span>
                       <span class="operator">[</span><span class="operator">]</span>(<span class="keyword">const</span> <span class="type">QByteArray</span> <span class="operator">&amp;</span>data) {
          std<span class="operator">::</span>cout <span class="operator">&lt;</span><span class="operator">&lt;</span> data<span class="operator">.</span>constData();
      });

</pre>
<p>We translate server replies into state machine events:</p>
<pre class="cpp">

      <span class="type">QObject</span><span class="operator">::</span>connect(<span class="operator">&amp;</span>controlChannel<span class="operator">,</span> <span class="operator">&amp;</span>FtpControlChannel<span class="operator">::</span>reply<span class="operator">,</span> <span class="operator">&amp;</span>ftpClient<span class="operator">,</span>
                       <span class="operator">[</span><span class="operator">&amp;</span>ftpClient<span class="operator">]</span>(<span class="type">int</span> code<span class="operator">,</span> <span class="keyword">const</span> <span class="type">QString</span> <span class="operator">&amp;</span>parameters) {
          ftpClient<span class="operator">.</span>submitEvent(<span class="type">QString</span>(<span class="string">&quot;reply.%1xx&quot;</span>)
                                <span class="operator">.</span>arg(code <span class="operator">/</span> <span class="number">100</span>)<span class="operator">,</span> parameters);
      });

</pre>
<p>We translate commands from the state machine into FTP control messages:</p>
<pre class="cpp">

      ftpClient<span class="operator">.</span>connectToEvent(<span class="string">&quot;submit.cmd&quot;</span><span class="operator">,</span> <span class="operator">&amp;</span>controlChannel<span class="operator">,</span>
                               <span class="operator">[</span><span class="operator">&amp;</span>controlChannel<span class="operator">]</span>(<span class="keyword">const</span> <span class="type"><a href="qscxmlevent.html">QScxmlEvent</a></span> <span class="operator">&amp;</span>event) {
          controlChannel<span class="operator">.</span>command(event<span class="operator">.</span>name()<span class="operator">.</span>mid(<span class="number">11</span>)<span class="operator">.</span>toUtf8()<span class="operator">,</span>
                                 event<span class="operator">.</span>data()<span class="operator">.</span>toMap()<span class="operator">[</span><span class="string">&quot;params&quot;</span><span class="operator">]</span><span class="operator">.</span>toByteArray());
      });

</pre>
<p>We send commands to log into the FTP server as an anonymous user, to announce a port for the data connection, and to retrive a file:</p>
<pre class="cpp">

      <span class="type">QList</span><span class="operator">&lt;</span>Command<span class="operator">&gt;</span> commands({
          {<span class="string">&quot;cmd.USER&quot;</span><span class="operator">,</span> <span class="string">&quot;anonymous&quot;</span>}<span class="operator">,</span><span class="comment">// login</span>
          {<span class="string">&quot;cmd.PORT&quot;</span><span class="operator">,</span> <span class="string">&quot;&quot;</span>}<span class="operator">,</span>         <span class="comment">// announce port for data connection,</span>
                                    <span class="comment">// args added below.</span>
          {<span class="string">&quot;cmd.RETR&quot;</span><span class="operator">,</span> file}        <span class="comment">// retrieve a file</span>
      });

</pre>
<p>We specify that the FTP client should send the next command when entering the <i>B</i> state:</p>
<pre class="cpp">

      ftpClient<span class="operator">.</span>connectToState(<span class="string">&quot;B&quot;</span><span class="operator">,</span> <span class="type"><a href="qscxmlstatemachine.html">QScxmlStateMachine</a></span><span class="operator">::</span>onEntry(<span class="operator">[</span><span class="operator">&amp;</span><span class="operator">]</span>() {
          <span class="keyword">if</span> (commands<span class="operator">.</span>isEmpty()) {
              app<span class="operator">.</span>quit();
              <span class="keyword">return</span>;
          }
          Command command <span class="operator">=</span> commands<span class="operator">.</span>takeFirst();
          qDebug() <span class="operator">&lt;</span><span class="operator">&lt;</span> <span class="string">&quot;Posting command&quot;</span> <span class="operator">&lt;</span><span class="operator">&lt;</span> command<span class="operator">.</span>cmd <span class="operator">&lt;</span><span class="operator">&lt;</span> command<span class="operator">.</span>args;
          ftpClient<span class="operator">.</span>submitEvent(command<span class="operator">.</span>cmd<span class="operator">,</span> command<span class="operator">.</span>args);
      }));

</pre>
<p>We specify that the FTP client should send an empty string as a password if the server asks for one:</p>
<pre class="cpp">

      ftpClient<span class="operator">.</span>connectToState(<span class="string">&quot;P&quot;</span><span class="operator">,</span> <span class="type"><a href="qscxmlstatemachine.html">QScxmlStateMachine</a></span><span class="operator">::</span>onEntry(<span class="operator">[</span><span class="operator">&amp;</span>ftpClient<span class="operator">]</span>() {
          qDebug() <span class="operator">&lt;</span><span class="operator">&lt;</span> <span class="string">&quot;Sending password&quot;</span>;
          ftpClient<span class="operator">.</span>submitEvent(<span class="string">&quot;cmd.PASS&quot;</span><span class="operator">,</span> <span class="type">QString</span>());
      }));

</pre>
<p>Finally, we connect to the FTP server specified as the first argument of the method and retrieve the file specified as the second argument:</p>
<pre class="cpp">

      controlChannel<span class="operator">.</span>connectToServer(server);
      <span class="type">QObject</span><span class="operator">::</span>connect(<span class="operator">&amp;</span>controlChannel<span class="operator">,</span> <span class="operator">&amp;</span>FtpControlChannel<span class="operator">::</span>opened<span class="operator">,</span>
                       <span class="operator">[</span><span class="operator">&amp;</span><span class="operator">]</span>(<span class="keyword">const</span> <span class="type">QHostAddress</span> <span class="operator">&amp;</span>address<span class="operator">,</span> <span class="type">int</span>) {
          dataChannel<span class="operator">.</span>listen(address);
          commands<span class="operator">[</span><span class="number">1</span><span class="operator">]</span><span class="operator">.</span>args <span class="operator">=</span> dataChannel<span class="operator">.</span>portspec();
          ftpClient<span class="operator">.</span>start();
      });

</pre>
<p>For example, the following invocation prints the specified file from the specified server: <code>ftpclient &lt;server&gt; &lt;file&gt;</code>.</p>
<p>Files:</p>
<ul>
<li><a href="qtscxml-ftpclient-ftpclient-pro.html">ftpclient/ftpclient.pro</a></li>
<li><a href="qtscxml-ftpclient-ftpcontrolchannel-cpp.html">ftpclient/ftpcontrolchannel.cpp</a></li>
<li><a href="qtscxml-ftpclient-ftpcontrolchannel-h.html">ftpclient/ftpcontrolchannel.h</a></li>
<li><a href="qtscxml-ftpclient-ftpdatachannel-cpp.html">ftpclient/ftpdatachannel.cpp</a></li>
<li><a href="qtscxml-ftpclient-ftpdatachannel-h.html">ftpclient/ftpdatachannel.h</a></li>
<li><a href="qtscxml-ftpclient-main-cpp.html">ftpclient/main.cpp</a></li>
<li><a href="qtscxml-ftpclient-simpleftp-cpp.html">ftpclient/simpleftp.cpp</a></li>
<li><a href="qtscxml-ftpclient-simpleftp-h.html">ftpclient/simpleftp.h</a></li>
<li><a href="qtscxml-ftpclient-simpleftp-scxml.html">ftpclient/simpleftp.scxml</a></li>
</ul>
</div>
<!-- @@@ftpclient -->
        </div>
       </div>
   </div>
   </div>
</div>
<div class="footer">
   <p>
   <acronym title="Copyright">&copy;</acronym> 2019 The Qt Company Ltd.
   Documentation contributions included herein are the copyrights of
   their respective owners.<br/>    The documentation provided herein is licensed under the terms of the    <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation    License version 1.3</a> as published by the Free Software Foundation.<br/>    Qt and respective logos are trademarks of The Qt Company Ltd.     in Finland and/or other countries worldwide. All other trademarks are property
   of their respective owners. </p>
</div>
</body>
</html>