[code.view]

[top] / python / PyMOTW / docs / socket / tcp.html


<!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/html; charset=utf-8" />
    
    <title>TCP/IP Client and Server &mdash; Python Module of the Week</title>
    <link rel="stylesheet" href="../_static/sphinxdoc.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../',
        VERSION:     '1.132',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="../_static/jquery.js"></script>
    <script type="text/javascript" src="../_static/underscore.js"></script>
    <script type="text/javascript" src="../_static/doctools.js"></script>
    <link rel="author" title="About these documents" href="../about.html" />
    <link rel="top" title="Python Module of the Week" href="../index.html" />
    <link rel="up" title="socket – Network Communication" href="index.html" />
    <link rel="next" title="User Datagram Client and Server" href="udp.html" />
    <link rel="prev" title="Addressing, Protocol Families and Socket Types" href="addressing.html" /> 
  </head>
  <body>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="udp.html" title="User Datagram Client and Server"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="addressing.html" title="Addressing, Protocol Families and Socket Types"
             accesskey="P">previous</a> |</li>
        <li><a href="../contents.html">PyMOTW</a> &raquo;</li>
          <li><a href="../internet_protocols.html" >Internet Protocols and Support</a> &raquo;</li>
          <li><a href="index.html" accesskey="U">socket &#8211; Network Communication</a> &raquo;</li> 
      </ul>
    </div>
      <div class="sphinxsidebar">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../contents.html">Table Of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">TCP/IP Client and Server</a><ul>
<li><a class="reference internal" href="#echo-server">Echo Server</a></li>
<li><a class="reference internal" href="#echo-client">Echo Client</a></li>
<li><a class="reference internal" href="#client-and-server-together">Client and Server Together</a></li>
<li><a class="reference internal" href="#easy-client-connections">Easy Client Connections</a></li>
<li><a class="reference internal" href="#choosing-an-address-for-listening">Choosing an Address for Listening</a></li>
</ul>
</li>
</ul>

  <h4>Previous topic</h4>
  <p class="topless"><a href="addressing.html"
                        title="previous chapter">Addressing, Protocol Families and Socket Types</a></p>
  <h4>Next topic</h4>
  <p class="topless"><a href="udp.html"
                        title="next chapter">User Datagram Client and Server</a></p>
  <h3>This Page</h3>
  <ul class="this-page-menu">
    <li><a href="../_sources/socket/tcp.txt"
           rel="nofollow">Show Source</a></li>
  </ul>
<div id="searchbox" style="display: none">
  <h3>Quick search</h3>
    <form class="search" action="../search.html" method="get">
      <input type="text" name="q" size="18" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    <p class="searchtip" style="font-size: 90%">
    Enter search terms or a module, class or function name.
    </p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body">
            
  <div class="section" id="tcp-ip-client-and-server">
<h1>TCP/IP Client and Server<a class="headerlink" href="#tcp-ip-client-and-server" title="Permalink to this headline">¶</a></h1>
<p>Sockets can be configured to act as a <em>server</em> and listen for incoming
messages, or connect to other applications as a <em>client</em>.  After both
ends of a TCP/IP socket are connected, communication is
bi-directional.</p>
<div class="section" id="echo-server">
<h2>Echo Server<a class="headerlink" href="#echo-server" title="Permalink to this headline">¶</a></h2>
<p>This sample program, based on the one in the standard library
documentation, receives incoming messages and echos them back to the
sender.  It starts by creating a TCP/IP socket.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">socket</span>
<span class="kn">import</span> <span class="nn">sys</span>

<span class="c"># Create a TCP/IP socket</span>
<span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
</pre></div>
</div>
<p>Then <tt class="xref py py-func docutils literal"><span class="pre">bind()</span></tt> is used to associate the socket with the server
address.  In this case, the address is <tt class="docutils literal"><span class="pre">localhost</span></tt>, referring to the
current server, and the port number is 10000.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c"># Bind the socket to the port</span>
<span class="n">server_address</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;localhost&#39;</span><span class="p">,</span> <span class="mi">10000</span><span class="p">)</span>
<span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;starting up on </span><span class="si">%s</span><span class="s"> port </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">server_address</span>
<span class="n">sock</span><span class="o">.</span><span class="n">bind</span><span class="p">(</span><span class="n">server_address</span><span class="p">)</span>
</pre></div>
</div>
<p>Calling <tt class="xref py py-func docutils literal"><span class="pre">listen()</span></tt> puts the socket into server mode, and
<tt class="xref py py-func docutils literal"><span class="pre">accept()</span></tt> waits for an incoming connection.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c"># Listen for incoming connections</span>
<span class="n">sock</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>

