how to maintain a connexion to send realtime data to distant client without request - sockets

i'm developing a mobile project the can control a home an receve information from it either from inside or outside of the house. im setting up a port forwarding mechanism on my router to connect to my server if i'm using my application from the outside.
i think that the fact of receving data from the server should be initiated by the client (android app) witch is in an other notwork or it will be blocked.
* is there a solution to receve data (temperature) in real time from the outside simply by just requesting once or i should send a request like evrey minute? * i'm confused because some applications like video streaming receve data from servers by just starting the video player then it receve udp packets automaticly
more spicificlly can i send data from a server to a distant client by just sending a request once (maybe by letting the socket open for every client, VPN , SIP)???

Sending Data to Distant Clients: Securely & Reliably
There is only one reasonably-reliable method for sending a signal to distant clients. I want to confirm your original assumption of sending to clients without request, this is theoretically impossible as the device needs to call home somewhere and notify a broker gateway (SIP) or otherwise of it's address. However please ignore that because the right way will be relayed here with source code.
Security Importance
It is important to realize that opening your firewall is outside of good practices. It is better to hold onto the firewall's lockdown rules for inbound traffic. The following section is a secure method that will allow you to open an outbound connection with maximum security preventing snooping and other unsafe security holes.
Download Android Source Libraries
See instructions here for downloading Android Source Library Files: https://github.com/pubnub/java/tree/master/android
Receiving Data On-Demand from a Distance on Android
You'll need to copy/paste the following code to get things moving forward quickly. Start by taking this Java code and pasting it into your app. Then follow by downloading the library files.
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// ANDROID PHONE
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Pubnub pubnub = new Pubnub(
"", // PUBLISH_KEY (Optional, supply "" to disable)
"demo", // SUBSCRIBE_KEY (REQUIRED)
"", // SECRET_KEY (Optional, supply "" to disable)
"", // CIPHER_KEY (Optional, supply "" to disable)
true // SSL_ON?
);
Hashtable args = new Hashtable(1);
args.put( "channel", "distant-client-ABC-DEF" );
pubnub.subscribe(args, new Callback() {
public void connectCallback(String channel) {
System.out.println("CONNECT on channel:" + channel);
}
public void disconnectCallback(String channel) {
System.out.println("DISCONNECT on channel:" + channel);
}
public void reconnectCallback(String channel) {
System.out.println("RECONNECT on channel:" + channel);
}
public void successCallback(String channel, Object message) {
System.out.println(channel + " " + message.toString());
}
public void errorCallback(String channel, Object message) {
System.out.println(channel + " " + message.toString());
}
});
Send Data On-demand to the Distant Client
On a Java VM on your home computer/systems, you may use the same code to send data securely to the remote distant client. Use the following code to do this:
Download JVM Server Source Libraries
See instructions here for downloading/using JVM Server Source Library Files: https://github.com/pubnub/java/tree/master/java
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// HOME SERVER
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Pubnub pubnub = new Pubnub(
"demo", // PUBLISH_KEY (REQUIRED on Server)
"demo", // SUBSCRIBE_KEY (REQUIRED)
"", // SECRET_KEY (Optional, supply "" to disable)
"", // CIPHER_KEY (Optional, supply "" to disable)
true // SSL_ON?
);
Hashtable args = new Hashtable(1);
args.put( "channel", "distant-client-ABC-DEF" ); // SEND TO CLIENT ABC-DEF
pubnub.publish(args, new Callback() {
public void successCallback(String channel, Object message) {
System.out.println("PUBLISH : " + message);
}
public void errorCallback(String channel, Object message) {
System.out.println("PUBLISH : " + message);
}
});

I'm not into Android world, but isn't it the service you're looking for ? : http://developer.android.com/google/gcm/index.html

Related

Unity Multiplayer: Standalone client

