esp32 rest chuncked response - rest

Im trying to know the real wifi speed capabilities of the esp32, and so i created a simple routine using a common library
void speedTest(AsyncWebServerRequest *request)
{
static uint8_t data[1024] = {0};
static uint32_t dataLen = 1*1024*1024;
memcpy(data, "ciao", 4);
AsyncWebServerResponse *response = request->beginChunkedResponse("application/octet-stream", [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t {
size_t len = (dataLen>maxLen)?maxLen:dataLen;
if (len>0)
{
memcpy(buffer, data, len);
dataLen -= len;
index += len;
}
return len;
});
response->setContentLength(dataLen);
request->send(response);
}
but when i make the GET request, the board reset itself and in serial monitor i see the following log:
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10124
load:0x40080400,len:5828
entry 0x400806a8
E (17770) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (17770) task_wdt: - async_tcp (CPU 0/1)
E (17770) task_wdt: Tasks currently running:
E (17770) task_wdt: CPU 0: IDLE0
E (17770) task_wdt: CPU 1: loopTask
E (17770) task_wdt: Aborting.
abort() was called at PC 0x40131b44 on core 0
I also have tried to reduce the file size and the download goes fine, but for my purpose is useless.
Someone has already meet and solved this problem ? im not really a lambda lover, alternately a different library more customizable, if is possible I would not like to reimplement all the http protocol over socket.
thanks in adavance for the help.
comeplete code:
#include <Arduino.h>
#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>
IPAddress local_ip(192,168,1,1);
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,255,0);
AsyncWebServer server(80);
const char* ssid = "testSpeed";
const char* psw = "12345678";
void notFound(AsyncWebServerRequest *request)
{
request->send(404, "text/plain", "Not found");
}
void speedTest(AsyncWebServerRequest *request)
{
#if 1
static uint8_t data[1024] = {0};
static uint32_t dataLen = 1*1024*1024;
memcpy(data, "ciao", 4);
AsyncWebServerResponse *response = request->beginChunkedResponse("application/octet-stream", [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t {
size_t len = (dataLen>maxLen)?maxLen:dataLen;
if (len>0)
{
memcpy(buffer, data, len);
dataLen -= len;
index += len;
}
return len;
});
response->setContentLength(dataLen);
request->send(response);
#endif
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_AP);
WiFi.softAP(ssid, psw);
WiFi.softAPConfig(local_ip, gateway, subnet);
server.on("/stream", HTTP_GET, speedTest);
server.onNotFound(notFound);
server.begin();
}
void loop() {
}

Looks like the implementation of AsyncWebServer is not meant for long-running transactions, as it never resets the task watchdog. As a workaround you can increase the watchdog timeout to its maximum limit of 60 s or disable it entirely. It's controlled by the following options in sdkconfig:
CONFIG_ESP_TASK_WDT=y # Task Watchdog is enabled
CONFIG_ESP_TASK_WDT_PANIC=y # Panic (reset) is invoked on timeout
CONFIG_ESP_TASK_WDT_TIMEOUT_S=30 # Timeout in seconds
The normal way to change those is to run idf.py menuconfig (where they appear under "Component config", "Common ESP-related") but you can just update the file "sdkconfig" directly.
Undo those changes after you're finished with your experiments, it's usually a good idea to keep the Task Watchdog enabled.

Related

What buffer collects the data sent through TCP sockets on localhost?

