I am using QTcpSocket to connect to given host:
QHostAddress oAddr( u32Addr);
QTcpSocket* poSocket = new QTcpSocket(this);
connect(poSocket, SIGNAL(connected()), this, SLOT(readCheckConnection()));
poSocket->connectToHost( oAddr, 80);
I am not using waitForConnected() because I try to connect many hosts at once, sometimes with quite long time connection so I need to count on connected() signal.
Everything works fine with Windows 10, problem appears with Windows 11. Signal connected() is emitted although there is no host existing. Moreover when socket state is checked it also returns CONNECTED state.
I am working wit QT 5.15.2. What may cause this problem?
Related
I'm working on a project based on the ESP32 platform. The aim is to count the number of MAC addresses in the area, and transmit this information over WiFi (using an http POST request).
The first task is achieved by sniffing WIFI packets and collecting the contained addresses, following this example: https://blog.podkalicki.com/esp32-wifi-sniffer/
I believe that the code which "sniffs" the packets sets the ESP to run in promiscuous mode, and therefore I cannot connect to any AP anymore.
I've tried several solutions, first starting with timer interrupts. However this approach always led to a Core Panic and reset of the chip.
I also learnt I could use RTOS to run different tasks in parallel on the two cores of the CPU, but that didn't help to solve the problem.
void wifi_sniffer_packet_handler(void* buff, wifi_promiscuous_pkt_type_t type)
{
if (type != WIFI_PKT_MGMT)//aggiungere filtro su RSSI a questa altezza.
return;
const wifi_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buff;
const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)ppkt->payload;
const wifi_ieee80211_mac_hdr_t *hdr = &ipkt->hdr;
//some analysis and then print the MAC address
}
void setup() {
Serial.begin(115200);
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &chUpdate, true);
timerAlarmWrite(timer, 1000000, true);//timer, arr_val, reload=true
delay(4000);
wifi_sniffer_init();
timerAlarmEnable(timer);
}
// the loop function runs over and over again forever
void loop() {
//Serial.print("inside loop");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Establishing connection to WiFi..");
}
Serial.println("Connected to network");
}
I also noticed that the code in the loop gets stuck into the while, and is restarted every time the packet handler is run (I nevere get to see "Connected to network", but i see "Establishing connection to WiFi.." several times.
Anyone can explain me what's going on? Is there a different approach to achieve this result?
Thank you.
You may have two tasks and two cores, but the ESP32 still has only one wifi chip. The way your code is written (at least, the code you shared), you'll be trying to connect to a wifi network at the same time as you're trying to run promiscuous mode. You can do only one of those things at a time.
You'll need to stop promiscuous mode before you attempt to connect to an access point. Right now your code constantly attempt to connect to a wifi access point. Use a volatile variable to store the current mode - promiscuous or connected. Change it when you need to change states. Only attempt to connect to wifi when the variable says you want to be in connected mode.
There may be some code you need to run to turn off promiscuous mode when you change states, before you connect to a wifi access point.
If you're using wifi_sniffer_init() from the example you linked to, that code isn't meant to be run in an Arduino Core application. It does some network initialization that the Arduino Core will also do. It may not be safe to do that twice (it might work, it might not... but it's definitely not intended to be done that way).
You're setting an interrupt handle chUpdate() which you didn't share. I'd bet that's the cause of your Core Panics. You can do very little in an interrupt handler. You definitely can't call most Arduino Core functions or most ESP-IDF functions. Most code isn't protected against interrupts, so the timer interrupt can occur while data structures are in an inconsistent state. Re-entering code can corrupt the data structures and cause the kind of crash you described. You're best off setting a volatile variable and waking up a task that will do the work you need done while not in the interrupt handler.
Finally, you should call WiFi.mode(WIFI_STA); before you call WiFi.begin().
For anyone confused about why you can't connect to a wifi network while in promiscuous mode - what ESP8266 and ESP32 call "promiscuous mode" is really "wifi monitor mode", which lets you monitor a wifi radio channel and see all wifi frames sent on it. They use the term "promiscuous mode" differently from the rest of the industry. Usually "promiscuous mode" means seeing all the packets being sent on the network (wifi or hardwired) that you're connected to.
I know that it's been just over a year but THANKS to the info provided by romkey I think I solved this problem within my app by calling this routine before connecting to WiFi to upload MAC data.
void end_Scan_WiFi() {
esp_wifi_set_promiscuous(false);
esp_wifi_stop();
}
Followed by this ...
WiFi.mode(WIFI_STA);
WiFi.begin(ssid,pass);
Hi there,
I will search and tried lots of solution for our problem but none of works. This will be a long post so be ready.
Our System:
We have an arduino uno r3 clone and ethernet shield wiznet w5100,
This Arduino makes a http post request to a windows web service.
According to response arduino will make something that is not revelant to question.
So in our test environment, we will install a windows webservice to our windows machine and plug this machine to our local network. Then plug arduino to our local network too. than with our server ip ,arduino made an dhcp request get ip from our modem-router and can call webservices from our server.
From now on everything works fine.
Here is some sample code from our arduino.(I only use this extra library for arduino:"RestClient.h"
#include <Ethernet.h>
#include <SPI.h>
#include "RestClient.h"
RestClient client = RestClient("192.168.100.17",51200);
String response;
String PostData;
void setup()
{
Serial.begin(9600);
byte mac[] = { 0x04, 0xD6, 0x2E, 0x81, 0x01, 0xB0 };
if ( Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
}
delay(1000);
Serial.println(Ethernet.localIP());
}
void postDataToServer(long rfidnumber,int rfidsource){
String postedRFIDNumber=String(rfidnumber);
postedRFIDNumber="000"+postedRFIDNumber;
response = "";
PostData="RFID="+postedRFIDNumber+"&SOURCE="+rfidsource;
const char * myPost = PostData.c_str();
int statusCode =
client.post("/sqlpublish/TTSWebService.asmx/INSERT_INDEXRFID",myPost,&response);
}
We need to install our system to a company. This Company has its own local network. they have very restricted local network. You can connect their network but can not go to the "www" without their permissions. But that is not problem. We will use only local connection for our web services because we will also use an windows server which will inside local network.
This is a picture of their network system schema:
In this picture switches is missing but you can simply guess they uses lots of swtiches .Because company is very wide and have lots of device.
So if I connect any device to their local network , this device first call dhcp protocals get ip from Windows DHCP Server and then can communicate in the local network with other devices. But can not get through the internet modem because of the firewall in the router.
Then We will setup our system like this:
In this setup switch models are : "AVAYA".
VSP7000 XLS
ERS4826 GTS-PWR+
ERS3549 GTS-PWR+
Firewall is: Watchguard Firebox M300
When we setup the system something weird is going on. First of all when I connect my PC(My Device) to local network I can call webservices in the windows server. But Arduino cannot get IP from DHCP Server, and naturaly cannot connect to web services. So we think that "ok we can give IP static". Than we will give IP to our Arduino manually. After that weird things started to begin. When Arduino try to conenct our Windows webservices it only get response some times. Roughly 1 of 20 has got response from server anything else get time out connection.And also succeded response time also too long.
If we ping our static arduino IP From another Device(For example Device_1), It get response sometimes again. (Same Amount)
So then we try to narrow down our problem.
First Of All We Change the setup like this for once to make sure problem in local network.
And Normaly all systems works perfectly. So our Modem's DHCP server make it works perfectly.(Also in this setup If I give Ip static it worked too).
So there is these possibilties for connection error.
1-Firewall
2-Switch problem
3-Arduino Clon Problem.
1-Firewall
When We talked about the problem with system admin, He told ust every local network connection and port is open in the firewall. He is probably right because any pc connect to local network can call the web sevice.
2-Switch problem
This Question, talks about it as a solution it says use static ip, bu in our case it did not solve the problem.
In this Question jdr5ca answer make sense but ı hve no idea how can test the problem or solve the problem
In this Question answer tried but not working.
Lastly this post , but it is so general. and also what ı should use replace for "arping" in windows.
3-Arduino Clon Problem.
next week we try it with with original arduino ,
I will inform everybody.
SO, any suggestion,tool, or some diagnostic tool for the problem I'm open all the suggestion.
Apparently Our Problem is a specific switch model!
Here is the model: https://www.zyxel.com/tr/tr/products_services/es_108a.shtml?t=p (zyxel ES-108E)
When we directly connect arduino to zyxel switch, and ping arduino from another device in the network only some of pings successful.(Roughly %15 succeeded).
But if we use another switch model or don't directly connect to zyxel switch, it works fine.
I dont know why it is not working with zyxel but problem is the switch!
I'm completely new at using the QtNetwork for connecting computers.
Right now all I want is to see an attempt at a connection. So I create a GUI application and on the mainwindow.cpp I write these two functions as slots for two buttons:
void MainWindow::on_pbTalk_clicked(){
QString IP = ui->leIP->text();
ui->pteLog->appendPlainText("Now Talking to IP: " + IP);
talker = new Talker();
talker->connectToHost(IP,25000);
}
void MainWindow::on_pbListen_clicked(){
ui->pteLog->appendPlainText("Now listening on any port, I think");
listener = new Listener(this);
if (!connect(listener, SIGNAL(newConnection()), this, SLOT(on_newConnections()))){
ui->pteLog->appendPlainText("The connection of slot and signal failed!");
}
}
Now Talker is essentially a QTcpSocket there is nothing reimplemented just yet.
Listener is a QTcpServer with the following code con Listener.cpp:
Listener::Listener(QObject *parent) :
QTcpServer(parent)
{
qDebug() << "Listening on any port";
listen(QHostAddress::Any);
}
void Listener::incomingConnection(int socketDescriptor){
qDebug() << "New connection: " << socketDescriptor;
}
So I run two instances of the same program. One is in my machine. I run the program and push the Listen button (IP 10.255.255.101).
The second instance is run in a virtual machine (IP 10.255.255.215) where I run the program and push the Talk button. This, as I understand should attempt to open a connection to IP (which is 10.255.255.101) at port 25000 and I should get a "New connection" message in the console. However no such message appears. And since this is not working, I'm not moving on.
Can any one tell me what I might be doing wrong?
Check the documenation of QTcpServer::listen - it says:
Tells the server to listen for incoming connections on address address
and port port. If port is 0, a port is chosen automatically. If
address is QHostAddress::Any, the server will listen on all network
interfaces.
QHostAddress::Any means that you are listening on all network interfaces, not ports. (For example, if you want to have a local server only, you could use QHostAddress::LocalHost - check QHostAddress::SpecialAddress for more like that.
If you want to set the port manually, you have to call:
listen(QHostAddress::Any, 25000);
If not, you can get the automatically chosen port by calling
quint16 port = serverPort();
The "listening on any port" idiom isn't available for your use; it's not how UDP and TCP were meant to be used. Most likely you shouldn't be designing your communications that way. Use a dedicated port.
If you want to build a packet sniffer, you'll have to use the platform-specific mechanisms designed for that. There are libraries that help you with that task, the most notable would be WinPcap on Windows and cross-platform libpcap from the TcpDump project.
I have a ssh tunnel setup using libssh. However, this does not bind it to a local port, so what I need essentially is to forward all data received on a port to the ssh channel. However, when I do this:
QTcpSocket* socket = new QTcpSocket();
socket->bind(27017);
QObject::connect(socket, &QTcpSocket::readyRead, this, &Forwarder::newData);
The newData slot is never invoked i.e. the readyRead on QTcpSocket is never invoked. Whenever I try to connect to the port via an external script, I get an Operation timed out. I am sure that atleast the port is opened because when the Qt application is not running, the error I get is Connection refused.
I have considered using QTcpServer, however, how do I even handle this case? I will probably get newConnection signals, but what data do I write to the ssh channel? How would I handle multiple incoming connections for a QTcpServer? Isn't a connection request also a data packet? Can I just not forward everything to the channel (The ssh channel I am referring to is akin to a fd that I can simple write to).
I have a network application which uses UDP broadcasts for device discovery, but only accepts one connection at a time. So, when a new TCP connection is made, I delete the QUdpSocket that was used for discovery.
However, when the remote device is disconnected, I want to create a new QUdpSocket and start listening again:
// Set up a UDP server to respond to any "discovery" messages:
udpServer = new QUdpSocket(this);
if (udpServer -> bind(QHostAddress::Any, DISCOVERY_PORT))
connect(udpServer, SIGNAL(readyRead()),
this, SLOT(beDiscovered()));
else
{
fprintf(stderr, "UDP port not bound successfully: %d, ", udpServer ->error());
fprintf(stderr, udpServer ->errorString().toLocal8Bit());
fprintf(stderr, "\r\n");
fflush(stderr);
#ifdef WIN32
_commit(_fileno(stderr));
#else
fsync(_fileno(stderr));
#endif
}
The re-bind fails, however, with code 8, "The bound address is already in use".
So, how can I make sure that when the 'old' QUdpSocket was deleted, it fully releases the address(es) it was bound to?
Alternatievly, should I be binding with QUdpSocket::ShareAddress or QUdpSocket::ReuseAddressHint? This doesn't seem right, as neither really describe the behaviour I want, namely an exclusive binding for my QUdpSocket during its lifetime, and in any case QUdpSocket::ShareAddress is supposed to be the default on Windows.
Thanks,
Stephen.
...so in other words the question has answered itself!