Using multicast addresses and groups - sockets

For a week or so I have been researching methods to send datagrams to multiple clients from a single source, and found that the IP supports multicasting over the range of 224.0.0.0 and 234.255.255.255. I have read a few documents that describe the technology, but am finding nothing that has helped me understand how to use them.
From what I have gathered, it seems that a program asks the OS kernel to join a non-associated multicast group, then starts sending data over a socket via UDP to the multicast address. Everything else is handled by WAN without needing anything something physically at the address being sent to.
This line of thinking has been vaguely supported by what I've read, but has not been confirmed at all. Is this thinking correct? What is mistaken if there are issues with it?

This is essentially correct.
On the receiver side, you first open up a socket listening on a particular port. Then you join a multicast address on a given network interface. Doing so causes the OS to send out IGMP messages to the network informing routers that is joining a group.
On the sender side, you open a socket, then configure the outgoing network interface for multicast. Once you do that, you can send packets to any multicast address.
Here's an example sender in C:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <strings.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
struct sockaddr_in sin;
struct in_addr out_addr;
char mes[255], ttl;
int sock;
printf("Enter message: ");
fgets(mes, sizeof(mes), stdin);
bzero(&sin,sizeof(sin));
sin.sin_family=AF_INET;
sin.sin_addr.s_addr=inet_addr(argv[1]);
sin.sin_port=htons(atoi(argv[2]));
if ((sock=socket(AF_INET,SOCK_DGRAM,0))==-1) {
perror("Error creating socket");
exit(1);
}
out_addr.s_addr=inet_addr(argv[3]);
if (setsockopt(sock,IPPROTO_IP,IP_MULTICAST_IF,(char *)&out_addr,sizeof(out_addr))== -1) {
perror("Error setting outgoing interface");
close(sock);
exit(1);
}
if (sendto(sock,mes,strlen(mes),0,(struct sockaddr *)&sin,sizeof(sin))==-1) {
close(sock);
perror("Send error");
}
close(sock);
}
And here's a sample receiver in C:
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int addr_len;
struct sockaddr_in sin,sin_recv;
struct ip_mreq multi;
char mes[255];
int sock;
bzero(&sin,sizeof(sin));
multi.imr_multiaddr.s_addr=inet_addr(argv[1]);
multi.imr_interface.s_addr=inet_addr(argv[2]);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(atoi(argv[3]));
if ((sock=socket(AF_INET,SOCK_DGRAM,0))==-1) {
perror("Error creating socket");
exit(1);
}
if (setsockopt(sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char *)&multi,sizeof(multi))== -1) {
perror("Error joining multicast group");
close(sock);
exit(1);
}
if (bind(sock,(struct sockaddr *)&sin,sizeof(sin))==-1) {
perror("Error binding socket");
close(sock);
exit(1);
}
while (1) {
bzero(mes,sizeof(mes));
bzero(&sin_recv,sizeof(sin_recv));
addr_len=sizeof(sin_recv);
printf("Waiting for packet...\n");
if (recvfrom(sock,mes,sizeof(mes),0,(struct sockaddr *)&sin_recv,&addr_len)==-1) {
perror("error recving socket");
close(sock);
exit(1);
}
printf("Got packet\n");
printf("Origin: %s port %d\n",inet_ntoa(sin_recv.sin_addr),sin_recv.sin_port);
printf("Message: %s\n",mes);
}
}

Related

Serial communication between RPi and Arduino using C++

I've written two pieces of code, to create a serial communication between Arduino and a Raspberry Pi using C++. The codes are:
void setup() {
Serial.begin(9600); // opens serial port, sets data rate to 9600 baud
}
void loop() {
Serial.println("Hello from arduino");
delay(500);
}
And the C++ code in Raspberry is :
#include <iostream>
#include <wiringPi.h>
#include <wiringSerial.h>
using namespace std ;
int serialDeviceId=0;
int main(void)
{
int pin=7;
serialDeviceId= serialOpen("/dev/ttyACM1",9600);
if(serialDeviceId==-1)
{
cout<<"Unable to open serial device"<<endl;
return 1;
}
if(wiringPiSetup()==-1)
{
return 0 ;
}
pinMode(pin,OUTPUT); // designing pin as an output
while(1)
{
digitalWrite(pin,0);
delay(500);
digitalWrite(pin,1);
delay(500);
}
return 0;
}
So now I would like to read the data from the serial port using always that wiringpi and I've found that I can use SerialGetchar, but I don't know exactly how to use it. I just need to need this part in my code so that I can receive that "Hello from from arduino" written in the serial, from my Arduino code.
This code should work for you on the Raspberry Pi. It is extremely simple! Make sure you get the correct device special file by running:
dmesg
and looking for line like this:
[610106.464745] usb 1-1.4: new full-speed USB device number 4 using dwc_otg
[610106.608642] usb 1-1.4: New USB device found, idVendor=2341, idProduct=0043
[610106.608655] usb 1-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=220
[610106.608663] usb 1-1.4: Manufacturer: Arduino (www.arduino.cc)
[610106.608671] usb 1-1.4: SerialNumber: 55731323536351E002E1
[610106.686193] cdc_acm 1-1.4:1.0: ttyACM0: USB ACM device
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <wiringSerial.h>
int main ()
{
int fd ;
if((fd=serialOpen("/dev/ttyACM0",9600))<0){
fprintf(stderr,"Unable to open serial device: %s\n",strerror(errno));
return 1;
}
for (;;){
putchar(serialGetchar(fd));
fflush(stdout);
}
}
I assume you have a USB cable connecting one of the RaspberryPi USB ports to the USB port on the Arduino.

