cannot read from QUdpSocket client - qt

I send command to a system and read response from it. My machine is client, I write a packet successfully to server, however, I cannot receive the response from it. I am wondering why this happens, please have a look at my code: (server address is 192.168.100.143 and the port is 11000)
void UDP::UDPInit(int port)
{
socketPort = port;
udpsocket = new QUdpSocket(this);
}
void UDP::sendCommand(QByteArray data)
{
QHostAddress *host = new QHostAddress("192.168.100.143");
quint16 port = 11000;
if(udpsocket->writeDatagram(data.data(),QHostAddress(ip),socketPort)==-1)
emit clientLogMessage(QString("UDPCLIENT : Write problem !"));
else
udpsocket->flush();
while (!udpsocket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(udpsocket->pendingDatagramSize());
qDebug() << udpsocket->pendingDatagramSize();
udpsocket->readDatagram(datagram.data(), datagram.size(), host, &port);
emit dataReceived(datagram);
}
}

QUdpSocket has a signal readyRead which is emitted each time a new packet is available, if you are in an event loop I suggest you use it
the condition in your while is negated which means that udpsocket->pendingDatagramSize() will return -1 inside the while loop and readDatagram will discard the packet
fixed code:
void UDP::UDPInit(int port)
{
socketPort = port;
udpsocket = new QUdpSocket(this);
connect(udpsocket, SIGNAL(readyRead()), this, SLOT(readSocket()));
}
void UDP::sendCommand(QByteArray data)
{
QHostAddress *host = new QHostAddress("192.168.100.143");
quint16 port = 11000;
if(udpsocket->writeDatagram(data.data(),QHostAddress(ip),socketPort)==-1)
emit clientLogMessage(QString("UDPCLIENT : Write problem !"));
else
udpsocket->flush();
}
void UDP::readSocket()
{
while (udpsocket->hasPendingDatagrams())
{
QByteArray datagram;
datagram.resize(udpsocket->pendingDatagramSize());
qDebug() << udpsocket->pendingDatagramSize();
udpsocket->readDatagram(datagram.data(), datagram.size(), host, &port);
emit dataReceived(datagram);
}
}

Related

ESP32: Send a simple TCP Message and receive the response

I want to do the same request as with the netcat "nc" command on my computer with an ESP32:
Computer:
$ nc tcpbin.com 4242
Test
Test
What I've tried so far:
Create a wifi client and listen to an answer:
Connect to a tcp server
write a message
wait and read the answer
#include <Arduino.h>
#include <WiFi.h>
WiFiClient localClient;
const char* ssid = "...";
const char* password = "...";
const uint port = 4242;
const char* ip = "45.79.112.203"; // tcpbin.com's ip
void setup() {
Serial.begin(115200);
Serial.println("Connect Wlan");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(WiFi.localIP());
}
void loop() {
sendRequest();
delay(200);
}
void sendRequest() {
if(!localClient.connected()) {
if (localClient.connect(ip, port)) {
Serial.println("localClient connected");
localClient.write('A'); //Single char
Serial.println("msg sent");
}
}
if(localClient.connected()) {
Serial.println("Start reading");
if (localClient.available() > 0) {
char c = localClient.read();
Serial.print(c);
}
Serial.println("Stop reading");
}
}
I'm pretty sure that I misunderstood something of the tcp concept during the implementation. However, after various approaches and trying other code snippets, I can't come up with a solution.
thank you in advance
regards
Leon
There are several issues with your code.
If you test nc, you will notice that the server will not acknowledge back until your press 'return'. You are sending a single byte without termination in your code, so the server is waiting for subsequent data. To terminate the data, you need to send a '\n', or instead of using client.write('A'), use client.println('A').
A network response take time, your current code expecting immediate response without waiting with if (localClient.available() > 0).
Here is the code that will work:
void sendRequest() {
if (localClient.connect(ip, port)) { // Establish a connection
if (localClient.connected()) {
localClient.println('A'); // send data
Serial.println("[Tx] A");
}
while (!localClient.available()); // wait for response
String str = localClient.readStringUntil('\n'); // read entire response
Serial.print("[Rx] ");
Serial.println(str);
}
}

Send data periodically as a server to my client in arduino ESP8226