I'm looking into Unity multiplayer support. From all docs it seems like the main model is for a game to be capable of being both the server and the client, and the same binary used for both.
Would it be possible to make a game where the client and the server are two different binaries: client being more lightweight and only doing the client part, while server doing heavy lifting of handling the open world/gameplay/state etc.?
As a simplified example imagine a huge world populated by characters, and the client is a mobile app that only needs to display their health/stats and render their avatar. While on the server those characters live a complex life in a large environment.
You could use something like SmartFoxServer (supports unity3d) for the server operations completely independent of the client side logic. This is going to be C# Unity on the client and Java for SmartFoxServer. It is pretty easy to configure extensions, manage rooms, lobby, user events, chats etc in the server and get the events on the client side. You can build a complete MMO system and run it on mobile too.
So I believe I found a way, at least it's working for me.
What I need is possible using NetworkClient and NetworkServer classes. So now I have two separate projects, server and client.
Server has a script which is pretty much:
public class Server : MonoBehaviour {
public Text text;
public class HelloMessage : MessageBase
{
public string helloText;
}
void Start () {
NetworkServer.Listen(4444);
NetworkServer.RegisterHandler(333, onHelloMessage);
}
public void onHelloMessage(NetworkMessage msg)
{
text.text = msg.ReadMessage<HelloMessage>().helloText;
}
}
This listens for messages on port 4444.
Then the client side is like this:
public class NetworkManager : MonoBehaviour {
NetworkClient client;
public class HelloMessage : MessageBase
{
public string helloText;
}
// Use this for initialization
void Start () {
client = new NetworkClient();
client.Connect("127.0.0.1", 4444);
}
public void SendNetworkMessage()
{
HelloMessage msg = new HelloMessage();
msg.helloText = "Hello";
client.Send(333, msg);
}
}
Now on the server side we can hook up text to a label and on the client side SendNetworkMessage to a button and we can send messages from client to appear on the server.
Now just need to define a protocol and off we go.

How to keep chat history locally on android?

I am using openfire and aSmack for my chat application.
I am able to send and receive messages using aSmack library.
Can anyone tell me how to keep these messages in local(android) storage, so that whenever user opens application next time, he can see his previous chat history ? Is there any api provided by aSmack/Smack ?
Simply register a packet listener and interceptor and log the messages to the backing store of your choice.
use packetListener as:
PacketFilter gc_filter = new MessageTypeFilter(Message.Type.groupchat);
XMPPconnection.addPacketListener(new PacketListener()
{
public void processPacket(Packet packet)
{
final Message message = (Message) packet;
String body = message.getBody();
String from_jid = message.getFrom();
// save it in data base
}
)};

A socket operation was attempted to an unreachable network [2a00:1450:4013:c01::6d]:993 when receiving Gmail email with S22 ImapClient

I'm trying to receive email from Gmail. Occaisionly (approx 1 out of 5 times) I get a System.Net.Sockets.SocketException, error message:
A socket operation was attempted to an unreachable network [2a00:1450:4013:c01::6d]:993
The network address is not always the same, but varies slightly. This error does appears occaisonally on all the Gmail boxes I want to check, but does not appear on my Office 365 mailbox at all.
My app is an MVC 5 applications hosted by Microsoft Azure. I use the S22 Imap library
The relevant part of the code to retrieve the email is:
using S22.Imap;
ImapClient Client;
List<MailMessage> NewMessages;
try
{
Client = new ImapClient(tenant.ImapHostName,
tenant.ImapPortNumber,
tenant.ImapUserName,
tenant.ImapPassword,
AuthMethod.Login, tenant.UseSsl);
}
catch (Exception e)
{
return;
}
try
{
NewMessages = GetUnseenMessages(Client);
}
catch (Exception e)
{
}
I've disable IPv6 on my Azure webservice (disabled it on the adapter) but still this error comes back over and over again.
imap.gmail.com returns several IP addresses (three right now, but the number might vary depending on time and location). You're supposed to try all three. If one fails in the manner you see, you're supposed to try the next address, so your next step is to find out whether S22 does that, and if not, how you can make that happen.
I had the same problem as OP and did following to retry multiple IP addresses with S22.Imap.dll
var ips = Dns.GetHostAddresses("imap.gmail.com");
foreach(var ip in ips)
{
try
{
return new ImapClient(ip.ToString(), "993", Email, Password, AuthMethod.Login, true);
}
catch(SocketException e) //error means server is down, try other IP
{
//nothing, check next IP for connection
}
}