Unable to authenticate bluemix connection using eclipse paho c libraries

I am using the eclipse paho mqtt c library to connect to bluemix. Have done my part on the bluemix cloud and created an IoT device and registered the same, have generated API keys. But when i try to connect to the device using the below code, my code exits with an rc state of 5.
And i see log messages on the cloud saying "Closed connection, unable to authenticate".
I have tried a lot, but rc is always 5.
Appreciate your assistance.
I am using the below code, with my organization ID, device type, space ID and authentication token (on bluemix i have created a IoT device on watson).
#include <iostream>
#include <sstream>
#include <fstream>
#include <string.h>
#include "MQTTClient.h"
#define CPU_TEMP "/sys/class/thermal/thermal_zone0/temp"
using namespace std;
#define ADDRESS "tcp://<org_ID>.messaging.internetofthings.ibmcloud.com:1883"
#define CLIENTID "d:<org_ID>:<Device_type>:<space_ID>"
#define AUTHMETHOD "use-token-auth"
#define AUTHTOKEN "<authentication_token>"
#define TOPIC "iot-2/evt/status/fmt/json"
#define QOS 1
#define TIMEOUT 10000L
float getCPUTemperature(){
int CPUTemp;
fstream fs;
fs.open(CPU_TEMP, fstream::in);
fs >> CPUTemp;
fs.close();
return (((float)CPUTemp)/1000);
}
int main(int argc, char* argv[]) {
MQTTClient client;
MQTTClient_connectOptions opts = MQTTClient_connectOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
opts.keepAliveInterval = 20;
opts.cleansession = 1;
opts.username = AUTHMETHOD;
opts.password = AUTHTOKEN;
int rc;
if ((rc = MQTTClient_connect(client, &opts)) != MQTTCLIENT_SUCCESS)
{
cout<<"Failed to connect "<<rc<<endl;
return -1;
}
stringstream message;
message <<"{\"d\":{\"Temp\":"<<getCPUTemperature()<<"}}";
pubmsg.payload = (char*) message.str().c_str();
pubmsg.payloadlen = message.str().length();
pubmsg.qos = QOS;
pubmsg.retained = 0;
MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token);
cout<< "Waiting for " << (int) (TIMEOUT/1000) << "seconds for pub of"<<message.str()<<"\non topic"<<TOPIC<<"for ClientID:"<<CLIENTID<<endl;
rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
cout<<"Message with token"<< (int)token<<"delivered"<<endl;
MQTTClient_disconnect(client,10000);
MQTTClient_destroy(&client);
return rc;
}
Apparently there are 2 connection types on bluemix, TLS and non TLS.
So i was accessing TLS type using my code meant for non-TLS connections.
Hence the authent

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.

UDP Socket communication using different ports between two hosts