I'm using NodeMCU board to communicate a laptop through WiFi. Basic communication is ok with a code like this:
void loop (){
WiFiClient client = server.available();
if (client) {
while (client.connected()){
client.println(Data_mem[0]);
delay(2000);
}
client.stop(); // tarminates the connection with the client
}
}
But when I want to send data a Timer Tick, it seems the client couldn't connect to me.
void setup(){
....
//Initialize Ticker every 40ms
Data_Rec.attach_ms(40, 40ms_Data );
}
void 40ms_Data (){
WiFiClient client = server.available();
Serial.println("40ms_Data A");
if (client) {
Serial.println("40ms_Data B");
if (client .connected()){
Serial.println("40ms_Data C");
client.println(40ms_Data [0]);
}
else{
client.stop();
}
}
}
I arduino serial monitor, i see only this:
40ms_Data A \r\n
40ms_Data A \r\n
....
So, could anyone help me? maybe it a problem of WiFiClient deceleration in a non-forever loop (like example 1). But I have no idea to fix it.
According to M.R.'s idea, this is my complete new code:
#include <ESP8266WiFi.h>
#include <Ticker.h>
/* Put your SSID & Password */
const char* ssid = "NodeMCU"; // Enter SSID here
const char* password = "12345678"; //Enter Password here
/* Put IP Address details */
IPAddress local_ip(192,168,1,1);
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,255,0);
WiFiServer server(80);
const int CLIENT_TIMEOUT = 2000;
Ticker Data_Rec;
bool Sending_40ms_Start_Flag = false;
void setup() {
Serial.begin(115200);
pinMode(D0, OUTPUT);
WiFi.softAP(ssid, password);
WiFi.softAPConfig(local_ip, gateway, subnet);
delay(100);
server.begin();
Serial.println("HTTP server started");
Data_Rec.attach_ms(500, flag_enable);//500ms is for test
}
void flag_enable(){
//Read FPGA Data from SPI
//...
Sending_40ms_Start_Flag = true;
}
void loop(){
WiFiClient client = server.available();
if (client) {
while(client.connected()){
Serial.println("40ms_Data B");
if (Sending_40ms_Start_Flag){
client.println("Server listening.\r");
Sending_40ms_Start_Flag = false;
}
delay(1);//without this delay, ESP would be reset(because it cannot handle background processes)
}
// else{
// client.stop();
// }
}
}
This code worked. But the server RST the TCP connection after sending one,two or tree "Server listening." as Wireshark shows: Wireshark Capture
What is probable cause of TCP Reset from ESP?
Besides that some syntax errors in your code:
A good solution is to create a static pointer object from client and pass it as an argument to ms40_Data function:
void ms40_Data(WiFiClient *client)
{
Serial.println("40ms_Data A");
if (*client)
{
Serial.println("40ms_Data B");
if (client->connected())
{
Serial.println("40ms_Data C");
//client.println(40ms_Data [0]);
}
else
{
client->stop();
}
}
}
void setup()
{
...
// create a static object from WiFiClient
static WiFiClient client = server.available();
//Initialize Ticker every 40ms
Data_Rec.attach_ms(40, ms40_Data, &client);
}
void loop()
{
}
Another solution is, you can set a flag inside your ticker and then call your ms40_Data function:
bool start_40ms_Data = false;
void ms40_Data()
{
static WiFiClient client = server.available();
Serial.println("40ms_Data A");
if (client)
{
Serial.println("40ms_Data B");
if (client.connected())
{
Serial.println("40ms_Data C");
//client.println(40ms_Data [0]);
}
else
{
client.stop();
}
}
}
void flag_enable()
{
start_40ms_Data = true;
}
void setup()
{
...
//Initialize Ticker every 40ms
Data_Rec.attach_ms(40, flag_enable);
}
void loop()
{
if (start_40ms_Data)
{
ms40_Data();
start_40ms_Data = false;
}
}
The point is to adding this to setup function:
WiFi.mode(WIFI_AP);
Full explanation: Here
Thank you,

enc28j60 with arduino and local web service

