user38721: I'm trying to implement a full-duplex communication between my ESP8266 and a socketserver running on my laptop. In concrete I need each of the devices to initiate communication whenever it needs to. The ESP is measuring temperature all the time and when the temperature changes, I want the ESP to transmit the new temperature to my laptop.
On the other side I want to transmit a command from my laptop whenever I want to know the actual temperature (even if the temperature has not changed). 
Therefore I have a python server-script and a python client-script both running on my laptop (see scipts below).
In the loop function on my ESP I'm also running a server and a client (script below).
Sending commands from laptop-client to ESP-server works perfectly. Even at high rates and for days without any problem.
Communicating the other way around (that is sending from ESP-client to laptop-server) seems to work in general, but after numerous packages (usually a few hundreds) have been sent from ESP-client to laptop-server the communication fails and the laptop-server only receives empty byte-strings. After that has happened, also sending commands from laptop-client to ESP-server does not work any more temporarily.
When I shutdown the laptop-server, the ESP needs some time to "calm down" and will then continue working as usual.
Can anyone imagine what causes this behaviour? To me it looks like a buffer overflow or something like that.
I appreciate any help and hints about how to implement the desired functionality (do I actually need to run a server on both my laptop and the ESP?).
Laptop-Server:
import socket
import time

# create a socket object
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

host = "0.0.0.0"
port=1992

# bind to the port
serversocket.bind((host, port))

# queue up to 5 requests
serversocket.listen(5)

try:
  while True:
    # establish a connection
    clientsocket,addr = serversocket.accept()
    try:
        data = clientsocket.recv(1024)
        print(str(addr),":  ",data)
        clientsocket.send("hi there, "+str(addr)+"\n")
        clientsocket.close()
    except:
        pass
except:
  print(" !!! an exception occured !!!")
  serversocket.shutdown(socket.SHUT_RDWR)
  serversocket.close()

Laptop-Client:
import os,sys,re,time,socket,threading,readline

timeout=2

HOST, PORT = "ESP-IP", 1991

response=""
def s_client(data):
    global response
    try:
        response='Error: received no response'

        # Connect to server and send data
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(timeout)
        sock.connect((HOST, PORT))
        sock.sendall(bytes(data + "\n", "utf-8"))

        # Receive data from the server and shut down
        response=str(sock.recv(1024), "utf-8")
    except ConnectionRefusedError:
        response='Error: connection refused by remote host'
    except socket.timeout:
        response='Error: connection timed out'
    finally:
        sock.close()
    return 1


while True:
    try:
        print('  -->  '+s_client(input('_$ ')))
    except KeyboardInterrupt:
        break

ESP-script (containing server and client):
#include <WiFiClient.h>
#include <ESP8266WiFi.h>

IPAddress laptop_ip=(0,0,0,0);
uint16_t TCP_port=1991;
uint16_t TCP_remote_port=1992;
WiFiServer TCPserver(TCP_port);
WiFiClient client;

void ESP_server(void){
  if (!client.connected()) {
    client=TCPserver.available();
  }
  else {
    laptop_ip=client.remoteIP();
    Serial.println("received request");
    int query_l=client.available();
    if(query_l>0){
      String query="";
      for (int nb = 0; nb < query_l-1; nb++){
        query+=(char) client.read();
      }client.read();
      Serial.print("received from laptop: ");Serial.println(query);
      //  Do something with query and return the result
      //  For simplicity I'm just returning a constant value
      client.write("command transmitted");
    }
  }
}

void ESP_client(String message){
  WiFiClient TCPclient;
  if (TCPclient.connect(laptop_ip, TCP_remote_port)){
    TCPclient.print(message);
  }
}


void setup() {
  Serial.begin(115200);
  WiFi.begin("MYSSID","MYPASS");
  Serial.print("connecting with WiFi  ");
  while(WiFi.status()!=WL_CONNECTED){
    Serial.print(".");
    delay(500);
  }Serial.println();
  TCPserver.begin();

  // wait until a command has been received from the laptop
  // ESP_server stores the remote (laptop) ip in laptop_ip
  while(laptop_ip==(0,0,0,0)){
    ESP_server();
  }
}

int temp=0;
void loop() {
  // handle commands sent from my laptop
  ESP_server();

  //  here is a temperature meaurement returning the current temperature
  //  I've replaced it with a temperature generator
  if(temp<30){temp++;}
  else{temp=0;}

  // temperature has changed and needs to be transmitted by this function
  ESP_client((String) temp);
}

The above code differes from the code I'm actually running but it reproduces my problem. I hope that somebody can figure out a misstake or give my some advice about how I could implement things in a better way.
Actually I'm not sure whether the misstake is on laptop- or ESP-side but as the ESP crashes sometimes I think it's the ESP...
I'm using the arduino IDE for flashing, btw.

user37622: close the disconnected socket before reconnecting
if (!client.connected()) {
  client.stop();
  client=TCPserver.available();
}


