Sophie

Sophie

distrib > Mandriva > current > i586 > media > main-updates > by-pkgid > ed376d6842ea322c25405e7c23b3bc12 > files > 62

libcommoncpp-devel-1.8.0-5.1mdv2010.1.i586.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<title>GNU CommonC++: SampleSocketPort.cpp</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<link href="doxygen.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<!-- Generated by Doxygen 1.6.3 -->
<div class="navigation" id="top">
  <div class="tabs">
    <ul>
      <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
      <li><a href="namespaces.html"><span>Namespaces</span></a></li>
      <li><a href="annotated.html"><span>Classes</span></a></li>
      <li><a href="files.html"><span>Files</span></a></li>
      <li><a href="examples.html"><span>Examples</span></a></li>
    </ul>
  </div>
</div>
<div class="contents">
<h1>SampleSocketPort.cpp</h1><div class="fragment"><pre class="fragment">
<span class="preprocessor">#include &quot;SampleSocketPort.h&quot;</span>

SampleSocketPort::SampleSocketPort(SocketService *pService, TCPSocket &amp; tcpSocket) :
                                SocketPort(pService, tcpSocket) {
        <a name="a0"></a><a class="code" href="namespaceost.html#a3c74a1a40c359fd349f3e3e1b96ebfc7" title="Transport Protocol Ports.">tpport_t</a> port;
        <a name="a1"></a><a class="code" href="address_8h.html#a5eba36aa908d5a479c8ba7d0bc4512b1">InetHostAddress</a> ia = getPeer( &amp; port );
        cerr &lt;&lt; <span class="stringliteral">&quot;connecting from &quot;</span> &lt;&lt; ia.getHostname() &lt;&lt; <span class="stringliteral">&quot;:&quot;</span> &lt;&lt; port &lt;&lt; endl;

        <span class="comment">// Set up non-blocking reads</span>
        setCompletion( <span class="keyword">false</span> );

        <span class="comment">//1.9.3 THIS LINE DOES NOT SEEM TO BE REQUIRED ANYMORE!</span>
        <span class="comment">//This sorts out a bug which prevents connections after a disconnect</span>
        <span class="comment">//setDetectOutput(true);</span>

        m_bOpen = <span class="keyword">true</span>;
        m_bDoDisconnect = <span class="keyword">false</span>;
        m_bTimedOut = <span class="keyword">false</span>;
        m_bReceptionStarted = <span class="keyword">false</span>;
        m_nLastBytesAvail = 0;
        m_pBuf = <span class="keyword">new</span> <span class="keywordtype">char</span>[MAX_RXBUF];
}


SampleSocketPort::~SampleSocketPort()
{
        endSocket();
        <span class="keyword">delete</span> [] m_pBuf;
}