please help
i am trying to use arduino Pro mini with ENC28j60 to get data from my local web service
the URL i used to get the data is (http://192.168.1.5:801/m/Service1.asmx/HelloWorld?tag=01)
when i use this URL in browser it return this result
peter danile,1234567
with arduino
i use this code but i can't get a result
// Demo using DHCP and DNS to perform a web client request.
// 2011-06-08 <jc#wippler.nl> http://opensource.org/licenses/mit-license.php
#include <EtherCard.h>
// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
byte Ethernet::buffer[700];
static uint32_t timer;
const char website[] PROGMEM = "192.168.1.5";
//char website[] PROGMEM = "google.com";
// called when the client request is complete
static void my_callback (byte status, word off, word len) {
Serial.println(">>>");
Ethernet::buffer[off+300] = 0;
Serial.print((const char*) Ethernet::buffer + off);
Serial.println("...");
}
void setup () {
Serial.begin(57600);
Serial.println("\n[webClient]");
if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
Serial.println( "Failed to access Ethernet controller");
if (!ether.dhcpSetup())
Serial.println("DHCP failed");
ether.printIp("IP: ", ether.myip);
ether.printIp("GW: ", ether.gwip);
ether.printIp("DNS: ", ether.dnsip);
if (!ether.dnsLookup(website))
Serial.println("DNS failed");
ether.printIp("SRV: ", ether.hisip);
}
void loop () {
ether.packetLoop(ether.packetReceive());
if (millis() > timer) {
timer = millis() + 5000;
Serial.println();
Serial.println(PSTR("/m/Service1.asmx/HelloWorld?"));
Serial.print("<<< REQ ");
ether.hisport = 801;//to access local host
ether.browseUrl(PSTR("/m/Service1.asmx/HelloWorld?"), "tag=01", website, my_callback);
}
}

QTcpSocket: Sending data reliable to QTcpServer: Detect unplugged cable

I have to send data reliable from a client using QTcpSocket to a server using QTcpServer.
The connection is established once and the data is send line by line with terminator of "\r\n" (The server is splitting the incoming data on this terminator)
If need to know which line could be successful and which line not.
This works as expected. But if I unplug the server network cable from the network, the client is still writing data and the "bytesWritten" signal is still emitted.
But no write error occurred and the "error" signal is not emitted. It seems QTcpSocket is writing the data to an internal buffer even if the TPC connection is lost. Using flush() has no effect.
Example code based on the fortune client:
Client::Client(QWidget *parent)
: QDialog(parent), networkSession(0)
{
m_messageCount=0;
QString ipAddress= "192.168.1.16";
m_socket = new QTcpSocket(this);
//No effect...
//m_socket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
connect(m_socket, SIGNAL(connected()), this, SLOT(Connected()));
connect(m_socket, SIGNAL(disconnected()), this, SLOT(DisConnected()));
connect(m_socket, SIGNAL(bytesWritten(qint64)), this, SLOT(OnBytesWritten(qint64)));
connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));
}
void Client::connectToHost()
{
m_socket->connectToHost("192.168.1.16", 1234);
}
void Client::Connected()
{
qDebug() << "Connected()";
QTimer::singleShot(1000, this, SLOT(SendNextRecord()));
}
void Client::DisConnected()
{
qDebug() << "DisConnected()";
}
void Client::SendNextRecord()
{
m_messageCount++;
QByteArray singleRecord=QString("Nr: %1 Some Text").arg(m_messageCount).toUtf8();
singleRecord.append("\r\n");
Q_ASSERT(m_socket->isValid());
qDebug() << "Sending: " <<singleRecord;
//bytesSend always > 0
qint64 bytesSend=m_socket->write(singleRecord);
//No effect
m_socket->flush();
qDebug() <<"bytes Send:" << bytesSend;
}
//Signal is still emitted even if network cable is unplugged
void Client::OnBytesWritten(qint64 bytes)
{
qDebug() << "OnBytesWritten:" << bytes;
//No effect
m_socket->flush();
QTimer::singleShot(1000, this, SLOT(SendNextRecord()));
}
//Signal not emitted even if network cable is unplugged
void Client::displayError(QAbstractSocket::SocketError socketError)
{
qDebug() << "Socket error";
}
Can I change this behaviour ?

How to use function "send" (Winsock) to stream video in VS10 with OpenCV?