<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
    <span class="c"># Wait for a connection</span>
    <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;waiting for a connection&#39;</span>
    <span class="n">connection</span><span class="p">,</span> <span class="n">client_address</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>
</pre></div>
</div>
<p><tt class="xref py py-func docutils literal"><span class="pre">accept()</span></tt> returns an open connection between the server and
client, along with the address of the client.  The connection is
actually a different socket on another port (assigned by the kernel).
Data is read from the connection with <tt class="xref py py-func docutils literal"><span class="pre">recv()</span></tt> and transmitted
with <tt class="xref py py-func docutils literal"><span class="pre">sendall()</span></tt>.</p>
<div class="highlight-python"><div class="highlight"><pre>    <span class="k">try</span><span class="p">:</span>
        <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;connection from&#39;</span><span class="p">,</span> <span class="n">client_address</span>

        <span class="c"># Receive the data in small chunks and retransmit it</span>
        <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
            <span class="n">data</span> <span class="o">=</span> <span class="n">connection</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span>
            <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;received &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span> <span class="o">%</span> <span class="n">data</span>
            <span class="k">if</span> <span class="n">data</span><span class="p">:</span>
                <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;sending data back to the client&#39;</span>
                <span class="n">connection</span><span class="o">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;no more data from&#39;</span><span class="p">,</span> <span class="n">client_address</span>
                <span class="k">break</span>
            
    <span class="k">finally</span><span class="p">:</span>
        <span class="c"># Clean up the connection</span>
        <span class="n">connection</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
</div>
<p>When communication with a client is finished, the connection needs to
be cleaned up using <tt class="xref py py-func docutils literal"><span class="pre">close()</span></tt>.  This example uses a
<tt class="docutils literal"><span class="pre">try:finally</span></tt> block to ensure that <tt class="xref py py-func docutils literal"><span class="pre">close()</span></tt> is always called,
even in the event of an error.</p>
</div>
<div class="section" id="echo-client">
<h2>Echo Client<a class="headerlink" href="#echo-client" title="Permalink to this headline">¶</a></h2>
<p>The client program sets up its <a class="reference internal" href="index.html#module-socket" title="socket: Network communication"><tt class="xref py py-class docutils literal"><span class="pre">socket</span></tt></a> differently from the
way a server does.  Instead of binding to a port and listening, it
uses <tt class="xref py py-func docutils literal"><span class="pre">connect()</span></tt> to attach the socket directly to the remote
address.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">socket</span>
<span class="kn">import</span> <span class="nn">sys</span>

<span class="c"># Create a TCP/IP socket</span>
<span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>

<span class="c"># Connect the socket to the port where the server is listening</span>
<span class="n">server_address</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;localhost&#39;</span><span class="p">,</span> <span class="mi">10000</span><span class="p">)</span>
<span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;connecting to </span><span class="si">%s</span><span class="s"> port </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">server_address</span>
<span class="n">sock</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">server_address</span><span class="p">)</span>
</pre></div>
</div>
<p>After the connection is established, data can be sent through the
<a class="reference internal" href="index.html#module-socket" title="socket: Network communication"><tt class="xref py py-class docutils literal"><span class="pre">socket</span></tt></a> with <tt class="xref py py-func docutils literal"><span class="pre">sendall()</span></tt> and received with <tt class="xref py py-func docutils literal"><span class="pre">recv()</span></tt>,
just as in the server.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">try</span><span class="p">:</span>
    
    <span class="c"># Send data</span>
    <span class="n">message</span> <span class="o">=</span> <span class="s">&#39;This is the message.  It will be repeated.&#39;</span>
    <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;sending &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span> <span class="o">%</span> <span class="n">message</span>
    <span class="n">sock</span><span class="o">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>

    <span class="c"># Look for the response</span>
    <span class="n">amount_received</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="n">amount_expected</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
    
    <span class="k">while</span> <span class="n">amount_received</span> <span class="o">&lt;</span> <span class="n">amount_expected</span><span class="p">:</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span>
        <span class="n">amount_received</span> <span class="o">+=</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
        <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;received &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span> <span class="o">%</span> <span class="n">data</span>

<span class="k">finally</span><span class="p">:</span>
    <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;closing socket&#39;</span>
    <span class="n">sock</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
</div>
<p>When the entire message is sent and a copy received, the socket is
closed to free up the port.</p>
</div>
<div class="section" id="client-and-server-together">
<h2>Client and Server Together<a class="headerlink" href="#client-and-server-together" title="Permalink to this headline">¶</a></h2>
<p>The client and server should be run in separate terminal windows, so
they can communicate with each other.  The server output is:</p>
<div class="highlight-python"><pre>$ python ./socket_echo_server.py

