Android UDP Client - javascript

So I made a simple UDP Client for android, and for some reason it doesn't want to work. I've been struggling with this for like 5 hours now, and I can't find the problem. I even looked almost all the tutorials on the internet, to compare the codes, but I had no luck.
String serverString = "192.168.1.109";
int port = 7777;
Log.d("adam", "Debug");
DatagramSocket socket = null ;
String msg = "Hello World!";
try {
socket = new DatagramSocket() ;
InetAddress host = InetAddress.getByName(serverString);
byte [] data = msg.getBytes() ;
DatagramPacket packet = new DatagramPacket( data, data.length, host, port );
Log.d("adam", "Debug2");
socket.send(packet) ;
Log.d("adam", "Packet sent" );
} catch( Exception e )
{
Log.d("adam", "Exception");
Log.e("adam", Log.getStackTraceString(e));
}
finally
{
if( socket != null ) {
socket.close();
}
}
My mainfest:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
Here is the debug img:
As you can see the "Packet sent" text is not in the logcat. So the problem is probably with the send() function. Any idea what could be the problem?

Never ever run networking on the main thread. Do not do the work around that Mark suggests.
When you send data you should use an ASyncTAsk or a Thread.
Here is a very simple threaded function:
Thread sendDate = new Thread() {
#Override
public void run() {
String serverString = "192.168.1.109";
int port = 7777;
Log.d("adam", "Debug");
DatagramSocket socket = null ;
String msg = "Hello World!";
try {
socket = new DatagramSocket() ;
InetAddress host = InetAddress.getByName(serverString);
byte [] data = msg.getBytes() ;
DatagramPacket packet = new DatagramPacket( data, data.length, host, port );
Log.d("adam", "Debug2");
socket.send(packet) ;
Log.d("adam", "Packet sent" );
} catch( Exception e )
{
Log.d("adam", "Exception");
Log.e("adam", Log.getStackTraceString(e));
}
finally
{
if( socket != null ) {
socket.close();
}
}
}
};
sendDate.start();
If you want to tell the user if the data was sent then you should use an ASyncTask

Related

WebSocket - After sending the second message I got: A server must not mask any frames that it sends to the client

I'm receiving first message Successfully, but the second ( same message ) i got the Error :
A server must not mask any frames that it sends to the client.
Its only one client.
private void RunWebSocketListener()
{
int websocket_port = 8996;
TcpListener websocket = new TcpListener(Address, websocket_port);
websocket.Start();
bool websocket_isRunning = true;
while (websocket_isRunning)
{
Console.WriteLine("--- Waiting for WebSocket ----");
TcpClient websocket_client = websocket.AcceptTcpClient();
NetworkStream sockStream = websocket_client.GetStream();
byte[] bRead = new byte[1024];
sockStream.Read(bRead, 0, bRead.Length);
Console.WriteLine("---- Reading WebSocket ----");
string websocket_header = Encoding.UTF8.GetString(bRead);
string matchs = new System.Text.RegularExpressions.Regex("Sec-WebSocket-Key: (.*)").Match(websocket_header).Groups[1].Value.Trim() + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
string finakAcceptedKey = Convert.ToBase64String(System.Security.Cryptography.SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(matchs)));
// write response
string responseHeader = "";
responseHeader += "HTTP/1.1 101 Switching Protocols\r\n";
responseHeader += "Connection: Upgrade\r\n";
responseHeader += "Upgrade: websocket\r\n";
responseHeader += "Sec-WebSocket-Accept: "+ finakAcceptedKey +"\r\n";
responseHeader += "\r\n";
byte[] sendResponse = Encoding.UTF8.GetBytes(responseHeader);
sockStream.Write(sendResponse, 0, sendResponse.Length);
bool clientConnected = true;
while (clientConnected)
{
byte[] msg = this.encodeMessage("{ \"msg\": \"Your message\" }");
// The Problem Writing on a Second time
sockStream.Write(msg);
Console.WriteLine("--- msg Sent "+ msg.Length +" Bytes ---");
Thread.Sleep(2000);
}
Thread.Sleep(2000);
}
}
#IOException on C#:
Unable to write data to the transport connection: An established
connection was aborted by the software in your host machine..
JavaScript:
var websocket = new WebSocket("ws://LOCAL:PORT");
websocket.onopen = ....
websocket.onmessage = function(e) { console.log(e.data); }
#JavaScript Error:
failed: A server must not mask any frames that it sends to the client.
Do You Receive the first Message ? [ Yes i do ].
AcceptTcpClient To AcceptSocket [ not working ].
I'm using Sleep 2 seconds [ not working ].
new Threads [ not working ].
Fixed,
The this.encodeMessage method i was return a larger bytes,
byte[] b = new byte[message.length + 5]
To:
byte[] b = new byte[message.length + 2]