I have a client and server connected through TCP sockets on localhost.
I check with getsockopt that the server's SO_SNDBUF is small and the client's SO_RCVBUF is small (in my case both are 64KB)
I send twenty 500KB buffers from the server to the client, but in the client I've added a sleep for 500ms after each recv and I've capped the client receive buffer to 1MB.
What I observe is that the server very quickly rids itself of the 10MB of data which then arrives at the client in the next several seconds. 7-8MB are consistently in the "ether" in my experiments.
My question is what is this "ether"? It's obviously some buffer somewhere but can one tell which buffer it is?
Here is my test program.
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <thread>
#include <cstdio>
#include <vector>
#include <cstdlib>
#define PROXY 0
static std::vector<uint8_t> getRandomBuf() {
std::vector<uint8_t> buf;
buf.reserve(500 * 1024);
for (size_t i = 0; i < buf.capacity(); ++i) buf.push_back(rand() % 256);
return buf;
}
int server() {
auto sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd < 0) return puts("socket fail");
sockaddr_in srv = {};
srv.sin_family = AF_INET;
srv.sin_addr.s_addr = INADDR_ANY;
srv.sin_port = htons(7654);
int enable = 1;
if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) {
return puts("setsockopt fail");
}
if (bind(sd, (sockaddr*)&srv, sizeof(srv)) < 0) {
return puts("bind fail");
}
listen(sd, 3);
puts("listening...");
sockaddr_in client;
socklen_t csz = sizeof(client);
auto sock = accept(sd, (sockaddr*)&client, &csz);
if (sock < 0) return puts("accept fail");
{
int data;
socklen_t size = sizeof(data);
getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &data, &size);
printf("accepted: %d\n", int(data));
}
for (int i=0; i<20; ++i) {
auto buf = getRandomBuf();
puts("Server sending blob");
send(sock, buf.data(), buf.size(), 0);
puts(" Server completed send of blob");
}
while (true) std::this_thread::yield();
return close(sock);
}
int client() {
int sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd < 0) return puts("socket fail");
sockaddr_in client = {};
client.sin_family = AF_INET;
client.sin_addr.s_addr = inet_addr("127.0.0.1");
#if PROXY
client.sin_port = htons(9654);
#else
client.sin_port = htons(7654);
#endif
if (connect(sd, (sockaddr*)&client, sizeof(client)) < 0) {
return puts("connect fail");
}
{
int data;
socklen_t size = sizeof(data);
getsockopt(sd, SOL_SOCKET, SO_RCVBUF, &data, &size);
printf("connected: %d\n", int(data));
}
std::vector<uint8_t> buf(1024*1024);
while (true) {
auto s = recv(sd, buf.data(), buf.size(), 0);
if (s <= 0) {
puts("recv fail");
break;
}
printf("Client received %.1f KB\n", double(s)/1024);
#if !PROXY
std::this_thread::sleep_for(std::chrono::milliseconds(500));
#endif
}
return close(sd);
}
int main() {
std::thread srv(server);
std::this_thread::sleep_for(std::chrono::milliseconds(300)); // give time for the server to start
client();
srv.join();
return 0;
}
Note that in the test program there is a #define PROXY 0.
In another experiment with PROXY set to 1, I ditch the sleep and instead connect the client to a throttling proxy (Charles) and throttle the bandwidth to 400KB/s. In this case the server rids itself of the 10MB almost immediately and they arrive in course of ~20 seconds on the client. I assume that the proxy is buffering, though I don't see a configuration in this particular one for the buffer size.
This is all done hunting for another (likely bufferbloat) issue in which the server sends 10MB with 20 packets from Denver to Amsterdam over an Internet connection which does indeed have a 400KB/s bandwidth. In this case the server, much like the throttling proxy example from above, rids itself of the 10MB almost immediately, and they arrive over the next 20 seconds on the client, leading to 20 second delays for any subsequent messages. Had they not left the server, I would've been able to reorder the packets and send higher-priority ones in-between the ones from the 10MB blob, and not have the client suffer a 20 second delay due to network clog.

Stuck with netlink, connektor, socket and co