I have a device that listen to UDP packets on port IN_PORT and echo the message on port OUT_PORT. I can communicate with it using a test software like Packet Sender.
I have to write a C++ library (Win32 at the moment) to communicate with the device. I made several tests but I still wasn't able to communicate. My guess is to use this workflow:
create socket
fill sockaddr_in structure with the device address, AF_INET family and the listeng port (OUT_PORT)
bind the socket
change sockaddr_in.sin_port with IN_PORT and send a packet (using sendto)
wait for an answer (using recvfrom)
repeat from 4
This works if I simulate the device with the Packet Sender utility working locally (device address = 127.0.0.1). I can't use the same workflow to connect to a remote address, even in the same subnet (e.g. my PC address: 192.168.1.2, remote PC address 192.168.1.5), since I get WSAEADDRNOTAVAIL error.
I've tested several different workflows, and read several discussions on the topic here and there, but none works, awfully.
Can someone give me some hints on the subject.
Thanks!
MIX
Your work flow is slightly wrong. It should be more like this instead:
create socket
fill sockaddr_in structure with the address of the local network adapter that is communicating with the device, AF_INET family, and the listenig port (OUT_PORT)
bind the socket
change sockaddr.sin_addr with device address, and sockaddr_in.sin_port with IN_PORT, and send a packet (using sendto)
wait for an answer (using recvfrom)
repeat from 4
I changed my code following Remy Lebeau hints. It works now. If someone will like to have a look and spot some weak points, or suggest improvements, I'll be glad (a code that "just works" is never enough; it must also "shine"!). Comments mark the previous (wrong) version of the code.
#pragma comment (lib, "Ws2_32.lib")
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#include <STRING>
#define IN_PORT 18
#define OUT_PORT 17
#define LOCAL_IP "10.0.10.108"
#define DEVICE_IP "10.0.10.104"
#define DEFAULT_BUFLEN 1024
int main(int argc, char *argv[])
{
WSADATA wsaData;
SOCKET sck;
struct sockaddr_in sckAddrInfo;
bool terminate;
char dataBuffer[DEFAULT_BUFLEN];
int rcvDataLength;
int sckAddrInfoLength;
WSAStartup(MAKEWORD(2,2), &wsaData);
sck = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
memset((&sckAddrInfo), 0, sizeof(sckAddrInfo));
sckAddrInfo.sin_family = AF_INET;
sckAddrInfo.sin_port = htons(IN_PORT);
//sckAddrInfo.sin_addr.s_addr = inet_addr(DEVICE_IP); // WRONG! Must bind local address
sckAddrInfo.sin_addr.s_addr = inet_addr(LOCAL_IP);
bind(sck, (struct sockaddr*)(&sckAddrInfo), sizeof(sckAddrInfo));
terminate = false;
sckAddrInfoLength = sizeof(sckAddrInfo);
while(!terminate)
{
printf("Write echo request: ");
gets(dataBuffer);
sckAddrInfo.sin_addr.s_addr = inet_addr(DEVICE_IP); // Must set device address, too, not just output port
sckAddrInfo.sin_port = htons(OUT_PORT);
sendto(sck, dataBuffer, strlen(dataBuffer), 0, (struct sockaddr*)(&sckAddrInfo), sizeof(sckAddrInfo));
memset(dataBuffer, '\0', DEFAULT_BUFLEN);
rcvDataLength = recvfrom(sck, dataBuffer, DEFAULT_BUFLEN, 0, (struct sockaddr*)(&sckAddrInfo), &sckAddrInfoLength);
printf("Device answer: %s\n", dataBuffer);
if(strcmp(dataBuffer, "quit") == 0)
terminate = true;
}
closesocket(sck);
WSACleanup();
return 0;
}

to create a socket to read image from url in linux

I want to write a socket program which read an image from an url and store it at a location.
I am familiar with basic of socket programming but never created such type of socket.
Below is the code to create a socket to read data from client which i want to modify for above mentioned problem.
Please help me with this.
Thank you
Code::
include<stdio.h>
#include<unistd.h>
#include<netinet/in.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<errno.h>
#include<stdlib.h>
#define sport 5000
int main(int argc,char **argv[])//Main function
{
struct sockaddr_in serveraddr;
int m,sd,acceptsd,rc,i;
char command[]="hello\n";
if((sd=socket(AF_INET,SOCK_STREAM,0))<0)
{
perror("error in socket creation\n");
exit(0);
}
memset(&serveraddr,0,sizeof(serveraddr));
serveraddr.sin_family=AF_INET;
serveraddr.sin_port=htons(sport);
serveraddr.sin_addr.s_addr=(INADDR_ANY);
//serveraddr.sin_addr.s_addr=inet_addr("127.0.0.1");
rc=bind(sd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
if(rc<0)
{
perror("srver bind error\n");
close(sd);
exit(-1);
}
rc=listen(sd,5);
if(rc<0)
{
perror("listen error");
close(sd);
exit(-1);
}
printf("server is ready to accept connection\n");
printf("\n");
acceptsd=accept(sd,NULL,NULL);
if(acceptsd<0)
{
perror("error in accepting\n");
exit(-1);
close(sd);
}
rc=send(acceptsd,command2,sizeof(command2),0);
if(rc<0)
{
perror("error in sending\n");
close(acceptsd);
close(sd);
exit(-1);
}
close(acceptsd);
close(sd);
exit(0);
}
The code needs to use TCP sockets and implement HTTP protocol to be able to access any URLs.
Implementing HTTP protocol handling on your own is a daunting and labour intensive task. A good start would be using libcurl.