Sending binary data by socket between C# and Js

I'm trying to send binary data between server (C#) application and client (js-application -- made by WebSocket). Connection between server and client is established and handshake is OK. Messages from client are receiving by server, but when I'm trying to send binary data to client, the event "onmessage" doesn't work.
This is fragments of my C# code. Sending binary data in "sendFile" function.
class Listener
{
private IPAddress ip;
private int port;
private TcpListener server;
private TcpClient client;
private NetworkStream stream;
private bool isSuccHandshaked;
public Listener()
{
ip = IPAddress.Loopback;
port = 8080;
server = new TcpListener(ip, port);
isSuccHandshaked = false;
}
private void makeHandshake()
{
//...
}
private String decodeMessage(Byte[] bytes)
{
//...
}
private void sendFile()
{
Byte[] dataToSend = File.ReadAllBytes("test.txt");
stream.Write(datatosend, 0, datatosend.Length);
stream.Flush();
}
public void startListen()
{
server.Start();
Console.WriteLine("Server has started on {0}. Port: {1}. {2}Waiting for a connection...", ip, port, Environment.NewLine);
client = server.AcceptTcpClient();
Console.WriteLine("A client connected.");
stream = client.GetStream();
while (!isSuccHandshaked)
{
makeHandshake();
}
while (true)
{
if (client.Available > 0)
{
Byte[] bytes = new Byte[client.Available];
stream.Read(bytes, 0, bytes.Length);
String message = decodeMessage(bytes);
sendFile();
}
}
}
}
}
and js-code:
var address = 'ws://localhost:8080';
var socket = new WebSocket( address );
socket.binaryType = "arraybuffer";
socket.onopen = function () {
alert( 'handshake successfully established. May send data now...' );
socket.send( "Aff" );
};
socket.onclose = function () {
alert( 'connection closed' );
};
socket.onmessage = function ( evt ) {
console.log( "Receive message!" );
console.log( "Got ws message: " + evt.data );
}
Maybe there is some peculiar properties in receiving data with WebSocket protocol? Wich useful approaches to send binary data from C# code to js you can recommend?
A websocket is not a raw TCP socket. It uses HTTP negotiation and its own framing protocol you have to comply with. If you are interested in writing your own server in C# take a look at this.
However if you only want to use them, you can either use the default Microsoft implementation with IIS, or you can use one of the many standalone websockets components. I maintain one named WebSocketListener.

How to Complete a WebSocket Handshake?

