Flutter/Dart socket communication, characters encoding issue - sockets

For a proof of concept where 2 applications, written in Flutter and running on the same device, need to exchange information, I am using the 'dart:io' Sockets.
One of the 2 applications implements a SocketServer to receive the information and the other initializes the sockets communication.
From a connection perspective, this is working fine, using the following code:
Code of the server:
ServerSocket.bind('127.0.0.1', 8080).then((ServerSocket socketServer) {
socketServer.listen((Socket socket) {
socket.listen((List<int> data){
String result = String.fromCharCodes(data);
print('received: $result');
});
});
}).catchError(print);
Code of the client:
Socket.connect('127.0.0.1', 8080).then((socket) {
String data = 'Les élèves regardent par la fenêtre';
socket.write(data);
print("sent: $data");
}).catchError(print);
However, when I try to send a String which contains accentuated characters, I have the following outcome:
sent: Les élèves regardent par la fenêtre
received: Les élèves regardent par la fenêtre
This looks like an encoding related issue but I haven't yet been able to solve it.
Would anybody have any idea how to proceed to have this working?
Thanks

I found the solution.
Here it is:
Code for the Client:
Socket.connect('127.0.0.1', 8080).then((socket) {
String data = 'Les élèves regardent par la fenêtre';
socket.encoding = utf8; // <== force the encoding
socket.write(data);
print("sent: $data");
}).catchError(print);
Code for the Server:
ServerSocket.bind('127.0.0.1', 8080).then((ServerSocket socketServer) {
socketServer.listen((Socket socket) {
socket.listen((List<int> data){
String result = utf8.decode(data);
print('received: $result');
});
});
}).catchError(print);
The solution consists of "forcing" the encoding to utf8
Thanks for your help.

You should try using ut8.encode when writing the data, and utf8.decode when reading it on the other side.

Related

Problem with decoding JSON data from Pusher API in flutter

I am using Pusher API as real time database.
I can successfully connected and getting data in JSON format.
Problem: I couldn't decode it. I am using jsonDecode(); but that's not working as follow. Here is the screenshot of my code.
Anyone have solution? Any other way to decode it?
Future<void> _initPusher() async{
PusherClient pusher;
Channel channel;
pusher = new PusherClient(
"adb844af65547f4a67cf",
PusherOptions(
cluster: "mt1",
),
enableLogging: true,
);
channel = pusher.subscribe("my-channel-chat");
pusher.onConnectionError((error) {
print("error: ${error!.message}");
});
channel.bind('my-event-chat', (event) {
// print(event!.data.toString());
final data = jsonDecode(event!.data.toString());
print (data);
});
}
You will need to put a comma at the end of the line to make it valid JSON. Currently it is:
{
"sender":"you"
"message":"Something to say"
"time":"00.00"
}
Try with
{
"sender":"you",
"message":"Something to say",
"time":"00.00"
}
You can use services such as https://jsonlint.com/ to check whether your JSON is valid.

How to get Public IP in Flutter?