I used OpenCV on VS10 to stream video from my webcam. I also used winsock2 to transmit a message and an image in the same computer from server-client TCP/IP (local host). Now I'm trying to stream video in real-timing. I don't know if with function "send" I can specify the length of each frame because I think that it can also send a constant char. Anyone know what function could I use to solve my problem?
Source code:
Server.cpp
#include "Server.h"
using namespace std;
//Our main function
//void main()
int _tmain(int argc, _TCHAR* argv[])
{
//We have to start de Winsock-dll
long answer;
WSAData wsaData;
WORD DLLVERSION;
DLLVERSION = MAKEWORD (2,1);
//Stard the dll
answer = WSAStartup(DLLVERSION, &wsaData);
//The dll was started, now I use the winsock funcitions in the program
//Structure for the sockets
SOCKADDR_IN addr;
//addr = our structure
int addrlen = sizeof(addr);
//Now we have to create our sockets
//sListen = socket which is listening for incoming connection
SOCKET sListen;
//sConnect = socket which is operating if a connection was found!
SOCKET sConnect;
//Now we have to setup our sockets:
//AF_INET = means that our socket belongs to the internet family
//SOCK_STREAM = means that our socket is a connection-orientated socket
sConnect = socket(AF_INET, SOCK_STREAM, NULL);
//Now we have to setup our structure
//inet_addr = IP of our socket (I use 127.0.0.1...this is the loopback adress)
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//Retype the family
addr.sin_family = AF_INET;
//Now we have to setup the port in the structure;
//Now our server has the IP: 127.0.0.1 and the port 1234
addr.sin_port = htons (1234);
//Now we have to setup our sListen socket
sListen = socket(AF_INET, SOCK_STREAM, NULL);
//Now we blind the socket
//The socket becomes the structure addr
bind(sListen, (SOCKADDR*)&addr, sizeof(addr));
//We have to say that the socket is listening for an incoming connection
listen(sListen, SOMAXCONN);
//SOMAXCON means that the server is listenning without any limit
//We have to start the capture of the frames to send it
//Well first of all initialize the frames and the default camera
//Using OpenCV
CvCapture *capture = 0;
IplImage *frame = 0;
int key = 0;
capture = cvCaptureFromCAM(0);
//At last we have to say what the serve sould do if a connection was found!
//For this we create a endless loop:
for(;;)
{
cout << "Waiting for an incoming connection" <<endl;
//if a connection was found << "..." <<endl
if(sConnect = accept(sListen, (SOCKADDR*)&addr, &addrlen))
{
cout << "A connection was found" <<endl;
//Second part in reference to Youtube 2
//1r: The server should send a message with the funcion send();
//The number of the letters +1
//Ex: Number of the letters: 14+1=15
answer = send(sConnect, "Bonjour",8, NULL);
//*************************Third part of the project
//Sending an image captured from the cam
//always check
if ( !capture )
{
fprintf( stderr, "Cannot open initialize webcam!\n" );
return 1;
}
//create a window for the video
cvNamedWindow( "server", CV_WINDOW_AUTOSIZE );
while( key != 'q' )
{
//get a frame
frame = cvQueryFrame(capture);
//always check
if( !frame ) break;
//display current frame
cvShowImage( "server", frame );
//exit if user press 'q'
key = cvWaitKey(1);
}
char StartStream(IplImage *frame);
int streamSize(IplImage *frame);
if(frame!=0)
{
return sizeof(*frame->imageData);
}
char* buffer = new char[10000];
int len = 10000;
//int sent = 0;
for(int i=0; i<len; i+= answer)
{
answer = send(sConnect, buffer+i, len-i, 0);
}
}
//free memory
cvDestroyWindow( "server" );
cvReleaseCapture( &capture );
}
return 0;
}
Client.cpp
#include "Client.h"
using namespace std;
//void main()
int _tmain(int argc, _TCHAR* argv[])
{
string confirm;
char message[200];
string strmessage;
//IplImage *pImg;
//Start the functions of the Winsock-DLL
long answer;
WSAData wsaData;
WORD DLLVersion;
DLLVersion = MAKEWORD(2,1);
answer = WSAStartup(DLLVersion, &wsaData);
//Setup our Sockets and SOCKADDR_IN
SOCKADDR_IN addr;
//we will need addrlen later maybe!
int addrlen = sizeof(addr);
//Now setup our Socket
SOCKET sConnect;
sConnect = socket(AF_INET, SOCK_STREAM, NULL);
//IP of our server
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//Now we have to retype de family
addr.sin_family = AF_INET;
//Port of our server
addr.sin_port = htons(1234);
//Now we will ask the client if he wants to connect
cout << "Do you want to connect to your server? [Y/N]" <<endl;
cin >> confirm;
//If the user don't want to connect the client will close
if (confirm == "N")
{
exit(1);
}
else
{
if (confirm == "Y")
{
//function connect
connect(sConnect, (SOCKADDR*)&addr, sizeof(addr));
//Our client is working
//Now we program the client that he should recv a message from the server
//Our client should receive the message with the function recv();
//With new char "message"
answer = recv(sConnect, message, sizeof(message), NULL);
//The client should display the message
//With new string strmessage
strmessage = message;
cout << strmessage <<endl;
//the client also should display the image recived
char* buffer = new char[10000];
int len = 10000;
//int rec = 0;
int i=0;
for(int i=0; i<len; i+= answer)
{
while (answer = recv(sConnect, buffer+i, len-i, 0))
{
IplImage *frame = cvCreateImage(cvSize(640,480), 8, 3);
frame->imageData = (char *)buffer;
cvNamedWindow( "client", CV_WINDOW_AUTOSIZE );
cvShowImage( "client", frame );
}
return 0;
}
getchar();
}
}
getchar();
}
I receive the message and the confirmation of the connection in the server. And also it opens the webcam but the client doesn't receive anything.
You can try the cv_video_server and client.

Resources