user38721: I found my stupid mistake:
By using try without catching specific exceptions (I know one shouln't do that) in my Laptop-Server script I didn't recognize that I was trying to send unencoded strings.
So,
clientsocket.send("hi there, "+str(addr)+"\n")
has to be
clientsocket.send(bytes(("hi there, "+str(addr)+"\n").encode('utf-8')))
instead.

38721: <p>I'm trying to implement a full-duplex communication between my ESP8266 and a socketserver running on my laptop. In concrete I need each of the devices to initiate communication whenever it needs to. The ESP is measuring temperature all the time and when the temperature changes, I want the ESP to transmit the new temperature to my laptop.
On the other side I want to transmit a command from my laptop whenever I want to know the actual temperature (even if the temperature has not changed). </p>

<p>Therefore I have a python server-script and a python client-script both running on my laptop (see scipts below).</p>

<p>In the loop function on my ESP I'm also running a server and a client (script below).</p>

<p>Sending commands from laptop-client to ESP-server works perfectly. Even at high rates and <strong>for days</strong> without any problem.</p>

<p>Communicating the other way around (that is sending from ESP-client to laptop-server) seems to work in general, but after numerous packages (usually a few hundreds) have been sent from ESP-client to laptop-server the communication fails and the laptop-server only receives empty byte-strings. After that has happened, also sending commands from laptop-client to ESP-server does not work any more temporarily.
When I shutdown the laptop-server, the ESP needs some time to "calm down" and will then continue working as usual.</p>

<p>Can anyone imagine what causes this behaviour? To me it looks like a buffer overflow or something like that.
I appreciate any help and hints about how to implement the desired functionality (do I actually need to run a server on both my laptop and the ESP?).</p>

<p><strong>Laptop-Server</strong>:</p>

<pre><code>import socket
import time

# create a socket object
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

host = "0.0.0.0"
port=1992

# bind to the port
serversocket.bind((host, port))

# queue up to 5 requests
serversocket.listen(5)

try:
  while True:
    # establish a connection
    clientsocket,addr = serversocket.accept()
    try:
        data = clientsocket.recv(1024)
        print(str(addr),":  ",data)
        clientsocket.send("hi there, "+str(addr)+"\n")
        clientsocket.close()
    except:
        pass
except:
  print(" !!! an exception occured !!!")
  serversocket.shutdown(socket.SHUT_RDWR)
  serversocket.close()
</code></pre>

<p><strong>Laptop-Client</strong>:</p>

<pre><code>import os,sys,re,time,socket,threading,readline

timeout=2

HOST, PORT = "ESP-IP", 1991

response=""
def s_client(data):
    global response
    try:
        response='Error: received no response'

        # Connect to server and send data
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(timeout)
        sock.connect((HOST, PORT))
        sock.sendall(bytes(data + "\n", "utf-8"))

        # Receive data from the server and shut down
        response=str(sock.recv(1024), "utf-8")
    except ConnectionRefusedError:
        response='Error: connection refused by remote host'
    except socket.timeout:
        response='Error: connection timed out'
    finally:
        sock.close()
    return 1


while True:
    try:
        print('  --&gt;  '+s_client(input('_$ ')))
    except KeyboardInterrupt:
        break
</code></pre>

<p><strong>ESP-script</strong> (containing server and client):</p>

<pre><code>#include &lt;WiFiClient.h&gt;
#include &lt;ESP8266WiFi.h&gt;

IPAddress laptop_ip=(0,0,0,0);
uint16_t TCP_port=1991;
uint16_t TCP_remote_port=1992;
WiFiServer TCPserver(TCP_port);
WiFiClient client;

void ESP_server(void){
  if (!client.connected()) {
    client=TCPserver.available();
  }
  else {
    laptop_ip=client.remoteIP();
    Serial.println("received request");
    int query_l=client.available();
    if(query_l&gt;0){
      String query="";
      for (int nb = 0; nb &lt; query_l-1; nb++){
        query+=(char) client.read();
      }client.read();
      Serial.print("received from laptop: ");Serial.println(query);
      //  Do something with query and return the result
      //  For simplicity I'm just returning a constant value
      client.write("command transmitted");
    }
  }
}

void ESP_client(String message){
  WiFiClient TCPclient;
  if (TCPclient.connect(laptop_ip, TCP_remote_port)){
    TCPclient.print(message);
  }
}


void setup() {
  Serial.begin(115200);
  WiFi.begin("MYSSID","MYPASS");
  Serial.print("connecting with WiFi  ");
  while(WiFi.status()!=WL_CONNECTED){
    Serial.print(".");
    delay(500);
  }Serial.println();
  TCPserver.begin();

  // wait until a command has been received from the laptop
  // ESP_server stores the remote (laptop) ip in laptop_ip
  while(laptop_ip==(0,0,0,0)){
    ESP_server();
  }
}

int temp=0;
void loop() {
  // handle commands sent from my laptop
  ESP_server();

  //  here is a temperature meaurement returning the current temperature
  //  I've replaced it with a temperature generator
  if(temp&lt;30){temp++;}
  else{temp=0;}

  // temperature has changed and needs to be transmitted by this function
  ESP_client((String) temp);
}
</code></pre>

<p>The above code differes from the code I'm actually running but it reproduces my problem. I hope that somebody can figure out a misstake or give my some advice about how I could implement things in a better way.
Actually I'm not sure whether the misstake is on laptop- or ESP-side but as the ESP crashes <strong>sometimes</strong> I think it's the ESP...</p>

<p>I'm using the arduino IDE for flashing, btw.</p>
 37622: <p>close the disconnected socket before reconnecting</p>

<pre><code>if (!client.connected()) {
  client.stop();
  client=TCPserver.available();
}
</code></pre>
 38721: <p>I found my stupid mistake:
By using <code>try</code> without catching <strong>specific</strong> exceptions (I know one shouln't do that) in my Laptop-Server script I didn't recognize that I was trying to send unencoded strings.
So,
<code>clientsocket.send("hi there, "+str(addr)+"\n")</code>
has to be
<code>clientsocket.send(bytes(("hi there, "+str(addr)+"\n").encode('utf-8')))</code>
instead.</p>