keep all connected clients' ip in netty

My TCP server uses netty.The situation is: When a client connects to the server,I will save the client's ip in a global variable(such as a Map); When the client is disconnected,I will remove the IP from the map.
I used channelConnected() and channelDisconnected() method in SimpleChannelHandler.But my problem is ,some times the channelDisconnected() method cannot catch the event when I think the client is disconnected(maybe the computer closed,or the client process closed,or some other situations...) Can you give me some suggestions.
Just use DefaultChannelGroup which will automatically remove the Channel from it when it was closed.
Alternative you can register a ChannelFutureListener to the Channels close future to do the removal from your map.
Something like this:
channel.getCloseFuture().addListener(new ChannelFutureListener() {
public void operationCompleted(ChannelFuture f) {
map.remove(f.getChannel());
}
});

Any off the shelf app to rebroadcast tcp packets?

I am working with a 3rd party device which opens a tcp port that only allows one connection at a time. If my app connects to the port, all other connections are denied.
I'd like to find an app that basically connects to this port, then allows others to connect to it on a different port.
Any data sent out of the device's port is then rebroadcast to any connected client.
I know how to write such an app, but it seems like it would be something someone else has already thought off and written it & shared, and I could avoid taking the time to write it.
basicaly code would be:
1) start a tcp socket server, binding to TO_PORT (clients connect to this)
2) connect as a client to DEVICE_IP:DEVICE_PORT
3) when data is read into a buffer from DEVICE_IP:DEVICE_PORT, the buffer content is resent to each connected client.
4) everything else that makes it a stable, working program.
This is for windows, and I'd prefer it not require a java install.
My google skills have failed me.
Anyone know of such an app?
Not a complete solution for you, but might be interesting, though
http://www.codeproject.com/KB/IP/serversocket.aspx
http://www.codeproject.com/KB/IP/UniversalTCPSocketClass.aspx
Guess I'll answer my own question.
I implemented the solution my self.
Key points to my solution:
A class named IPClient which wraps up a TcpClient instance, uses async model of calling TcpClient.BeginConnect, BeginRead, etc. It has a Timer used for reconnecting if it loses connection.
This is the class that connects to the device.
It's public interface would look something like this:
public class IPClient{
public event EventHandler<MyConnectedArgs> Connected;
public event EventHandler<MyDisconnectedArgs>Disconnected;
public event EventHandler<MyDataReceivedArgs> DataReceived;
public bool Connect(string address, int port){...}
public bool Disconnect() {...}
}
To open the port that would allow other clients to connect, I used this library: http://codeproject.com/KB/IP/BasicTcpServer.aspx and modified it a bit.
It's job was to open a port, accept connections, and do the following:
in the Connected handler, start the listening port
in the Disconnected handler, stop the listening port
in the DataReceived handler, broadcast the data to any connected clients.
I'll leave out the rest of the boring details, but say it wasn't "too hard", and eventually I just had to roll my own.
command line usage: myapp.exe remote_addr remote_port listen_port
psuedocode/main idea of my program main:
static int Main(string[] args){
//SetConsoleCtrlHandler(my callback re: ctrl+C,etc)
//get command line params
var ipClient = new IPClient();
var myprovider = MyTcpServiceProvider();
var server = new TcpServer(myProvider, listenPort);
ipClient.Connected += (sender, e) => server.Start();
ipClient.Disconnected += (sender,e) => server.Stop();
ipClient.DataReceived += (sender,e)=> provider.BroadcastToClients(e.Data);
ipClient.Connect(remoteAddress, remotePort);
//wait for Ctrl+C or program exit
//shutdown code,etc
return 0;
}