I'm completely new to netlink & co. and I am trying to establisch a connection from user space to the w1-kernel module of a raspberry pi.
Unfortunately the documentation i found is spotty and contradictory.
Here some of the things not clear to me:
basic communication is:
generate a socket: socket()
int s = socket(AF_NETLINK,SOCK_DGRAM, NETLINK_CONNECTOR);
bind it to a local name: bind()
int b = bind(s,(sockaddr*)&sa,sizeof(sa));
with
sa.nl_family=AF_NETLINK;
sa.nl_pid=getpid();//0?
sa.nl_groups=0; //23? -1?
create the message
send it: send()? sendmsg()?
wait for answer: poll()
read answer: recv()
+In examples i found (w1d.c and ucon.c) they use the send() command (not sendmsg) without a connect(), even though the man pages of send say that wouldnt work.
+I am not clear about the structure of the message:
send can send any buffer (char*)
netlink expects a struct nlmsghdr header;
connector expects a struct cn_msg header.
w1_netlink expects a w1_netlink_msg header and w1_netlink_cmd data.
Do i need all headers in a row? Ther are 2 sequence / message number variables, one in nlmsghdr and on in cn_msg???
The test program i wrote is not producing the result i expect: every thing works withour producing an error but i am getting no answer :-(
#include <iostream>
#include <linux/netlink.h>
#include <sys/types.h>
#include <sys/socket.h>
#include<sys/poll.h>
#include <unistd.h>
#include<cstring>
#include "w1_netlink.h"
__u32 nl_seq;
static int netlink_send(int s, struct cn_msg *msg) //copy from (ucon.c)
{
struct nlmsghdr *nlh;
unsigned int size;
int err;
char buf[128];
struct cn_msg *m;
size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len);
nlh = (struct nlmsghdr *)buf;
nlh->nlmsg_seq = nl_seq++;
nlh->nlmsg_pid = getpid();
nlh->nlmsg_type = NLMSG_DONE;
nlh->nlmsg_len = size;
nlh->nlmsg_flags = 0;
m = (cn_msg*) NLMSG_DATA(nlh);
memcpy(m, msg, sizeof(*m) + msg->len);
err = send(s, nlh, size, 0);
return err;
}
int main(int argc, char *argv[])
{
nl_seq=0;
int s = socket(AF_NETLINK,SOCK_DGRAM, NETLINK_CONNECTOR);
if(s==-1) {std::cout<<"no socket"; return s;};
std::cout<<"socket "<<s;
sockaddr_nl sa;
sa.nl_family=AF_NETLINK;
sa.nl_pid=0;//getpid();
sa.nl_groups=0;
int b = bind(s,(sockaddr*)&sa,sizeof(sa));
if(b==-1){std::cout<<"bind error";return b;}; //prints 3
std::cout<<"bind "<<b; //prints 0
int si=sizeof(struct cn_msg)+sizeof(struct w1_netlink_msg)+sizeof(w1_netlink_cmd);
char * buf;
buf=(char *)malloc(1024);
memset(buf,0,1024);
cn_msg *cnh = (cn_msg*)buf;
w1_netlink_msg* wnh=(w1_netlink_msg*)&cnh->data;
w1_netlink_cmd* wcmd = (w1_netlink_cmd*)&wnh->data;
cnh->id.idx=CN_W1_IDX;
cnh->id.val=CN_W1_VAL;
cnh->seq=nl_seq;
cnh->flags=0;
wnh->type=W1_LIST_MASTERS;
wnh->len=0;
cnh->len=sizeof(struct w1_netlink_msg)+sizeof(w1_netlink_cmd);
int len=netlink_send(s,cnh);
std::cout<<"send "<<len<<" "<<(int)wnh->status; //prints 52 0
pollfd pfd;
pfd.fd=s;
pfd.events=POLLIN;
pfd.revents=0;
int p=0;
while(p<1) {
p=poll(&pfd,1,1000);
std::cout<<"poll "<<p<<pfd.revents; //prints 0 0 in infinite loop
std::cout.flush();
};
memset(wcmd,0,128);
len=recv(s,buf,255,0);
std::cout<<"recv "<<len;
close(s);
return 0;
}
Result is socket 3 bind 0 send 52 0 poll 00 poll 00 ...
Thanks

Reading Ettus E310 Barometer over I2C, always returns No Such Device or Address (-1)