In my case, i need public IP Address. But, after research almost all documentary related to Local IP like: Get_IP, I want something like 202.xxx not 192.168.xxx. Can someone give some advice?
As far as I'm aware, there's no way to get the public IP of a device from within that device. This is because the vast majority of the time, the device doesn't know it's own public IP. The public IP is assigned to the device from the ISP, and your device is usually separated from the ISP through any number of modems, routers, switches, etc.
You need to query some external resource or API (such as ipify.org) that will then tell you what your public IP is. You can do this with a simple HTTP request.
import 'package:http/http.dart';
Future<String> getPublicIP() async {
try {
const url = 'https://api.ipify.org';
var response = await http.get(url);
if (response.statusCode == 200) {
// The response body is the IP in plain text, so just
// return it as-is.
return response.body;
} else {
// The request failed with a non-200 code
// The ipify.org API has a lot of guaranteed uptime
// promises, so this shouldn't ever actually happen.
print(response.statusCode);
print(response.body);
return null;
}
} catch (e) {
// Request failed due to an error, most likely because
// the phone isn't connected to the internet.
print(e);
return null;
}
}
EDIT: There is now a Dart package for getting public IP information from the IPify service. You can use this package in place of the above manual solution:
import 'package:dart_ipify/dart_ipify.dart';
void main() async {
final ipv4 = await Ipify.ipv4();
print(ipv4); // 98.207.254.136
final ipv6 = await Ipify.ipv64();
print(ipv6); // 98.207.254.136 or 2a00:1450:400f:80d::200e
final ipv4json = await Ipify.ipv64(format: Format.JSON);
print(ipv4json); //{"ip":"98.207.254.136"} or {"ip":"2a00:1450:400f:80d::200e"}
// The response type can be text, json or jsonp
}
I recently came across this package dart_ipify that can do this work.
https://pub.dev/packages/dart_ipify
Here is an example:
import 'package:dart_ipify/dart_ipify.dart';
void main() async {
final ipv6 = await Ipify.ipv64();
print(ipv6); // 98.207.254.136 or 2a00:1450:400f:80d::200e
}
I came across this topic recently.
After investigating the issue, I found a solution using an external API.
I am using ipstack, it has a generous free tier.
Request a free access key
Make the following POST call
http://api.ipstack.com/check?access_key=YOUR_ACCESS_KEY
You can extract the ip parameter from the response

socket.io for react native (sending query problems)

