Problem Description
I am using hiredis unix socket to publish a number of messages (~2 KB per second) on a RPI 4B. I use the code given below to publish. I start getting Redis Protocol error messages after approximately 30-45 minutes of operation. Please let me know I can resolve this. Thank you!
`
#include "RedisDriver.h"
static redisContext* context;
const char* REDIS_SERVER_UNIX_SOCKET = (const char*) "/var/run/redis/redis-server.sock";
const char* REDIS_PACKET_CHANNEL_NAME = (const char*) "App-Data";
const char* REDIS_STATS_CHANNEL_NAME = (const char*) "App-Stats";
int RedisDriver_Initialize() {
struct timeval timeout = { 1, 500000 }; // 1.5 seconds
context = redisConnectUnixWithTimeout(REDIS_SERVER_UNIX_SOCKET, timeout);
if (context == NULL || context->err) {
if (context) {
syslog(LOG_ERR, "REDIS connection error: %s", context->errstr);
redisFree(context);
} else {
syslog(LOG_ERR,"Unable to allocate REDIS context.");
}
return FAILURE;
}
syslog(LOG_INFO, "Connected to REDIS at %s", REDIS_SERVER_UNIX_SOCKET);
return SUCCESS;
}
int RedisDriver_Publish(char* msg, const char* channel_name) {
if (!msg || !channel_name) {
return FAILURE;
}
//syslog(LOG_DEBUG, "message to publish: %s", msg);
redisReply* reply = (redisReply*) redisCommand(context, "PUBLISH %s %s", channel_name, msg);
if (reply) {
syslog(LOG_INFO, "Published %s. Reply: %s", channel_name, reply->str);
freeReplyObject(reply);
return SUCCESS;
}
switch(context->err) {
case REDIS_ERR_IO:
syslog(LOG_ERR, "There was an I/O error while connecting to REDIS.");
break;
case REDIS_ERR_EOF:
syslog(LOG_ERR, "REDIS server closed the connection.");
break;
case REDIS_ERR_PROTOCOL:
syslog(LOG_ERR, "REDIS protocol error.");
break;
case REDIS_ERR_OTHER:
default:
syslog(LOG_ERR, "Unknown REDIS Error.");
break;
}
return context->err;
}
int RedisDriver_Finalize() {
redisFree(context);
return SUCCESS;
}
`
Environment:
Hardware: Raspberry PI 4B with 8 GB RAM
OS: Raspbian GNU/Linux 10 (buster)
Redis server: v=5.0.14 sha=00000000:0 malloc=libc bits=32 build=a6df2d1b76e73a91
Compiler: gcc (Raspbian 8.3.0-6+rpi1) 8.3.0
hiredis version: 0.14.0-3 armhf
Related
Let me start by saying this is my first foray into the world of C after 20+ years of assembly programming for PLCs and MicroControllers.
I'm trying to send a UDP datagram to the network broadcast address, in this particular case, 192.168.1.255.
The error I'm getting is a bind failure with error code 10049 (from WSAGetLastError()). As you can see from the attached code, I've created the socket, populated sockaddr_in, and setsockopt() to SO_BROADCAST.
For the life of me I can't figure out what I'm doing wrong and any pointers would be gratefully received.
iResult = WSAStartup(MAKEWORD(2, 2), &wsaTxData);
if (iResult != NO_ERROR)
{
WSAErrorString("WSAStartup for TX failed");
return(-1);
}
XPLMDebugString("UDP Server: WSAStartup TX complete.\n");
if ((BeaconSocket = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
WSAErrorString("UDP Server: Could not create BECN socket");
return(-1);
}
// setup the sockaddr_in structure
//
si_beacon.sin_family = AF_INET;
si_beacon.sin_addr.s_addr = inet_addr("192.168.1.255");
si_beacon.sin_port = htons(_UDP_TX_PORT);
// setup to broadcast
//
char so_broadcast_enabled = '1';
if (setsockopt(BeaconSocket, SOL_SOCKET, SO_BROADCAST, &so_broadcast_enabled, sizeof(so_broadcast_enabled)) == SOCKET_ERROR) {
WSAErrorString("Error in setting Broadcast option");
closesocket(BeaconSocket);
return(-1);
}
// bind our socket
//
if (bind(BeaconSocket, (struct sockaddr *)&si_beacon, sizeof(si_beacon)) == SOCKET_ERROR)
{
char buf[256];
WSAErrorString("Bind to socket for UDP beacon failed");
sprintf(buf, "Port %u, address %s\n", ntohs(si_beacon.sin_port), inet_ntoa(si_beacon.sin_addr));
XPLMDebugString(buf);
return(-1);
}
// start the UDP beacon
//
udp_becn_thread_id = CreateThread(NULL, 0, BeaconThread, NULL, 0, NULL);
if (!udp_becn_thread_id) {
WSAErrorString("UDP Server: Error starting UDP Beacon");
return (-1);
}
XPLMDebugString("UDP Server: bind complete. beacon ACTIVE.\n");
return(0);
The issue is the IP address itself.
I copied the code to my computer (changed it a bit to get it to compile) and I got the error:
UDP Server: WSAStartup TX complete.
Bind to socket for UDP beacon failed
Port 47977, address 192.168.1.255
I then changed the line:
si_beacon.sin_addr.s_addr = inet_addr("192.168.1.255");
To
si_beacon.sin_addr.s_addr = inet_addr("192.168.0.127");
And when I ran it again, everything worked:
UDP Server: WSAStartup TX complete.
Done successfully
The issue is that the "bind" address needs to be your computers address on the local network. Not the remote client.
Another alternative is to use the address:
si_beacon.sin_addr.s_addr = inet_addr("0.0.0.0");
which binds to all network interfaces on the computer at once.
For reference, here's the version of the code that I used:
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <WinSock2.h>
#include <WS2tcpip.h> // For inet_pton
#pragma comment(lib, "ws2_32.lib")
int main()
{
{
WSADATA wsaTxData;
memset(&wsaTxData, 0, sizeof(WSADATA));
const int iResult = WSAStartup(MAKEWORD(2, 2), &wsaTxData);
if (iResult != NO_ERROR)
{
printf("%s", "WSAStartup for TX failed.\n");
return -1;
}
printf("%s", "UDP Server: WSAStartup TX complete.\n");
}
SOCKET BeaconSocket;
memset(&BeaconSocket, 0, sizeof(SOCKET));
if ((BeaconSocket = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
printf("%s", "UDP Server: Could not create BECN socket\n");
return -1;
}
// setup the sockaddr_in structure
//
sockaddr_in si_beacon;
memset(&si_beacon, 0, sizeof(sockaddr_in));
si_beacon.sin_family = AF_INET;
si_beacon.sin_addr.s_addr = inet_addr("0.0.0.0");
const unsigned short port_num = 0xbb69;
si_beacon.sin_port = htons(port_num);
// setup to broadcast
//
char so_broadcast_enabled = '1';
if (setsockopt(BeaconSocket, SOL_SOCKET, SO_BROADCAST, &so_broadcast_enabled, sizeof(so_broadcast_enabled)) == SOCKET_ERROR) {
printf("%s", "Error in setting Broadcast option\n");
closesocket(BeaconSocket);
return(-1);
}
// bind our socket
//
if (bind(BeaconSocket, (struct sockaddr*)&si_beacon, sizeof(si_beacon)) == SOCKET_ERROR)
{
char buf[256];
printf("%s", "Bind to socket for UDP beacon failed\n");
sprintf_s(buf, "Port %u, address %s\n", ntohs(si_beacon.sin_port), inet_ntoa(si_beacon.sin_addr));
printf("%s", buf);
return(-1);
}
printf("%s", "Done successfully");
return 0;
}
I am trying to establish UDP communication in the stm32 NUCLEO-F746ZG board. But I'm not able to ping. Getting the message as "Destination host unreachable." The program not going inside udp_echoserver_receive_callback() function.
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_LWIP_Init();
while (1)
{
MX_LWIP_Process();
}
}
void udp_echoserver_init(void)
{
struct udp_pcb *upcb;
err_t err;
upcb = udp_new();
if (upcb)
{
ip_set_option(upcb, SOF_BROADCAST);
err = udp_bind(upcb, IP_ADDR_ANY, 80);
if(err == ERR_OK)
{
udp_recv(upcb, udp_echoserver_receive_callback, NULL);
}
else
{
udp_remove(upcb);
}
}
}
void udp_echoserver_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
pc = (char*)p->payload;
pbuf_free(p);
}
I' trying to make an identical function to "ioctl" in c++ style using boost library.
Here is my "c" style code:
int sockfd;
char * id;
struct iwreq wreq;
memset(&wreq, 0, sizeof(struct iwreq));
sprintf(wreq.ifr_name, IW_INTERFACE);
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
fprintf(stderr, "Cannot open socket \n");
fprintf(stderr, "errno = %d \n", errno);
fprintf(stderr, "Error description is : %s\n",strerror(errno));
exit(1);
}
printf("Socket opened successfully \n");
id = malloc(IW_ESSID_MAX_SIZE+1);
wreq.u.essid.pointer = id;
if (ioctl(sockfd, SIOCGIWESSID, &wreq)) {
fprintf(stderr, "Get ESSID ioctl failed \n");
fprintf(stderr, "errno = %d \n", errno);
fprintf(stderr, "Error description : %s\n",strerror(errno));
exit(2);
}
printf("IOCTL Successfull\n");
printf("ESSID is %s\n", wreq.u.essid.pointer);
I found some relevant example, but I'm not clear how to use it correctly. example
Main function:
boost::asio::ip::udp::socket socket(io_service);
struct iwreq wreq
memset(&wreq, 0, sizeof(struct iwreq));
sprintf(wreq.ifr_name, IW_INTERFACE);
id = malloc(IW_ESSID_MAX_SIZE+1);
wreq.u.essid.pointer = id;
boost::asio::detail::io_control::myCommand command;
command.set(&wreq);
boost::system::error_code ec;
socket.io_control(command, ec);
if (ec)
{
// An error occurred.
}
Custom command:
#include <boost/asio/detail/config.hpp>
#include <cstddef>
#include <boost/config.hpp>
#include <boost/asio/detail/socket_types.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
namespace io_control {
// I/O control command for getting number of bytes available.
class myCommand
{
public:
// Default constructor.
myCommand()
: value_(0)
{
}
// Get the name of the IO control command.
int name() const
{
return static_cast<int>(SIOCGIWESSID);
}
// Set the value of the I/O control command.
void set(struct iwreq* value)
{
value_ = static_cast<detail::ioctl_arg_type>(value);
}
// Get the current value of the I/O control command.
std::size_t get() const
{
return static_cast<struct iwreq*>(value_);
}
// Get the address of the command data.
detail::ioctl_arg_type* data()
{
return &value_;
}
// Get the address of the command data.
const detail::ioctl_arg_type* data() const
{
return &value_;
}
private:
detail::ioctl_arg_type value_;
};
} // namespace io_control
} // namespace detail
} // namespace asio
} // namespace boost
However, the code does not work.
If you have any example code or solution, please let me know.
Thank you.
I am trying to use PubNub to publish a message to a channel but I always get "Connection Failed!".
I know the structure of a publish URL is the following:
http://pubsub.pubnub.com/publish/<PUB-KEY>/<SUB-KEY>/0/<CHANNEL>/0/%22<MESSAGE>%22
I have tested the URL on Google Chrome and it works just fine.
The following is a C flavored code is running on an Arduino UNO + Adafruit HUZZAH CC3000 WIFI Breakout. This is not an Arduino hardware question per se, because I believe there is nothing wrong with my circuit. My issue is with the structure of the HTTP GET request created using Adafruit CC3000 Library.
I am having to go with sending a GET rather than using PubNub Arduino Library because it doesn't seem to support CC3000 WIFI module. They have a JSON WIFI and Ethernet examples but both do not communicate with the CC3000 WIFI module.
char PUBKEY[] = "XXXXXXX";
char SUBKEY[] = "XXXXXXX";
Adafruit_CC3000_Client client = cc3000.connectTCP(ip, 80);
if (client.connected())
{
client.print("GET /publish/");
client.print(PUBKEY);
client.print("/");
client.print(SUBKEY);
client.print("/0/");
client.print("MyPubChannel"); // Channel Name
client.print("/0/%22");
client.print("Hello World from Arduino!"); // Msg to publish
client.print("%22");
client.println(" HTTP/1.1");
client.print("Host: ");
client.println("pubsub.pubnub.com");
client.println();
}
else
{
Serial.println(F("Connection failed"));
}
I have read this page and understood that a correct GET request would be of the form:
GET /pub/WWW/TheProject.html HTTP/1.1
Host: www.w3.org
I am pretty sure there is something wrong with my GET request. Can anyone look at this and provide ANY hints as to what could be going wrong?
I am finally able to connect to PubNub using the code below.
#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
#include "utility/debug.h"
#define ADAFRUIT_CC3000_IRQ 3 // MUST be an interrupt pin!
#define ADAFRUIT_CC3000_VBAT 5
#define ADAFRUIT_CC3000_CS 10
#define WLAN_SSID "XXXWifi"
#define WLAN_PASS "XXX"
#define WLAN_SECURITY WLAN_SEC_WPA2
#define IDLE_TIMEOUT_MS 3
uint32_t ip;
// PubNub Setup
#define WEBSITE "pubsub.pubnub.com"
#define WEBPAGE "/publish/"
char PUBKEY[] = "pub-XXXX";
char SUBKEY[] = "sub-XXXX";
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT, SPI_CLOCK_DIVIDER); // you can change this clock speed
Adafruit_CC3000_Client www;
void setup(void)
{
Serial.begin(115200);
/* Initialize the module */
Serial.print(F("\n Initializing WIFI Adapter..."));
if (!cc3000.begin())
{
Serial.println(F("Couldn't begin()! Check your wiring?"));
while(1);
}
Serial.print(F("Ready!\n"));
Serial.print(F("Connecting to [")); Serial.print(WLAN_SSID);
Serial.print(F("]..."));
if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
Serial.println(F("Failed!"));
while(1);
}
Serial.print(F("Connected!\n"));
//Wait for DHCP to complete
Serial.print(F("Waiting for DHCP..."));
while (!cc3000.checkDHCP())
{
delay(100); // ToDo: Insert a DHCP timeout!
}
Serial.print(F("Done!\n"));
Serial.print(F("Resolving PubNub..."));
ip = 0;
// Try looking up the website's IP address
while (ip == 0) {
if (! cc3000.getHostByName(WEBSITE, &ip)) {
Serial.println(F("Couldn't resolve!"));
}
delay(500);
}
Serial.print(F("Resolved!\n"));
www = cc3000.connectTCP(ip, 80);
for(int i=0;i<=50;i++)
{
char buffer[4];
dtostrf(i, 4, 0, buffer);
Publish("ch2", buffer);
}
/* You need to make sure to clean up after yourself or the CC3000 can freak out */
/* the next time your try to connect ... */
Serial.println(F("\n\nDisconnecting"));
www.close();
cc3000.disconnect();
}
void loop(void)
{
delay(1000);
}
void Publish(char* CH, char* MSG)
{
if (www.connected()) {
www.fastrprint(F("GET "));
www.fastrprint(WEBPAGE);
www.fastrprint(PUBKEY);
www.fastrprint(F("/"));
www.fastrprint(SUBKEY);
www.fastrprint(F("/0/"));
www.fastrprint(CH);
www.fastrprint(F("/0/%22"));
www.fastrprint(MSG);
www.fastrprint(F("%22"));
www.fastrprint(F(" HTTP/1.1\r\n"));
www.fastrprint(F("Host: "));
www.fastrprint(WEBSITE);
www.fastrprint(F("\r\n"));
www.fastrprint(F("\r\n"));
www.println();
} else {
Serial.println(F("Connection failed"));
return;
}
//Read data until either the connection is closed, or the idle timeout is reached.
unsigned long lastRead = millis();
while (www.connected() && (millis() - lastRead < IDLE_TIMEOUT_MS)) {
while (www.available()) {
char c = www.read();
//Serial.print(c);
lastRead = millis();
}
}
}
char* clean(char* MSG)
{
return MSG;
}
I've downloaded and compiled libssh 0.6.1 from libSSH and linked the ssh.lib,ssh.dll to a visual c++ project .
The code below compiles and run fine , but when calling ssh_connect() , it return -1 : Failed to connect : No error.
Also, I used putty to connect to my remote machine and it works fine.
here is my code:
// sshClient.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdlib.h>
#include <libssh/libssh.h>
int _tmain(int argc, _TCHAR* argv[])
{
ssh_session my_ssh_session;
int verbosity = SSH_LOG_PROTOCOL;
int port = 22;
char* host="127.0.0.1";
ssh_channel channel;
int rc;
//I create a session
my_ssh_session = ssh_new();
if (my_ssh_session == NULL)
exit(-1);
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, host);
ssh_options_set(my_ssh_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &port);
ssh_options_set(my_ssh_session, SSH_OPTIONS_USER,"true");
rc = ssh_connect(my_ssh_session);
if (rc != SSH_OK) {
fprintf(stderr, "Error connecting to 192.168.78.131 : %s\n", ssh_get_error(my_ssh_session));
exit(-1);
}
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
//Here I create a channel
channel = ssh_channel_new(my_ssh_session);
if (channel == NULL)
return SSH_ERROR;
if (SSH_OK != ssh_channel_open_session(channel)) {
printf("ssh_channel_open_session");
ssh_channel_free(channel);
return rc;
}
//My remote command ls -l under true Folder
rc = ssh_channel_request_exec(channel, "ls -l");
if (rc != SSH_OK){ ssh_channel_close(channel);
ssh_channel_free(channel);
return rc;
}
char buffer[256];
unsigned int nbytes;
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
while (nbytes > 0){
if (fwrite(buffer, 1, nbytes, stdout) != nbytes)
{ ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
}
if (nbytes < 0){
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
ssh_free(my_ssh_session);
system("pause");
return 0;
}
Check your host IP address. I guess you forgot to change the IP address in the example source file.