I've been trying to write a I2C device driver for the BMP 180 barometer and temperature sensor found on the E310 (as seen in sheet 9 of the schematic.) I have been basing my code off of the example driver given by bosch.
The driver requires function pointers to block read and write, as well as a sleep, which are basically the only original code:
int8_t user_i2c_read(uint8_t dev_id, uint8_t reg_addr,uint8_t *data, uint16_t len)
int8_t user_i2c_write(uint8_t dev_id, uint8_t reg_addr,uint8_t *data, uint16_t len)
void user_delay_ms(uint32_t period)
The problem I am having is that this driver (as well as simpler SMBUS command only programs I have written) have always failed to read or write the i2c address 0x77, where the sensor should be located on the bus.
readBytes for device ID 0x77: -1 - No such device or address
Even though my code seems to work for locations that other devices are located at (though I haven't done more than ping them)
Motion Sensor:
readBytes for device ID 0x69: 0 - Success
Temperature Sensor:
readBytes for device ID 0x19: 0 - Success
I was wondering either what is wrong with my code that the device would be completely unresponsive, or what hardware configuration am I missing that would explain the lack of communication with the barometer at 0x77.
I notice that the BMP-180 barometer is placed on the auxiliary i2c of the Gyro MPU-9150, but the wiring and datasheet make me think it is in pass through mode and not master mode. Just a thought I had though.
Here is all of the code I have that interacts with the bmpDriver.
Compiled with the following
gcc test.c -o test -std=c11 -D _DEFAULT_SOURCE
#include "bmp280.c"
#include <linux/i2c-dev-user.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int8_t user_i2c_read(uint8_t dev_id, uint8_t reg_addr,uint8_t *data, uint16_t len){
int file;
file = open("/dev/i2c-0", O_RDWR);
if(file < 0)
{
printf("Failed to open /dev/i2c-0\n");
close(file);
return -1;
}
if(ioctl(file, I2C_SLAVE, dev_id) < 0)
{
printf("ioctl failed for /dev/i2c-0 at %x - %s\n", dev_id, strerror(errno));
close(file);
return -2;
}
int readBytes;
readBytes = i2c_smbus_read_block_data(file, reg_addr, data);
printf("readBytes for device ID 0x%x: %d - %s\n", dev_id, readBytes, strerror(errno));
close(file);
return readBytes;
}
int8_t user_i2c_write(uint8_t dev_id, uint8_t reg_addr,uint8_t *data, uint16_t len){
int file;
file = open("/dev/i2c-0", O_RDWR);
if(file < 0)
{
printf("Failed to open /dev/i2c-0\n");
close(file);
return -1;
}
if(ioctl(file, I2C_SLAVE, dev_id) < 0)
{
printf("ioctl failed for /dev/i2c-0 at %x - %s\n", dev_id, strerror(errno));
close(file);
return -2;
}
int writeBytes;
uint8_t shortLen = len;
writeBytes = i2c_smbus_write_block_data(file, reg_addr, shortLen, data);
printf("writeBytes for device ID 0x%x: %d - %s\n", dev_id, writeBytes, strerror(errno));
close(file);
return writeBytes;
}
void user_delay_ms(uint32_t period){
unsigned int sleep = period;
usleep(sleep * 1000);
}
int main(){
int8_t rslt;
struct bmp280_dev user_bmp;
user_bmp.dev_id = BMP280_I2C_ADDR_SEC;
user_bmp.intf = BMP280_I2C_INTF;
user_bmp.read = user_i2c_read;
user_bmp.write = user_i2c_write;
user_bmp.delay_ms = user_delay_ms;
rslt = bmp280_init(&user_bmp);
if (rslt == BMP280_OK) {
printf("Device found with chip id 0x%x\n", user_bmp.chip_id);
}
else {
printf("Device not found, exiting...\n");
return -1;
}
struct bmp280_config conf;
rslt = bmp280_get_config(&conf, &user_bmp);
conf.filter = BMP280_FILTER_COEFF_2;
conf.os_pres = BMP280_OS_16X;
conf.os_temp = BMP280_OS_4X;
conf.odr = BMP280_ODR_1000_MS;
rslt = bmp280_set_config(&conf, &user_bmp);
rslt = bmp280_set_power_mode(BMP280_NORMAL_MODE, &user_bmp);
struct bmp280_uncomp_data ucomp_data;
uint8_t meas_dur = bmp280_compute_meas_time(&user_bmp);
printf("Measurement duration: %dms\r\n", meas_dur);
uint8_t i;
for (i = 0; (i < 10) && (rslt == BMP280_OK); i++) {
printf("Running measurement: %d\n", i+1);
user_bmp.delay_ms(meas_dur);
rslt = bmp280_get_uncomp_data(&ucomp_data, &user_bmp);
int32_t temp32 = bmp280_comp_temp_32bit(ucomp_data.uncomp_temp, &user_bmp);
uint32_t pres32 = bmp280_comp_pres_32bit(ucomp_data.uncomp_press, &user_bmp);
uint32_t pres64 = bmp280_comp_pres_64bit(ucomp_data.uncomp_press, &user_bmp);
double temp = bmp280_comp_temp_double(ucomp_data.uncomp_temp, &user_bmp);
double pres = bmp280_comp_pres_double(ucomp_data.uncomp_press, &user_bmp);
printf("UT: %d, UP: %d, T32: %d, P32: %d, P64: %d, P64N: %d, T: %f, P: %f\r\n", \
ucomp_data.uncomp_temp, ucomp_data.uncomp_press, temp32, \
pres32, pres64, pres64 / 256, temp, pres);
user_bmp.delay_ms(1000);
}
if(rslt != BMP280_OK){
printf("Result not okay at measurement: %d\n", i);
}
}
Before starting off with a speculation I would make sure that the transmission is actually reaching the sensor behind the gyro. Just use any scope to measure SCL and SDA. If the device is getting the transmission, the scope reading will provide additional information on where the device NAKs.
One difference between the BMP and the other i2c devices you were able to address that gave me multiple headaches in the past:
the BMP seems to require a repeated start condition between device address and register read.
As far as I can remember, standard i2c libraries do not support this and you usually have to build your own read / write functions using linux/i2c-dev.h.