<span class="keywordtype">void</span> SampleSocketPort::pending(<span class="keywordtype">void</span>)
{
<span class="comment">//cerr &lt;&lt; &quot;Pending called &quot; &lt;&lt; endl;</span>
        <span class="keywordflow">if</span>(!m_bOpen)
                <span class="keywordflow">return</span>;

        <span class="comment">// Read all available bytes into our buffer</span>
        <span class="keywordtype">int</span> nBytesAvail = <a name="a2"></a><a class="code" href="classost_1_1_buffer.html#a2066fdf67ab3b6727be90a51fc5c4d64">peek</a>(m_pBuf, MAX_RXBUF);
<span class="comment">//cerr &lt;&lt; &quot;Pending .. &quot; &lt;&lt; nBytesAvail &lt;&lt; endl;</span>

        <span class="keywordflow">if</span>(!m_bReceptionStarted)
        {       <span class="comment">//Start the receive timer</span>
                ResetReadTimeout(MAX_RXTIMEOUT);        <span class="comment">//Got &#39;n&#39; seconds to get all the data else we timeout</span>
                m_bReceptionStarted = <span class="keyword">true</span>;
        }
        <span class="keywordflow">else</span> {
                <span class="keywordflow">if</span>(m_bTimedOut) <span class="comment">//The receive timer has expired...this is a timeout condition</span>
                {
                        ResetReadTimeout(MAX_RXTIMEOUT); <span class="comment">//Clear the timeout flag</span>
                        m_nLastBytesAvail = 0;          <span class="comment">//Reset the flags</span>
                        m_bReceptionStarted = <span class="keyword">false</span>;
                        OnRxTimeout();  <span class="comment">//Do whatever &#39;we&#39; do for a timeout (probably a flush or disconnect)...</span>
                        <span class="keywordflow">return</span>;
                }
        }

        <span class="keywordflow">if</span>(m_nLastBytesAvail == nBytesAvail)    <span class="comment">//Check if any more data has been received since last time</span>
        {                                                                               <span class="comment">//No point in parsing unless this has changed!</span>
                <span class="comment">//Maybe yield in here!</span>
                <span class="comment">//Thread::yield();</span>
                <span class="keywordflow">if</span>(nBytesAvail == 0)            <span class="comment">//If we have been called with 0 bytes available (twice now)</span>
                {                                                       <span class="comment">//a disconnection has occurred</span>
                        <span class="keywordflow">if</span>(!m_bDoDisconnect) {
                                CloseSocket();  <span class="comment">//Force the close</span>
                        }
                }
                <span class="keywordflow">return</span>;
        }

        <span class="comment">//Depending on your application you may want to attempt to process the extra data</span>
        <span class="comment">//(or change your MAX_RXBUF).</span>
        <span class="comment">//</span>
        <span class="comment">//Here I just flush the whole lot, because I assume a &#39;legal&#39; client wont send more than</span>
        <span class="comment">//we can receive....maybe someone is trying to flood / overrun us!</span>
        <span class="keywordflow">if</span>(nBytesAvail &gt; MAX_RXBUF) {
                cerr &lt;&lt; <span class="stringliteral">&quot;TCP/IP overflow...&quot;</span> &lt;&lt; endl;
                FlushRxData();
                m_nLastBytesAvail = 0;
                m_bReceptionStarted = <span class="keyword">false</span>;
                <span class="keywordflow">return</span>;
        }
        m_nLastBytesAvail = nBytesAvail;

        <span class="comment">//In this loop you may parse the received data to determine whether a whole</span>
        <span class="comment">//&#39;packet&#39; has arrived. What you do in here depends on what data you are sending.</span>
        <span class="comment">//Here we will just look for a /r/n terminator sequence.</span>
        <span class="keywordflow">for</span>(<span class="keywordtype">int</span> i=0; i &lt; nBytesAvail; i++) {

<span class="comment">/***************************SHOULD BE CUSTOMISED*******************/</span>

                <span class="keywordflow">if</span>(m_pBuf[i] == <span class="charliteral">&#39;\r&#39;</span>) {
                        <span class="keywordflow">if</span>(i+1 &lt; nBytesAvail) {
                                <span class="keywordflow">if</span>(m_pBuf[i+1] == <span class="charliteral">&#39;\n&#39;</span>)
                                {       <span class="comment">//Terminator sequence found</span>

                                        <span class="comment">/**************************************************************/</span>
                                        <span class="comment">// COMPULSORY ... Clear the flag and count..</span>
                                        <span class="comment">// do this when you have received a good packet</span>
                                        m_nLastBytesAvail = 0;
                                        m_bReceptionStarted = <span class="keyword">false</span>;
                                        <span class="comment">/**************************************************************/</span>

                                        <span class="comment">// Now receive the data into a buffer and call our receive function</span>
                                        <span class="keywordtype">int</span> nLen = i+2;
                                        <span class="keywordtype">char</span> *pszRxData = <span class="keyword">new</span> <span class="keywordtype">char</span>[nLen+1];     <span class="comment">//Allow space for terminator</span>
                                        receive(pszRxData, nLen);               <span class="comment">//Receive the data</span>
                                        pszRxData[nLen] = <span class="charliteral">&#39;\0&#39;</span>;         <span class="comment">//Terminate it</span>
                                        OnDataReceived(pszRxData, nLen);
                                        <span class="keyword">delete</span> [] pszRxData;
                                        <span class="keywordflow">return</span>;
                                }
                        }
                }
<span class="comment">/***************************END CUSTOMISATION*******************/</span>

        }
}

<span class="keywordtype">void</span> SampleSocketPort::disconnect(<span class="keywordtype">void</span>)
{
        <span class="keywordflow">if</span>(m_bOpen) {
                m_bDoDisconnect = <span class="keyword">true</span>;
                CloseSocket();
        }
}

<span class="keywordtype">void</span> SampleSocketPort::expired(<span class="keywordtype">void</span>)
{
        <span class="keywordflow">if</span>(m_bDoDisconnect &amp;&amp; m_bOpen) {
                CloseSocket();
        }
        <span class="keywordflow">else</span> <span class="keywordflow">if</span>(m_bOpen &amp;&amp; m_bReceptionStarted) {
                <span class="comment">//Timer must have expired because the rx data has not all been received</span>
                m_bTimedOut = <span class="keyword">true</span>;
        }
}


<span class="keywordtype">bool</span> SampleSocketPort::CloseSocket(<span class="keywordtype">void</span>)
{
        <span class="keywordflow">if</span>(m_bOpen &amp;&amp; m_bDoDisconnect)
        {                                                                       <span class="comment">//This is where the disconnection really occurs</span>
                m_bOpen = <span class="keyword">false</span>;                                <span class="comment">//If m_bDoDisconnect == true we know this has been called</span>
                OnConnectionClosed();                   <span class="comment">//through the timer, so &#39;delete this&#39; is safe!</span>
                <span class="keyword">delete</span> <span class="keyword">this</span>;
        }
        <span class="keywordflow">else</span> <span class="keywordflow">if</span>(m_bOpen) {
                m_bDoDisconnect = <span class="keyword">true</span>;                 <span class="comment">//Just set the timer and the flag so we can</span>
                setTimer(DISCONNECT_MS);                <span class="comment">//disconnect safely, in DISCONNECT_MS</span>
        }
        <span class="keywordflow">return</span>(<span class="keyword">true</span>);
}


ssize_t SampleSocketPort::DoSend(<span class="keywordtype">void</span> *buf, <span class="keywordtype">size_t</span> len)
{
        <span class="comment">//If we are disconnecting, just pretend all the bytes were sent</span>
        <span class="keywordflow">if</span>(m_bDoDisconnect)
                <span class="keywordflow">return</span>((ssize_t)len);

        ssize_t nSent = send(buf, len);
        <span class="keywordflow">while</span>(!isPending(Socket::pendingOutput, 0))             <span class="comment">//Wait for output to complete</span>
        {
                <span class="keywordflow">if</span>(m_bDoDisconnect || !m_bOpen) {
                        <span class="comment">//If we are disconnecting, just pretend all the bytes were sent</span>
                        <span class="keywordflow">return</span>((ssize_t)len);
                }
                <span class="comment">//I like to yield whenever waiting for things...</span>
                <span class="comment">//this is optional and may not suit your implementation!</span>
                Thread::yield();
        }
        <span class="keywordflow">return</span>(nSent);
}

<span class="keywordtype">bool</span> SampleSocketPort::WriteData(<span class="keyword">const</span> <span class="keywordtype">char</span> *szTxData, <span class="keyword">const</span> <span class="keywordtype">size_t</span> nByteCount)
{
        <span class="comment">//First calculate how many bytes we are to send</span>
        ssize_t nLen = nByteCount;

        <span class="keywordflow">if</span>(nLen == -1)
                nLen = (ssize_t)strlen(szTxData);

        <span class="keywordtype">size_t</span> nBytesToSend = nLen;

        <span class="keywordflow">while</span>(m_bOpen &amp;&amp; nLen) {
                nLen -= DoSend((<span class="keywordtype">void</span> *)&amp;(szTxData[nBytesToSend - nLen]), nLen);
        }

<span class="comment">//      If we are sending a terminator.....uncomment the following lines</span>
<span class="comment">//      char chTerminator = &#39;\n&#39;;</span>
<span class="comment">//      while(DoSend((void *)&amp;chTerminator, 1) != 1);</span>

        <span class="keywordflow">return</span>(<span class="keyword">true</span>);
}



<span class="preprocessor">#define WITH_EXAMPLE</span>
<span class="preprocessor"></span>
<span class="preprocessor">#ifdef WITH_EXAMPLE</span>
<span class="preprocessor"></span>

<span class="comment">/************ THE FOLLOWING CODE DEMONSTRATES THE USE OF THE ABOVE CLASS ********************</span>
<span class="comment"> ****</span>
<span class="comment"> ****   To test it, compile with:</span>
<span class="comment"> ****</span>
<span class="comment"> ****   g++ SampleSocketPort.cpp -lccgnu -lpthread -ldl -oSampleSocketPort -ggdb -I/usr/local/include/cc++/</span>
<span class="comment"> ****   Run the program.</span>
<span class="comment"> ****</span>
<span class="comment"> ****   From another terminal telnet to port 3999 of the server</span>
<span class="comment"> ****</span>
<span class="comment"> ****           &#39;telnet localhost 3999&#39;</span>
<span class="comment"> ****</span>
<span class="comment"> ****   Anything you type should be sent back to you in reverse!</span>
<span class="comment"> ****</span>
<span class="comment"> ****   To test the corrupt data detection, send a control code (like ^D),</span>
<span class="comment"> ****   if the terminating charcters are not detected within the specified time</span>
<span class="comment"> ****   the receive timeout will occur.</span>
<span class="comment"> ****</span>
<span class="comment"> ****/</span>


<span class="comment">//define the following to include the example classes and functions</span>

<span class="keywordtype">int</span> g_nOpenPorts = 0;                   <span class="comment">//Dirty global to allow us to quit simply</span>

<span class="keyword">class </span>ReverserPort : <span class="keyword">public</span> SampleSocketPort
{
<span class="keyword">public</span>:
        ReverserPort(SocketService *pService, TCPSocket &amp; tcpSocket) :
                        SampleSocketPort(pService, tcpSocket) {
                g_nOpenPorts++;
        }
        <span class="keyword">virtual</span> ~ReverserPort() {
                g_nOpenPorts--;
        }
        <span class="keyword">virtual</span> <span class="keywordtype">void</span> OnConnectionClosed(<span class="keywordtype">void</span>)
        { cerr &lt;&lt; <span class="stringliteral">&quot;Connection Closed!&quot;</span> &lt;&lt; endl; }

        <span class="keyword">virtual</span> <span class="keywordtype">void</span> OnDataReceived(<span class="keywordtype">char</span> *pszData, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> nByteCount) {
                <span class="comment">//Reverse the data and send it back</span>

                <span class="keywordtype">size_t</span> nLen = strlen(pszData);
                <span class="keywordtype">char</span> *szToSend = <span class="keyword">new</span> <span class="keywordtype">char</span>[nLen+1];

                <span class="comment">//No need to reverse the \r\n or \0</span>
                <span class="keywordtype">size_t</span> nIndex = nLen-3;

                <span class="keywordtype">size_t</span> i;
                <span class="keywordflow">for</span>(i=0; i &lt; nLen - 2; i++) {
                        szToSend[i] = pszData[nIndex - i];
                }
                szToSend[i++] = <span class="charliteral">&#39;\r&#39;</span>;
                szToSend[i++] = <span class="charliteral">&#39;\n&#39;</span>;
                szToSend[nLen] = <span class="charliteral">&#39;\0&#39;</span>;

                WriteData(szToSend, nLen);
                <span class="keyword">delete</span> [] szToSend;
        }

};

<span class="keyword">class </span>ReverserServer : <span class="keyword">public</span> SampleSocketServiceServer
{
<span class="keyword">public</span>:
        ReverserServer(<a class="code" href="address_8h.html#a5eba36aa908d5a479c8ba7d0bc4512b1">InetHostAddress</a> &amp; machine, <span class="keywordtype">int</span> port) :
        TCPSocket(machine, port), Thread(), SampleSocketServiceServer(machine, port) {
        }
        <span class="keyword">virtual</span> ~ReverserServer() {
        }
        <span class="keyword">virtual</span> SocketPort *CreateSocketPort(SocketService *pService, TCPSocket &amp; Socket) {
                <span class="keywordflow">return</span>(<span class="keyword">new</span> ReverserPort(pService, Socket));
        }
};


<span class="keywordtype">int</span> main(<span class="keywordtype">void</span>)
{
        <a class="code" href="address_8h.html#a5eba36aa908d5a479c8ba7d0bc4512b1">InetHostAddress</a> LocalHost;
        LocalHost = htonl(INADDR_ANY);
        ReverserServer *Server = NULL;
        <span class="keywordflow">try</span> {
                Server = <span class="keyword">new</span> ReverserServer(LocalHost, 3999);
                Server-&gt;StartServer();
        }
        <span class="keywordflow">catch</span>(...) {
                cerr &lt;&lt; <span class="stringliteral">&quot;Failed to start server&quot;</span> &lt;&lt; endl;
                <span class="keywordflow">return</span>(<span class="keyword">false</span>);
        }
        cerr &lt;&lt; <span class="stringliteral">&quot;Waiting for connections...type \&quot;quit\&quot; to exit.&quot;</span> &lt;&lt; endl;

        <span class="keywordtype">char</span> cmd[255];

        cin.getline(cmd, 255);


        <span class="keywordflow">while</span>(strcmp(cmd, <span class="stringliteral">&quot;quit&quot;</span>) != 0) {
                cin.getline(cmd, 255);
        }

        Server-&gt;StopServer();
        <span class="keyword">delete</span> Server;
        <span class="keywordflow">return</span> 0;
}

<span class="preprocessor">#endif  //WITH_EXAMPLE</span>
<span class="preprocessor"></span>
</pre></div> </div>
<hr class="footer"/><address style="text-align: right;"><small>Generated on Fri Nov 12 09:55:46 2010 for GNU CommonC++ by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.6.3 </small></address>
</body>
</html>