Why does this code never discover Bonjour instances (mDNS)? - bonjour

I've taken this code almost directly from the dns-sd SDK sample, and yet, it does not find the services I search for.
There is no error, just none of the callbacks are called. This is linked against the Apple Bonjour SDK on Windows 10 x32.
If I run "dns-sd -B _http._tcp" it finds many instances!
void DNSSD_API IterateServiceInstances(DNSServiceRef sdRef,
DNSServiceFlags flags,
uint32_t interfaceIndex,
DNSServiceErrorType errorCode,
const char * serviceName,
const char * regtype,
const char * replyDomain,
void * context)
{
puts("IterateServiceInstances is never called!");
}
void DiscoverSegments()
{
printf("Discovering Segments...");
DNSServiceRef client = NULL;
DNSServiceErrorType err;
err = DNSServiceBrowse(&client,
0,
0,
"_http._tcp",
"",
IterateServiceInstances,
NULL);
if (kDNSServiceErr_NoError != err)
printf("Error: Unable to enumerate Bonjour to find devices.\n");
int main(int argc, char ** argv)
{
DiscoverSegments();
}

Because your socket message loop must keep track of ALL of the socket handles (client service refs) and pump them all while open...

Related

ESP32 ModBus master half duplex read coil input registers

I'm trying to read a MODBUS sensor via an ESP32.
I'm using the following library: https://github.com/emelianov/modbus-esp8266
I have the following code:
#include <ModbusRTU.h>
#include <SoftwareSerial.h>
SoftwareSerial modBusSerial;
ModbusRTU modbus;
#define startReg 100
#define endReg 123
uint16_t res[endReg - startReg + 1];
// Callback to monitor errors in the modbus
bool cb(Modbus::ResultCode event, uint16_t transactionId, void* data) {
if (event != Modbus::EX_SUCCESS) {
Serial.print("Request result: 0x");
Serial.print(event, HEX);
}
return true;
}
void setup() {
Serial.begin(115200); // Default serial port (Hardware serial)
modBusSerial.begin(9600, SWSERIAL_8E1, MB_RX, MB_TX); // modbus configuration SWSERIAL_8E1 = 8 bits data, even parity and 1 stop-bit
modbus.begin(&modBusSerial);
modbus.master();
Serial.println("starting modbus...");
while (true) {
Serial.println(modBusSerial.read());
res[endReg - startReg] = 0; // string terminator to allow to use res as char*
if (!modbus.slave()) {
modbus.readIreg(16, startReg, res, endReg - startReg, cb);
}
modbus.task();
Serial.print("result: ");
Serial.println((char*) res);
delay(1000); // every second
}
}
Response I get;
When I do the exact same in QModMaster, I do get the correct output. Anyone any idea what I'm doing wrong here?
These are the settings I use;
I am aware of the "wrong" address in my code. I have 2 identical sensors but one is connected to my computer while the other one is connected to my ESP32.
Thanks in advance!

GTK GIO How to read reply sent by server

I wanted to write a client server thing using gio socket in gtk and I found a sample code to send data to server but, the more thing i want is to read the data/reply sent by the server. The below is sample code
#include <glib.h>
#include <gio/gio.h>
int main (int argc, char *argv[])
{
/* initialize glib */
g_type_init ();
GError * error = NULL;
/* create a new connection */
GSocketConnection * connection = NULL;
GSocketClient * client = g_socket_client_new();
/* connect to the host */
connection = g_socket_client_connect_to_host (client,
(gchar*)"localhost",
1500, /* your port goes here */
NULL,
&error);
/* don't forget to check for errors */
if (error != NULL)
{
g_error (error->message);
}
else
{
g_print ("Connection successful!\n");
}
/* use the connection */
GInputStream * istream = g_io_stream_get_input_stream (G_IO_STREAM (connection));
GOutputStream * ostream = g_io_stream_get_output_stream (G_IO_STREAM (connection));
g_output_stream_write (ostream,
"Hello server!", /* your message goes here */
13, /* length of your message */
NULL,
&error);
/* don't forget to check for errors */
if (error != NULL)
{
g_error (error->message);
}
return 0;
}
The above code works fine for the sending data to server but when i try to read it form input stream it goes in to block state. My read message function look like this
void readMessage()
{
char buffer[2048];
GInputStream * istream = g_io_stream_get_input_stream (G_IO_STREAM(connection));
gssize bytes;
bytes = g_input_stream_read(istream, buffer, sizeof buffer, NULL, NULL);
buffer[bytes] = '\0';
g_print ("%"G_GSSIZE_FORMAT" bytes read: %s\n", bytes, buffer);
}
g_input_stream_read() is documented as blocking until it receives as many bytes as you request (in this case, 2048), or until the connection is closed. Presumably, neither of those things are happening. How big is the reply from the server? Does it close the connection after sending its reply?
Bear in mind that g_socket_client_connect_to_host() opens a TCP connection, so you should expect to be doing stream-based I/O here, rather than message-based I/O. If you expect to be sending messages to and from the server, you will need a framing protocol within TCP.

Can one reliably connect a TCP socket to itself?

I am wondering whether it is possible to reliably connect a TCP socket to itself -- that is, to get just one socket where whatever you send() on you receive back through recv(). I saw that this can happen (e.g., here, here, and here), but none of these posts explain how to do this programmatically and reliably (i.e., this is usually touted as a curiosity, rather than a feature one would use deliberately). I'm interested in a solution for Windows, Mac, and Linux.
Just for completeness, please let me explain why I'm interested in this. I'm writing a cloud-based application where servers can send messages to other servers, including themselves. Each server uses one socket to talk to other servers, and so, to unify the code and make certain threading issues simpler, it would be good if the server could talk to itself using just one socket as well.
EDIT: #Rufflewind suggested connecting to the loopback adapter. I tried that using the code below, both with and without the call to listen. In all cases, however, I got an error (either "Invalid argument" or "Operation not supported"). What am I doing wrong?
#include <iostream>
#include <netinet/tcp.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void die(const char* const message) {
perror(message);
exit(0);
}
#define CHECK(operation,message) \
if ((operation) != 0) \
die(message)
int main(int argc, char* argv[]) {
sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(40000);
inet_aton("127.0.0.1", &local.sin_addr);
int sck = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
CHECK(bind(sck, (struct sockaddr *)&local, sizeof(local)), "Error while binding the socket to an address");
// CHECK(listen(sck, 1), "Error while listening.");
CHECK(connect(sck, (struct sockaddr *)&local, sizeof(local)), "Error while connecting the socket to self");
std::cout << "Succeeded in connecting sockets!" << std::endl;
const char* message = "ABCDEFGH";
const size_t messageLength = ::strlen(message) + 1;
const char* currentSend = message;
ssize_t leftToSend = messageLength;
while (leftToSend != 0) {
const ssize_t sent = send(sck, currentSend, leftToSend, 0);
if (sent == -1)
die("Can't send.");
currentSend += sent;
leftToSend -= sent;
}
std::cout << "Sent the message!" << std::endl;
char buffer[256];
char* currentRead = buffer;
size_t leftToRead = messageLength;
while (leftToRead != 0) {
const ssize_t read = recv(sck, currentRead, leftToRead, 0);
if (read == -1)
die("Can't read.");
currentRead += read;
leftToRead -= read;
}
std::cout << "Received message: " << buffer << std::endl;
return 0;
}
The most straightforward approach would be to bind to the loopback adapter. Just listen to 127.0.0.1 on some arbitrary port and the connect to that.
The problem with this approach is that the port is global on the machine, so that means other programs can connect to it too, and if you have multiple programs you might run into conflicts or conceivably exhaust all the possible ports.
Another approach is to use Unix domain sockets, but this is not supported on Windows.