Bluetooth connection refused

I am working on a Bluetooth project involving one Arduino (with Seeed bluetooth shield v2.0) and one ubuntu laptop. Basically, I want message exchanges between the Arduino and the laptop. I paired the Arduino bluetooth shield with the laptop. Then I use the code below (on the laptop) to test. The Arduino is set as a Slave. And the laptop sends a test message.
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
int main(int argc, char **argv){
struct sockaddr_rc addr = {0};
int s, status;
char buf[1024] = {0};
char dest[18] = "00:0E:EA:CF:1E:62";
for (size_t i = 1; i <= 30; i++) {
addr.rc_channel = i;
str2ba(dest, &addr.rc_bdaddr);
// connect to server
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
status = connect(s, (struct sockaddr *)&addr, sizeof(addr));
if(status == 0) {
status = send(s, "Hello!", 6, 0);
status = recv(s, buf, sizeof(buf), 0);
if(status > 0)
printf("received %s\n", buf);
break;
}
}
if(status < 0)
perror("send error");
close(s);
return 0;
}
Below is the test code at Arduino side.
#include <SoftwareSerial.h> //Software Serial Port
#define RxD 7
#define TxD 6
SoftwareSerial bt(RxD,TxD);
char buf[100];
size_t idx;
void setup() {
Serial.begin(9600);
bt.begin(9600);
pinMode(RxD, INPUT);
pinMode(TxD, OUTPUT);
setupBlueToothConnection();
}
void loop() {
Serial.println("Waiting ...");
idx = 0;
memset(buf, sizeof(buf), 0);
while(bt.available()){
buf[idx] = bt.read();
idx++;
}
while(idx >= 0){
bt.write(buf[idx]);
idx--;
}
delay(1000);
}
void setupBlueToothConnection() {
bt.print("AT");
delay(400);
bt.print("AT+DEFAULT"); // Restore all setup value to factory setup
delay(2000);
bt.print("AT+LADD?"); // Restore all setup value to factory setup
delay(2000);
bt.print("AT+NAMEProver"); // set the bluetooth name as "SeeedBTSlave"
delay(400);
bt.print("AT+PIN0000"); // set the pair code to connect
delay(400);
bt.print("AT+ROLE?");
delay(400);
bt.print("AT+AUTH0");
delay(400);
bt.flush();
}
I receive error message: "send error: Connection refused". What is the problem? Can some help me with this? Thanks!
Update: I guess it might be the problem with port number. But I checked the datasheet for Seeed Bluetooth shield v2.0 and has not found any clue regarding to setup port number.
Most common problem with Bluetooth on Arduino except for code is having Arduino connected to your PC over USB cable and trying to use Bluetooth, as far as I am aware most of the shields connect directly to hardware RX and TX of the Arduino board, which are the same ports used for USB communication to your PC.
So is your Arduino connected over a USB port to your PC?