starting up on localhost port 10000
waiting for a connection
connection from ('127.0.0.1', 52186)
received "This is the mess"
sending data back to the client
received "age.  It will be"
sending data back to the client
received " repeated."
sending data back to the client
received ""
no more data from ('127.0.0.1', 52186)
waiting for a connection</pre>
</div>
<p>The client output is:</p>
<div class="highlight-python"><pre>$ python socket_echo_client.py

connecting to localhost port 10000
sending "This is the message.  It will be repeated."
received "This is the mess"
received "age.  It will be"
received " repeated."
closing socket

$</pre>
</div>
</div>
<div class="section" id="easy-client-connections">
<h2>Easy Client Connections<a class="headerlink" href="#easy-client-connections" title="Permalink to this headline">¶</a></h2>
<p>TCP/IP clients can save a few steps by using the convenience function
<tt class="xref py py-func docutils literal"><span class="pre">create_connection()</span></tt> to connect to a server.  The function takes
one argument, a two-value tuple containing the address of the server,
and derives the best address to use for the connection.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">socket</span>
<span class="kn">import</span> <span class="nn">sys</span>

<span class="k">def</span> <span class="nf">get_constants</span><span class="p">(</span><span class="n">prefix</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Create a dictionary mapping socket module constants to their names.&quot;&quot;&quot;</span>
    <span class="k">return</span> <span class="nb">dict</span><span class="p">(</span> <span class="p">(</span><span class="nb">getattr</span><span class="p">(</span><span class="n">socket</span><span class="p">,</span> <span class="n">n</span><span class="p">),</span> <span class="n">n</span><span class="p">)</span>
                 <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="nb">dir</span><span class="p">(</span><span class="n">socket</span><span class="p">)</span>
                 <span class="k">if</span> <span class="n">n</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">prefix</span><span class="p">)</span>
                 <span class="p">)</span>

<span class="n">families</span> <span class="o">=</span> <span class="n">get_constants</span><span class="p">(</span><span class="s">&#39;AF_&#39;</span><span class="p">)</span>
<span class="n">types</span> <span class="o">=</span> <span class="n">get_constants</span><span class="p">(</span><span class="s">&#39;SOCK_&#39;</span><span class="p">)</span>
<span class="n">protocols</span> <span class="o">=</span> <span class="n">get_constants</span><span class="p">(</span><span class="s">&#39;IPPROTO_&#39;</span><span class="p">)</span>

<span class="c"># Create a TCP/IP socket</span>
<span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">create_connection</span><span class="p">((</span><span class="s">&#39;localhost&#39;</span><span class="p">,</span> <span class="mi">10000</span><span class="p">))</span>

<span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;Family  :&#39;</span><span class="p">,</span> <span class="n">families</span><span class="p">[</span><span class="n">sock</span><span class="o">.</span><span class="n">family</span><span class="p">]</span>
<span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;Type    :&#39;</span><span class="p">,</span> <span class="n">types</span><span class="p">[</span><span class="n">sock</span><span class="o">.</span><span class="n">type</span><span class="p">]</span>
<span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;Protocol:&#39;</span><span class="p">,</span> <span class="n">protocols</span><span class="p">[</span><span class="n">sock</span><span class="o">.</span><span class="n">proto</span><span class="p">]</span>
<span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span>

<span class="k">try</span><span class="p">:</span>
    
    <span class="c"># Send data</span>
    <span class="n">message</span> <span class="o">=</span> <span class="s">&#39;This is the message.  It will be repeated.&#39;</span>
    <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;sending &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span> <span class="o">%</span> <span class="n">message</span>
    <span class="n">sock</span><span class="o">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>

    <span class="n">amount_received</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="n">amount_expected</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
    
    <span class="k">while</span> <span class="n">amount_received</span> <span class="o">&lt;</span> <span class="n">amount_expected</span><span class="p">:</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span>
        <span class="n">amount_received</span> <span class="o">+=</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
        <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;received &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span> <span class="o">%</span> <span class="n">data</span>

<span class="k">finally</span><span class="p">:</span>
    <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;closing socket&#39;</span>
    <span class="n">sock</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
</div>
<p><tt class="xref py py-func docutils literal"><span class="pre">create_connection()</span></tt> uses <tt class="xref py py-func docutils literal"><span class="pre">getaddrinfo()</span></tt> to find candidate
connection parameters, and returns a <a class="reference internal" href="index.html#module-socket" title="socket: Network communication"><tt class="xref py py-class docutils literal"><span class="pre">socket</span></tt></a> opened with the
first configuration that creates a successful connection.  The
<tt class="xref py py-attr docutils literal"><span class="pre">family</span></tt>, <tt class="xref py py-attr docutils literal"><span class="pre">type</span></tt>, and <tt class="xref py py-attr docutils literal"><span class="pre">proto</span></tt> attributes can be
examined to determine the type of <a class="reference internal" href="index.html#module-socket" title="socket: Network communication"><tt class="xref py py-class docutils literal"><span class="pre">socket</span></tt></a> being returned.</p>
<div class="highlight-python"><pre>$ python socket_echo_client_easy.py

Family  : AF_INET
Type    : SOCK_STREAM
Protocol: IPPROTO_TCP

sending "This is the message.  It will be repeated."
received "This is the mess"
received "age.  It will be"
received " repeated."
closing socket</pre>
</div>
</div>
<div class="section" id="choosing-an-address-for-listening">
<h2>Choosing an Address for Listening<a class="headerlink" href="#choosing-an-address-for-listening" title="Permalink to this headline">¶</a></h2>
<p>It is important to bind a server to the correct address, so that
clients can communicate with it.  The previous examples all used
<tt class="docutils literal"><span class="pre">'localhost'</span></tt> as the IP address, which limits connections to clients
running on the same server.  Use a public address of the server, such
as the value returned by <tt class="xref py py-func docutils literal"><span class="pre">gethostname()</span></tt>, to allow other hosts to
connect.  This example modifies the echo server to listen on an
address specified via a command line argument.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">socket</span>
<span class="kn">import</span> <span class="nn">sys</span>

<span class="c"># Create a TCP/IP socket</span>
<span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>

<span class="c"># Bind the socket to the address given on the command line</span>
<span class="n">server_name</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">server_address</span> <span class="o">=</span> <span class="p">(</span><span class="n">server_name</span><span class="p">,</span> <span class="mi">10000</span><span class="p">)</span>
<span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;starting up on </span><span class="si">%s</span><span class="s"> port </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">server_address</span>
<span class="n">sock</span><span class="o">.</span><span class="n">bind</span><span class="p">(</span><span class="n">server_address</span><span class="p">)</span>
<span class="n">sock</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>

<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
    <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;waiting for a connection&#39;</span>
    <span class="n">connection</span><span class="p">,</span> <span class="n">client_address</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;client connected:&#39;</span><span class="p">,</span> <span class="n">client_address</span>
        <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
            <span class="n">data</span> <span class="o">=</span> <span class="n">connection</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span>
            <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;received &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span> <span class="o">%</span> <span class="n">data</span>
            <span class="k">if</span> <span class="n">data</span><span class="p">:</span>
                <span class="n">connection</span><span class="o">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">break</span>
    <span class="k">finally</span><span class="p">:</span>
        <span class="n">connection</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
</div>
<p>A similar modification to the client program is needed before the
server can be tested.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">socket</span>
<span class="kn">import</span> <span class="nn">sys</span>

<span class="c"># Create a TCP/IP socket</span>
<span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>

<span class="c"># Connect the socket to the port on the server given by the caller</span>
<span class="n">server_address</span> <span class="o">=</span> <span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="mi">10000</span><span class="p">)</span>
<span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;connecting to </span><span class="si">%s</span><span class="s"> port </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">server_address</span>
<span class="n">sock</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">server_address</span><span class="p">)</span>

<span class="k">try</span><span class="p">:</span>
    
    <span class="n">message</span> <span class="o">=</span> <span class="s">&#39;This is the message.  It will be repeated.&#39;</span>
    <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;sending &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span> <span class="o">%</span> <span class="n">message</span>
    <span class="n">sock</span><span class="o">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>

    <span class="n">amount_received</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="n">amount_expected</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
    <span class="k">while</span> <span class="n">amount_received</span> <span class="o">&lt;</span> <span class="n">amount_expected</span><span class="p">:</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span>
        <span class="n">amount_received</span> <span class="o">+=</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
        <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;received &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span> <span class="o">%</span> <span class="n">data</span>

<span class="k">finally</span><span class="p">:</span>
    <span class="n">sock</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
</div>
<p>After starting the server with the argument
<tt class="docutils literal"><span class="pre">farnsworth.hellfly.net</span></tt>, the <strong class="command">netstat</strong> command shows it
listening on the address for the named host.</p>
<div class="highlight-python"><pre>$ host farnsworth.hellfly.net

farnsworth.hellfly.net has address 192.168.1.17

$ netstat -an

Active Internet connections (including servers)
Proto Recv-Q Send-Q  Local Address          Foreign Address        (state)
...
tcp4       0      0  192.168.1.17.10000     *.*                    LISTEN
...</pre>
</div>
<p>Running the the client on another host, passing
<tt class="docutils literal"><span class="pre">farnsworth.hellfly.net</span></tt> as the host where the server is running,
produces:</p>
<div class="highlight-python"><pre>$ hostname

homer

$ python socket_echo_client_explicit.py farnsworth.hellfly.net

connecting to farnsworth.hellfly.net port 10000
sending "This is the message.  It will be repeated."
received "This is the mess"
received "age.  It will be"
received " repeated."</pre>
</div>
<p>And the server output is:</p>
<div class="highlight-python"><pre>$ python ./socket_echo_server_explicit.py farnsworth.hellfly.net

starting up on farnsworth.hellfly.net port 10000
waiting for a connection
client connected: ('192.168.1.8', 57471)
received "This is the mess"
received "age.  It will be"
received " repeated."
received ""
waiting for a connection</pre>
</div>
<p>Many servers have more than one network interface, and therefore more
than one IP address.  Rather than running separate copies of a service
bound to each IP address, use the special address <tt class="xref py py-const docutils literal"><span class="pre">INADDR_ANY</span></tt>
to listen on all addresses at the same time.  Although <a class="reference internal" href="index.html#module-socket" title="socket: Network communication"><tt class="xref py py-mod docutils literal"><span class="pre">socket</span></tt></a>
defines a constant for <tt class="xref py py-const docutils literal"><span class="pre">INADDR_ANY</span></tt>, it is an integer value and
must be converted to a dotted-notation string address before it can be
passed to <tt class="xref py py-func docutils literal"><span class="pre">bind()</span></tt>.  As a shortcut, use the empty string <tt class="docutils literal"><span class="pre">''</span></tt>
instead of doing the conversion.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">socket</span>
<span class="kn">import</span> <span class="nn">sys</span>

<span class="c"># Create a TCP/IP socket</span>
<span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>

<span class="c"># Bind the socket to the address given on the command line</span>
<span class="n">server_address</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;&#39;</span><span class="p">,</span> <span class="mi">10000</span><span class="p">)</span>
<span class="n">sock</span><span class="o">.</span><span class="n">bind</span><span class="p">(</span><span class="n">server_address</span><span class="p">)</span>
<span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;starting up on </span><span class="si">%s</span><span class="s"> port </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">sock</span><span class="o">.</span><span class="n">getsockname</span><span class="p">()</span>
<span class="n">sock</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>

<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
    <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;waiting for a connection&#39;</span>
    <span class="n">connection</span><span class="p">,</span> <span class="n">client_address</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;client connected:&#39;</span><span class="p">,</span> <span class="n">client_address</span>
        <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
            <span class="n">data</span> <span class="o">=</span> <span class="n">connection</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span>
            <span class="k">print</span> <span class="o">&gt;&gt;</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#39;received &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span> <span class="o">%</span> <span class="n">data</span>
            <span class="k">if</span> <span class="n">data</span><span class="p">:</span>
                <span class="n">connection</span><span class="o">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">break</span>
    <span class="k">finally</span><span class="p">:</span>
        <span class="n">connection</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
</div>
<p>To see the actual address being used by a socket, call its
<tt class="xref py py-func docutils literal"><span class="pre">getsockname()</span></tt> method.  After starting the service, running
<strong class="command">netstat</strong> again shows it listening for incoming connections
on any address.</p>
<div class="highlight-python"><pre>$ netstat -an

Active Internet connections (including servers)
Proto Recv-Q Send-Q  Local Address          Foreign Address        (state)
...
tcp4       0      0  *.10000                *.*                    LISTEN
...</pre>
</div>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="udp.html" title="User Datagram Client and Server"
             >next</a> |</li>
        <li class="right" >
          <a href="addressing.html" title="Addressing, Protocol Families and Socket Types"
             >previous</a> |</li>
        <li><a href="../contents.html">PyMOTW</a> &raquo;</li>
          <li><a href="../internet_protocols.html" >Internet Protocols and Support</a> &raquo;</li>
          <li><a href="index.html" >socket &#8211; Network Communication</a> &raquo;</li> 
      </ul>
    </div>
    <div class="footer">
      &copy; Copyright Doug Hellmann.
      Last updated on Oct 24, 2010.
      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.

    <br/><a href="http://creativecommons.org/licenses/by-nc-sa/3.0/us/" rel="license"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-nc-sa/3.0/us/88x31.png"/></a>
    
    </div>
  </body>
</html>

[top] / python / PyMOTW / docs / socket / tcp.html

contact | logmethods.com