I'm making a website with a game on it. For the game i need to send data trought sockets. Everything is working fine with loading the page but I can't get the handshaking to work.
class ServerClient {
public ServerClient() {
handshake();
}
private void handshake() {
try {
String line;
String key = "";
boolean socketReq = false;
while (true) {
line = input.readLine();
if (line.startsWith("Upgrade: websocket"))
socketReq = true;
if (line.startsWith("Sec-WebSocket-Key: "))
key = line;
if (line.isEmpty())
break;
}
if (!socketReq)
socket.close();
String encodedKey = DatatypeConverter.printBase64Binary(
MessageDigest.getInstance("SHA-1")
.digest((key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes()));
System.out.println(encodedKey);
output.println("HTTP/1.1 101 Switching Protocols");
output.println("Upgrade: websocket");
output.println("Connection: Upgrade");
output.println("Sec-WebSocket-Accept: " + encodedKey);
output.flush();
output.close(); // output = new PrintWriter(
// Socket.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
}
The socketReq variable is there because I don't want anyone to connect to localhost:25580 straight from their browser.
My send and receive functions are in different Threads and they will be started after the handshake.
The result of new WebSocket("ws://localhost:25580") in JS is
WebSocket connection to 'ws://localhost:25580/' failed: Error during WebSocket handshake: net::ERR_CONNECTION_CLOSED
I was having
Error during WebSocket handshake: Incorrect 'Sec-WebSocket-Accept' header value
but I guess I changed something in the code.
I searched for hours trought Article 1 and Article 2 and from other sites. Just couldn't get the whole thing to work properly.
I don't get the point of the keys and why we have to encode them.
The socket is connected to the browser and I am getting the headers from it.
Host: localhost:25580
Sec-WebSocket-Key: iWLnXKrA3fLD6h6UGMIigg==
How does the handshaking work?
You are getting a net::ERR_CONNECTION_CLOSED error, because you are closing the connection with output.close().
If you want to keep the connection open, obviously don't close it during a handshake.
Done!
Found the answers from http://blog.honeybadger.io/building-a-simple-websockets-server-from-scratch-in-ruby/ and It's working perfectly!
The code:
public ClientSocket(Socket socket) {
try {
this.socket = socket;
this.input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
this.output = new PrintWriter(socket.getOutputStream());
handshake();
}
private void handshake() {
try {
String line;
String key = "";
while (true) {
line = input.readLine();
if (line.startsWith("Sec-WebSocket-Key: ")) {
key = line.split(" ")[1];
System.out.println("'" + key + "'");
}
if (line == null || line.isEmpty())
break;
}
output.println("HTTP/1.1 101 Switching Protocols");
output.println("Upgrade: websocket");
output.println("Connection: Upgrade");
output.println("Sec-WebSocket-Accept: " + encode(key));
output.println();
output.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
private String encode(String key) throws Exception {
key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
byte[] bytes = MessageDigest.getInstance("SHA-1").digest(key.getBytes());
return DatatypeConverter.printBase64Binary(bytes);
}
Now I just have to decode the messages.

Problems with RabbitMQ and web-stomp

I'm using RabbitMQ and web-stomp in the web browser according to this tutorial:
https://www.rabbitmq.com/web-stomp.htm
I succeded to connect and the get messages in the browser.
But,
the message I sent and consumed in the client is still in the queue and not being dequeing(I did manual ack and auto ack), it still exists.
when I subscribe to a queue I'm not getting all the messages in the queue, but only the last.. only when the websocket is open and then the server send the message i get the last message but not the old ones.
The server Code:
private static final String EXCHANGE_NAME = "amq.topic";
public static void AddToQueue(String RoutingKey, String message) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "topic");
channel.basicPublish(EXCHANGE_NAME, RoutingKey, null, message.getBytes());
channel.close();
connection.close();
}
The client code:
var ws = new SockJS('http://' + window.location.hostname + ':15674/stomp');
$scope.client = Stomp.over(ws);
$scope.client.heartbeat.outgoing = 0;
$scope.client.heartbeat.incoming = 0;
var on_connect = function(x) {
$scope.client.subscribe("/topic/status", function(d) {
console.log(d.body);
});
};
var on_error = function() {
console.log('error');
};
$scope.client.connect('guest', 'guest', on_connect, on_error, '/');
Thanks.
Solved it, the exchange name needs to be "amq.topic"

Why does my websocket close after a few minutes?

I'm using ws with node.js on the server side and the regular WebSocket API on the client side. Opening the connection and messaging a few times back and forth works fine. But the socket always closes after a minute or two. Aren't they supposed to persist? Am I doing something wrong?
My server is node.js hosted on heroku. I just tested locally again using foreman start (the heroku tool to run the server locally) and the socket doesn't close unexpectedly at all, so perhaps it's a misconfiguration on heroku. Anyway, here's a relevant code sample with a few functions omitted for brevity.
I'm testing the application in Chrome on OSX Yosemite but have seen the same behavior in Chrome on Windows 7 when running against production environment.
server:
// Client <-> Host Protocol functions. Move to a different file so that they can be shared.
var C2H_SIGNAL_TYPE_REGISTER = "register";
var H2C_SIGNAL_WELCOME = "welcome";
var H2C_SIGNAL_TYPE_ERROR = "error";
var H2C_SIGNAL_TYPE_PEER_ADDED = "peer_joined";
var H2C_SIGNAL_TYPE_PEER_LEFT = "peer_left";
// Update channel endpoint names.
var UPDATE_ENDPOINT_PEERS = "/peers";
// Create a signal message with all asociated default properties.
// Signal senders should create this object and update it accordingly when
// building a signal message to send to a peer.
function createHostMsg(type)
{
var msg = { signalType: type };
if ( type == H2C_SIGNAL_WELCOME ) {
// Since we're sending a welcome message, we need to provide a list
// of currently connected clients.
msg.peers = {};
for ( var addr in clients ) {
console.log("addr " + addr);
var c = clients[addr].description;
if ( c && c.id ) {
msg.peers[c.id] = c;
}
}
}
return msg;
}
// require modules.
var express = require('express');
var http = require('http');
var bodyParser = require('body-parser');
var multer = require('multer');
// Tracks connected peers.
var clients = { };
// 1. Configure the application context settings.
var app = express();
app.enable('trust proxy');
app.use(express.static(__dirname + '/public'));
app.use(bodyParser.json()); // parse json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
app.use(multer()); // for parsing multipart/form-data
// a. configure http routers. these will handle requests coming from app.
app.set('port', (process.env.PORT || 5000));
app.get('/app', peerApp);
app.get('/script/:name', publicScriptRouter);
// 2. Create the http server itself, passing app to be the request handler.
// app will handle routing and multiplexing of incoming requests to different
// route middleware handlers.
var http = require('http');
var WebSocketServer = require("ws").Server
var httpServer = http.createServer(app);
httpServer.listen( app.get('port') );
// 3. Create one of these for all socket endpoints.
var wss = new WebSocketServer( { server: httpServer, path: UPDATE_ENDPOINT_PEERS } );
wss.on("connection", function(webSocket) {
// 1. Associate the socket with the remote address it came from.
var remoteAddress = webSocket._socket.remoteAddress;
var remotePort = webSocket._socket.remotePort;
var clientConnID = remoteAddress + ":" + remotePort;
var exists = clients[clientConnID] != null;
if ( exists ) {
console.log("socket server connection: associating new connection from %s with registered peer.", clientConnID);
clients[clientConnID].socket = webSocket;
} else {
console.log("socket server connection: associating new connection from %s with unregistered peer.", clientConnID);
clients[clientConnID] = { description: null, socket: webSocket };
}
// 2. Hook up handlers for communication over this particular socket.
webSocket.on("message", function(data, flags) {
processMessage(webSocket, data, flags);
});
webSocket.on("close", function() {
// Praise satin for closures!!
removePeer(clientConnID);
});
});
// Transduce the message and handle it accordingly.
function processMessage(socket, data, flags)
{
var msg = JSON.parse(data);
if ( !msg.signalType ) {
var msg = createHostMsg( H2C_SIGNAL_TYPE_ERROR );
msg.errStr = "message_malformed";
socket.send( JSON.stringify( msg ) );
} else if ( msg.signalType == C2H_SIGNAL_TYPE_REGISTER ) {
handleRegistration(socket, msg);
}
}
client:
function initSignalChannel()
{
rtcPeer.channel = new WebSocket( location.origin.replace(/^http/, 'ws') + "/peers" );
rtcPeer.channel.onmessage = updateChannelMessage;
rtcPeer.channel.onopen = function(event) {
console.log("remote socket opened");
}
rtcPeer.channel.onclose = function(event) {
console.log("host closed remote socket.");
}
}
function updateChannelMessage(event) {
var msgObj = JSON.parse(event.data);
if ( !msgObj || !msgObj.signalType ) {
console.log("updateChannelMessage: malformed response!! %o", msgObj );
} else if ( msgObj.signalType == "welcome" ) {
console.log("updateChannelMessage: received welcome from host.");
handleWelcome(msgObj);
} else if ( msgObj.signalType == "peer_joined" ) {
console.log("updateChannelMessage: received peer_joined from host.");
if ( msgObj.peer.id == rtcPeer.description.id ) {
console.log("updateChannelMessage: peer_joined: received notification that I've been added to the room. " + msgObj.peer.id);
console.log(msgObj);
} else {
console.log("updateChannelMessage: peer_joined: peer %s is now online.", msgObj.peer.id);
console.log(msgObj);
addRemotePeer( msgObj.peer );
}
}
}
function addRemotePeer(peerObj)
{
remotePeers[peerObj.id] = peerObj;
var ui = createPeerUIObj(peerObj);
$("#connectedPeerList").append( ui );
}
function createPeerUIObj(peerObj)
{
var ui = null;
if ( peerObj ) {
ui = $("<li></li>");
var a = $("<a></a>");
a.append("peer " + peerObj.id);
ui.append(a);
ui.click(function(event) { console.log("clicked");});
}
return ui;
}
function handleWelcome(msgObj)
{
if ( msgObj.id ) {
console.log("updateChannelMessage: welcome: received id from host. " + msgObj.id);
console.log(msgObj);
rtcPeer.description.id = msgObj.id;
for ( var p in msgObj.peers ) {
addRemotePeer(msgObj.peers[p]);
}
} else {
console.log("updateChannelMessage: malformed response. no id.");
}
}
Thanks for the comments everyone. It turns out that jfriend00 had the right answer, I just didn't realize that the hosting service I was using wouldn't allow for the connection to be kept open.
From the below forum posting, the solution is
you'll need to make your clients ping the server periodically to keep the socket alive.
Not the most ideal situation, but indeed doable. Thanks for pointing me in the right direction.

Categories