ReadFile(socket) is cancelled, if the thread that called it dies

I'm trying to learn async I/O.
My program creates sockets and either accepts them with AcceptEx or connects them with connect. In its main thread I call WaitForMultipleObjects() in a loop, but I still create threads to resolve the names, call connect() and call the initial ReadFile().
These threads exit after they call ReadFile() and let the main thread wait for the read result.
For some reason, after the connecting thread dies, the read operation is cancelled, the event is triggered and GetOverlappedResult() fails with ERROR_OPERATION_ABORTED
Example:
#define _WIN32_WINNT 0x0501
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#define BUFSZ 2048
#define PORT 80
#define HOST "192.168.2.1"
#define HOST "stackoverflow.com"
static struct {
char buf[BUFSZ];
OVERLAPPED overlap;
SOCKET sock;
} x = { 0 };
static DWORD WINAPI barthread(LPVOID param) {
static struct sockaddr_in inaddr = { 0 };
int rc;
BOOL b;
DWORD dw;
DWORD nb;
LPHOSTENT lphost;
x.sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
inaddr.sin_family = AF_INET;
lphost = gethostbyname(HOST);
inaddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
inaddr.sin_port = htons(PORT);
rc = connect(x.sock, (struct sockaddr *)&inaddr, sizeof(struct sockaddr_in));
if (rc == 0) {
printf("thread 2 connected\n");
printf("thread 2 call ReadFile\n");
b = ReadFile((HANDLE)x.sock, x.buf, BUFSZ, &nb, &x.overlap);
dw = GetLastError();
if (b || dw == ERROR_IO_PENDING) {
printf("thread 2 ReadFile ok\n");
} else {
printf("thread 2 ReadFile failed\n");
}
printf("thread 2 sleeping\n");
Sleep(3000);
printf("thread 2 dying\n");
}
return 0;
}
int main(int argc, char* argv[])
{
WSADATA WD;
BOOL b;
DWORD dw;
DWORD nb;
DWORD tid;
WSAStartup(MAKEWORD(2, 0), &WD);
x.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
CreateThread(NULL, 0, barthread, NULL, 0, &tid);
dw = WaitForSingleObject(x.overlap.hEvent, INFINITE);
printf("thread 1 event triggered\n");
b = GetOverlappedResult((HANDLE)x.sock, &x.overlap, &nb, FALSE);
dw = GetLastError();
printf("thread 1 GetOverlappedResult() = %d, GetLastError() = %d\n", b, dw);
return 0;
}
You shouldn't be using separate threads at all. The whole point of overlapped I/O is that a single thread can do multiple tasks at one time. Have your main loop use WSAAsyncGetHostByName() instead of gethostbyname(), and WSAConnect() in non-blocking mode with WSAEventSelect() instead of connect() in blocking mode.
Found the similar question here:
Asynchronous socket reading: the initiating thread must not be exited - what to do?
and, here: http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/reference/asynchronous_operations.html :
Specifically, on Windows versions prior to Vista, unfinished operations are cancelled when the initiating thread exits.
I have Windows 7, but suffer from the same problem.
Instead of calling the initial ReadFile() in a temporary thread I will just set some flag, set the event manually and call ReadFile() in the main loop.