I'm using this library and i can connect without problems.
Usually when I have worked with sockets the code that ever i used is:
socket = io.connect(url, { query: ‘token=’ + token});
and i can see this info reading socket.request._query
Using socket.io for react native i'm trying to send params:
this.socket = new SocketIO('http://localhost:3000', { query: ‘token=’ + token});
but in socket.request._query only can see this log:
{ transport: 'polling', b64: '1' }
In the library some options are mentioned like: connectParams. But i don't know how i can see the info
Related: link
It's not pretty detailed in the repo, but connectParams is a key/value object, and furthermore the values you sent in it will be appended in the url, as shown here:
if connectParams != nil {
for (key, value) in connectParams! {
let keyEsc = key.urlEncode()!
let valueEsc = "\(value)".urlEncode()!
queryString += "&\(keyEsc)=\(valueEsc)"
}
}
>Source<
So, you should try using connectParams like this(though I'm not sure how you tried it before):
this.socket = new SocketIO('http://localhost:3000', {
connectParams: {
myAwesomeQueryStringParam: "someRandomValue"
}
});
PS: forgive me, my english is pretty bad

UCWA: Unable to send/Receive formatted text

I have a simple chat application working fine with plain text implemented using UCWA api in a ASP.Net MVC web application. I have to implement a formatted text next.
Referring to UCWA: integrating advanced chat options
, I go to know that, before sending the message to using ucwa.Transport.clientRequest we have to set the contentType to text/html which currently is text/plain.
So i have the function to send a message as shown below:
function sendMessage(displayName, msg, timestamp) {
var encodedMsg = encodeURIComponent(msg);
ucwa.Transport.clientRequest({
url: messagingLinks.SendMessage + "?SessionContext=" + ucwa.GeneralHelper.generateUUID(),
type: "post",
contentType: "text/html",
data: encodedMsg,
callback: function () {
addMessageToChat(displayName, encodedMsg, timestamp);
}
});
}
The implementation of handleMessage() is as shown below:
function handleMessage(data, parts) {
alert("Inside Handle message");
if (!data._embedded.message._links.plainMessage) return false;
var message = decodeMessage(data._embedded.message._links.plainMessage.href);
var decodedMsg = decodeURIComponent(message);
addMessageToChat(data._embedded.message._links.participant.title, decodedMsg, formatTime(new Date(Date.now())));
}
The problem in the above implementation is that, on the receiving end, the handleMessage() method is not entered which means i'm not receiving the incoming message.
Can anyone point me where i'm going wrong and Are the any other changes i need to do along with the above changes, so that i can send a formatted text across. A sample will be really helpful regarding the same.
Any suggestion would also be good enough. Thanks in advance.
Edit:
As suggested i have modified my makeMeAvailable method. below is the definition of the same in Authentication.js:
function makeMeAvailable() {
if (!_authenticated) {
cache.read({
id: "main"
}).done(function (cacheData) {
if (cacheData) {
var data = {
SupportedModalities: ["Messaging"],
supportedMessageFormats: ["Plain","Html"]
};
transport.clientRequest({
url: cacheData._embedded.me._links.makeMeAvailable.href,
type: "post",
data: data,
callback: handleState
});
}
});
} else {
handleState({
status: 204
});
}
}
However, the output is still the same.
The second suggestion regarding the communication API, i'm unable to locate it.
Any suggestions with this?
Here are two reasons I did not receive messages sent through UCWA API:
Charset: Default value was ISO-8859-1, I had to use UTF-8 to receive any message.
Negotiated message formats: The receiving contact only supported plain message format, but the messages were sent with text/html content type.
When it comes to the messaging formats in UCWA it should be known that by default all endpoints that support the messaging modality by default support plain messages. It is interesting to note that this limitation does not prevent sending of HTML formatted messages as you have seen in your examples.
There are two ways to enable HTML formatted messages as follows:
When issuing a request to makeMeAvailable supply an SupportedMessageFormats (array) and include Html
Issue a PUT request to communication and include Html in SupportedMessageFormats
Until either 1 or 2 has executed successfully it will be impossible to receive HTML formatted messages.

Meteor: Saving images from urls to AWS S3 storage

I am trying, server-side, to take an image from the web by it's url (i.e. http://www.skrenta.com/images/stackoverflow.jpg) and save this image to my AWS S3 bucket using Meteor, the aws-sdk meteorite package as well as the http meteor package.
This is my attempt, which indeed put a file in my bucket (someImageFile.jpg), but the image file is corrupted then and cannot be displayed by a browser or a viewer application.
Probably I am doing something wrong with the encoding of the file. I tried many combinations and none of them worked. Also, I tried adding ContentLength and/or ContentEncoding with different encodings like binary, hex, base64 (also in combination with Buffer.toString("base64"), none of them worked. Any advice will be greatly appreciated!
This is in my server-side-code:
var url="http://www.skrenta.com/images/stackoverflow.jpg";
HTTP.get(url, function(err, data) {
if (err) {
console.log("Error: " + err);
} else {
//console.log("Result: "+JSON.stringify(data));
//uncommenting above line fills up the console with raw image data
s3.putObject({
ACL:"public-read",
Bucket:"MY_BUCKET",
Key: "someImageFile.jpg",
Body: new Buffer(data.content,"binary"),
ContentType: data.headers["content-type"], // = image/jpeg
//ContentLength: parseInt(data.headers["content-length"]),
//ContentEncoding: "binary"
},
function(err,data){ // CALLBACK OF HTTP GET
if(err){
console.log("S3 Error: "+err);
}else{
console.log("S3 Data: "+JSON.stringify(data));
}
}
);
}
});
Actually I am trying to use the filepicker.io REST API via HTTP calls, i.e. for storing a converted image to my s3, but for this problem this is the minimum example to demonstrate the actual problem.
After several trial an error runs I gave up on Meteor.HTTP and put together the code below, maybe it will help somebody when running into encoding issues with Meteor.HTTP.
Meteor.HTTP seems to be meant to just fetch some JSON or text data from remote APIs and such, somehow it seems to be not quiet the choice for binary data. However, the Npm http module definitely does support binary data, so this works like a charm:
var http=Npm.require("http");
url = "http://www.whatever.com/check.jpg";
var req = http.get(url, function(resp) {
var buf = new Buffer("", "binary");
resp.on('data', function(chunk) {
buf = Buffer.concat([buf, chunk]);
});
resp.on('end', function() {
var thisObject = {
ACL: "public-read",
Bucket: "mybucket",
Key: "myNiceImage.jpg",
Body: buf,
ContentType: resp.headers["content-type"],
ContentLength: buf.length
};
s3.putObject(thisObject, function(err, data) {
if (err) {
console.log("S3 Error: " + err);
} else {
console.log("S3 Data: " + JSON.stringify(data));
}
});
});
});
The best solution is to look at what has already been done in this regard:
https://github.com/Lepozepo/S3
Also filepicker.so seems pretty simple:
Integrating Filepicker.IO with Meteor