How to make a G-WAN servlet close its connection silently without sending any reply

How to have gwan send no reply to some requests, i.e. make a servlet closed silently without building and sending a reply?
It is useful to reduce the out-going bandwidth from the server side.
For collecting data only, there's no need to respond anything to the client.
You can also close the connection from the servlet by doing something like (untested):
#include <sys/socket.h>
char buf[1024];
int s = (int)get_env(argv, CLIENT_SOCKET);
shutdown(s, SHUT_WR);
while(read(s, buf, sizeof(buf)) > 0);
close(s);
return 500;
Then return something like 500 like above so you don't have to build a reply.
You can do that with a gwan connection handler.
I think this is the event that you need to catch on the handler. Since you want the servlet to run then close the connection after.
HDL_BEFORE_WRITE, // after a reply was built, but before it is sent
Here is a sample code for the connection handler. You still need to add your filter. This code will close all requests after the reply was built.
int init(int argc, char *argv[])
{
u32 *states = (u32*)get_env(argv, US_HANDLER_STATES);
*states = (1 << HDL_BEFORE_WRITE)
}
int main(int argc, char *argv[])
{
long state = (long)argv[0];
if(state == HDL_BEFORE_WRITE)
{
return 0; // Close connection
}
return(255); // continue G-WAN's default execution path
}

iphone tcp connection

I want to establish tcp connection between iphone and PC. On PC QTspServer is running and working (was tested with other client application).
Here is the connection method i'm using on iphone:
- (IBAction)connectToServer:(id)sender {
CFReadStreamRef read = NULL;
CFWriteStreamRef write = NULL;
NSString *host = #"192.168.1.169";
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef)host, 1000, &read, &write);
CFWriteStreamOpen(write);
int k = 0;
}
The server on PC is not reacting. Any help is appropriate
By the way: Server is nothing more then a QTcpServer with replemented incomingConnection method. Here is the main function on server side:
int main(int argc, char **argv)
{
QApplication app(argc, argv);
AbstractServer server;
server.listen(QHostAddress::Any, 1000);
QLabel label("Hello server");
label.setFixedSize(400, 400);
label.show();
return app.exec();
}
The connection is established after something was sent to the server
Check that write isn't NULL after the call to CFStreamCreatePairWithSocketToHost. If it is, the socket connection is failing.
-(IBAction)connectToServer:(id)sender {
CFWriteStreamRef write = NULL;
NSString *host = #"192.168.1.169";
int port = 1000;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef)host, port, NULL, &write);
if (!write) {
// connection failed.
NSLog(#"Connection to %#:%d failed.",host,port);
} else {
CFWriteStreamOpen(write);
// keep a reference to the output stream for later use.
self.output = (NSOutputStream*)write;
// the function that made the output stream has "Create" in its name, so
// this method owns the write stream & should release it.
CFRelease(write);
}
}
Note that I store the output stream in a property of self. In your sample code, the stream isn't saved anywhere. You don't release it, so it still exists when the method exits, but there's no way of accessing it. If the sample -connectToServer: is representative, that error will prevent your object from sending anything to the server.