I'm doing a mobile app for a website and they use Socket.io and Websocket to comunicate.
I'm using socket.io-java-client on Android to connect to the Socket.io server, the problem is, i don't know how to set custom headers / cookies with it.
here is how the code looks like:
public void runIO(){
try {
SocketIO socket = new SocketIO("http://192.168.1.60:1337");
socket.connect(new IOCallback() {
#Override
public void onMessage(JSONObject json, IOAcknowledge ack) {
try {
System.out.println("Server said:" + json.toString(2));
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onMessage(String data, IOAcknowledge ack) {
System.out.println("Server said: " + data);
}
#Override
public void onError(SocketIOException socketIOException) {
System.out.println("an Error occured");
socketIOException.printStackTrace();
}
#Override
public void onDisconnect() {
System.out.println("Connection terminated.");
}
#Override
public void onConnect() {
System.out.println("Connection established");
}
#Override
public void on(String event, IOAcknowledge ack, Object... args) {
System.out.println("Server triggered event '" + event + "'");
}
});
// This line is cached until the connection is establisched.
socket.send("Hello Server!");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
In fact there are simple functions that can be used to set headers before connection:
addHeader(String key, String value) and setHeaders(Properties headers)
You can also use SocketIO(final String url, Properties headers) (instead of SocketIO(final String url) that i was using):
// Haeader Properties initiation
private Properties headers = new Properties();
and then for exemple to set cookies:
headers.setProperty("Cookie","key=data;key2=data2");
Finally when connecting replace
this.socket = new SocketIO(val);
by
this.socket = new SocketIO(val,this.headers);
Related
I'm trying to write a JavaScript server running on NodeJS using Socket.io that communicates with the client which is written in JAVA.
I have no problem with the server side because I try it with a JavaScript client, so I assumed that the problem came from my java client.
I have this error on my client side :
io.socket.SocketIOException: Error while handshaking
at io.socket.IOConnection.handshake(IOConnection.java:322)
at io.socket.IOConnection.access$600(IOConnection.java:39)
at io.socket.IOConnection$ConnectThread.run(IOConnection.java:199)
Caused by: java.io.IOException: Server returned HTTP response code: 400 for URL: http://localhost:8000/socket.io/1/at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at io.socket.IOConnection.handshake(IOConnection.java:313)
This is my code(client side) :
public class BasicExample implements IOCallback {
private SocketIO socket;
public static void main(String[] args) {
try {
new BasicExample();
} catch (Exception e) {
e.printStackTrace();
}
}
public BasicExample() throws Exception {
socket = new SocketIO();
socket.connect("http://localhost:8000", this);
// Sends a string to the server.
socket.send("Hello Server");
// Emits an event to the server.
socket.emit("event", "ILYES");
}
#Override
public void onMessage(JSONObject json, IOAcknowledge ack) {
try {
System.out.println("Server said:" + json.toString(2));
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onMessage(String data, IOAcknowledge ack) {
System.out.println("Server said: " + data);
}
#Override
public void onError(SocketIOException socketIOException) {
System.out.println("an Error occured");
socketIOException.printStackTrace();
}
#Override
public void onDisconnect() {
System.out.println("Connection terminated.");
}
#Override
public void onConnect() {
System.out.println("Connection established");
}
#Override
public void on(String event, IOAcknowledge ack, Object... args) {
System.out.println("Server triggered event '" + event + "'");
}
}
I want use library
And I wan realize this functionality:
connect to my java server
Socket socket = IO.socket("http://127.0.0.1:4444");
socket.io().open(new Manager.OpenCallback() {
#Override
public void call(Exception err) {
if (err != null) {
Log.d("mylog", err.getMessage());
return;
}
Log.d("mylog", "connected");
}
});
Send messge - I do not understand how.
It is my server:
public class Server {
public static void main(String[] args) throws IOException {
System.out.println("Welcome to Server side");
BufferedReader in = null;
PrintWriter out= null;
ServerSocket servers = null;
Socket fromclient = null;
// create server socket
try {
servers = new ServerSocket(4444);
} catch (IOException e) {
System.out.println("Couldn't listen to port 4444");
System.exit(-1);
}
try {
System.out.print("Waiting for a client...");
fromclient= servers.accept();
System.out.println("Client connected");
} catch (IOException e) {
System.out.println("Can't accept");
System.exit(-1);
}
in = new BufferedReader(new
InputStreamReader(fromclient.getInputStream()));
out = new PrintWriter(fromclient.getOutputStream(),true);
String input,output;
System.out.println("Wait for messages");
while ((input = in.readLine()) != null) {
if (input.equalsIgnoreCase("exit")) break;
out.println("S ::: "+input);
System.out.println(input);
}
out.close();
in.close();
fromclient.close();
servers.close();
}
}
If I use Java client I can work with server, but I want to connect to android client. And I found only this library, and I not understand how it work. Examples in site not helped for me.
Make sure you have added its permission in your AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
Android's kernel, unlike mainline Linux kernel, restricts requests for creating sockets unless that application already has INTERNET permission.
Find more technical information about Android's Paranoid networking option in this link.
UPDATE #1
If you want to connect your Android client to the server on your PC localhost you should not use 127.0.0.1 as server IP address. This is Android its own localhost. You should instead use 10.0.2.2 as server IP address. More Info
#Pavel i've implemented SocketIO client for one of my app
here is the code... i think ..this may help u
private Socket mSocket;
/**
* chat socket connection methods
*/
public void socketConnection()
{
try
{
mSocket = IO.socket(Constant.CHAT_SERVER_URL);
mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectError);
mSocket.on("message", onSocketConnectionListener);
mSocket.connect();
}
catch (URISyntaxException e)
{
e.printStackTrace();
}
new Thread(new Runnable() {
#Override
public void run() {
while(mSocket.connected()==false)
{
//do nothing
}
sendConnectData();
}
}).start();
}
/**
* Send Data to connect to chat server
*/
public void sendConnectData()
{
JSONObject msgToSend=new JSONObject();
try
{
msgToSend.put("Type", 1);
msgToSend.put("userid", userid);
}
catch (Exception e)
{
e.printStackTrace();
}
mSocket.emit("message", msgToSend);
}
/**
* Listener for socket connection error.. listener registered at the time of socket connection
*/
private Emitter.Listener onConnectError = new Emitter.Listener() {
#Override
public void call(Object... args) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (mSocket != null)
if (mSocket.connected() == false)
socketConnection();
}
});
}
};
/**
* Listener to handle messages received from chat server of any type... Listener registered at the time of socket connected
*/
private Emitter.Listener onSocketConnectionListener = new Emitter.Listener() {
#Override
public void call(final Object... args) {
runOnUiThread(new Runnable() {
#Override
public void run() {
// handle the response args
}
});
}
};
This is the context:
A Java application subscribes to the Topic "ActiveMQ.Advisory.Connection" from an ActiveMQ 5.9.1 via MQTT (Paho 0.4.0):
public class SupervisorMqttClient implements MqttCallback {
private MqttClient client = null;
private MemoryPersistence persistence = null;
private MqttConnectOptions connOpts = null;
private final int STATUS_OK = 0;
private final int STATUS_ERROR = 1;
private String mqttServer = null;
private String clientId = null;
private int status = STATUS_OK;
public SupervisorMqttClient() {
try {
this.init();
} catch (MqttException e) {
Logger.error(e.getLocalizedMessage());
Logger.debug(e);
}
}
private void init() throws MqttException {
Properties props = PropertiesManager.getInstance("supervisor");
mqttServer = props.getProperty("supervisor.mqtt.server");
String supervisorID = props.getProperty("supervisor.mqtt.client.number");
clientId = Supervisor.APP_NAME+"-"+supervisorID;
connOpts = new MqttConnectOptions();
connOpts.setKeepAliveInterval(30);
connOpts.setCleanSession(true); // important non-durable
persistence = new MemoryPersistence();
client = new MqttClient(mqttServer, clientId, persistence);
connectAndSubscribe();
}
private void connectAndSubscribe() throws MqttSecurityException, MqttException {
try {
client.connect(connOpts);
client.setCallback(this);
client.subscribe("ActiveMQ/Advisory/Connection");
} catch (MqttSecurityException e) {
Logger.error(e.getLocalizedMessage());
Logger.debug(e);
} catch (MqttException e) {
Logger.error(e.getLocalizedMessage());
Logger.debug(e);
processError(e);
}
}
public void publish(String orderType, JSONObject jsonExtraData) {
if (status == STATUS_ERROR) {
connectAndSubscribe();
}
if (status == STATUS_OK) {
// some code here
}
}
#Override
public void connectionLost(Throwable err) {
Logger.info("Connection lost");
}
#Override
public void deliveryComplete(IMqttDeliveryToken arg0) {
Logger.info("deliveryComplete");
}
#Override
public void messageArrived(String topic, MqttMessage msg) throws Exception {
System.out.println("MQTT Mesage Arrived[" + topic + "] Msg[" + msg.toString() + "]");
}
private void processError(MqttException e) {
status = STATUS_ERROR;
try {
if (client.isConnected()) {
Logger.error("disconnecting");
client.disconnect();
}
} catch (MqttException ex) {
Logger.error(ex.getLocalizedMessage());
Logger.debug(ex);
}
}
}
The connection with ActiveMQ is established fine. This topic offers information about the connections (open/close) in the ActiveMQ, but my problem is that messages I catch are empty:
MQTT Mesage Arrived[ActiveMQ/Advisory/Connection] Msg[]
Is there any way to catch them using MQTT? or I should use JMS for that?
Thanks,
Jon Ander.
The question would be what do you want the MQTT client to receive on the Advisory topic as the message body. The advisories generally include much of the information as message properties however those cannot be mapped to MQTT as MQTT messages don't have properties. The body of the Connection advisory is a copy of the ConnectionInfo object that was used to create the connection. On the MQTT side there is not much you could do with that as all you would receive would be the serialized bytes of that object which you wouldn't be able to do anything with.
I have an web server which is getting a lot of messages to the same topic and is returning response messages to another topic.
I am currently re-using the same MQTT client instance both for the callback and for sending the response messages by keeping the MQTT client connected all the time.
However, after one cycle of receiving a message and sending a response, I am able to receive another message but cannot send the response - I have to restart the application server.
Is it a good approach to have a single MQTTclient instance? Is it OK to keep it connected all the time? What's the best approach for this kind of requirement?
Here is my code:
public static void registerCallBack(String topicName, String userName,
String password, String clientId, MqttCallback callback,
MqttClient client) {
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(true);
options.setKeepAliveInterval(30);
options.setUserName(userName);
options.setPassword(password.toCharArray());
// Connect to Broker
try {
options.setSocketFactory(SslUtil.getSocketFactory(
ManagerProps.MQTT_BROKER_CA_FILE.getValue(), ""));
client.setCallback(callback);
client.connect(options);
client.subscribe(topicName, 0);
log.info("successfuly registered callback to topic " + topicName);
} catch (MqttException me) {
log.error("MqttException, " + me);
} catch (Exception e) {
log.error("Exception, " + e);
}
}
public static String publishMessage(MqttClient client, String message,
String topic, String userName, String password) {
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(true);
options.setKeepAliveInterval(30);
options.setUserName(userName);
options.setPassword(password.toCharArray());
try {
MqttMessage msg = new MqttMessage();
msg.setPayload(message.getBytes());
client.publish(topic, msg);
} catch (MqttException e) {
log.error("MqttException, " + e);
} catch (Exception e) {
log.error("Exception, " + e);
}
return message;
}
I was seeing something similar, and got this to work:
final CallbackConnection connection = mqtt.callbackConnection();
connection.listener(new org.fusesource.mqtt.client.Listener() {
public void onConnected() {
}
public void onDisconnected() {
}
public void onFailure(Throwable value) {
value.printStackTrace();
System.exit(-2);
}
public void onPublish(UTF8Buffer topic, Buffer msg, Runnable ack) {
String body = msg.utf8().toString();
if( body.startsWith("REPLY: ")) {
// Don't reply to your own reply
System.out.println("Replied");
System.out.println("");
} else {
try{
byte[] reply = "REPLY: Hello Back".getBytes();
connection.publish(destination, reply, QoS.AT_MOST_ONCE, true, null) ;
msg.clear();
}catch (Exception e){
e.printStackTrace();
}
}
}
});
I am using the great async http library from loopj, but I have run into a small snag.
If the user has no internet connection or loses their connection, the app just won't return anything. This part is expected, but it also doesn't fire the onFailure method.
Also, the code I have used when there is an internet connection does work so there is no problem on the server end.
Here is some code that is stripped down to the minimum. It also doesn't work (I have tested this too)
String url = getString(R.string.baseurl) + "/appconnect.php";
client.getHttpClient().getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
client.get(url, null, new JsonHttpResponseHandler()
{
#Override
public void onSuccess(JSONArray response)
{
Toast.makeText(getApplicationContext(), "Success", Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Throwable e, JSONArray errorResponse)
{
Toast.makeText(getApplicationContext(), "Failure", Toast.LENGTH_SHORT).show();
}
});
Thanks,
Ashley
You can try this:
In AsyncHttpRequest->makeRequestWithRetries(), add a catch to SocketException like this:
while (retry) {
try {
makeRequest();
return;
} catch (UnknownHostException e) {
if(responseHandler != null) {
responseHandler.sendFailureMessage(e, "can't resolve host");
}
return;
} catch (SocketException e){
// Added to detect no connection.
if(responseHandler != null) {
responseHandler.sendFailureMessage(e, "can't resolve host");
}
return;
} catch (IOException e) {
cause = e;
retry = retryHandler.retryRequest(cause, ++executionCount, context);
} catch (NullPointerException e) {
// there's a bug in HttpClient 4.0.x that on some occasions causes
// DefaultRequestExecutor to throw an NPE, see
// http://code.google.com/p/android/issues/detail?id=5255
cause = new IOException("NPE in HttpClient" + e.getMessage());
retry = retryHandler.retryRequest(cause, ++executionCount, context);
}
}
Yeah, unfortunately the loopj Android library isn't very well designed. If you implement the other onFailure callbacks one of them should fire:
#Override
public void onFailure(Throwable e) {
Log.e(TAG, "OnFailure!", e);
}
#Override
public void onFailure(Throwable e, String response) {
Log.e(TAG, "OnFailure!", e);
}
#Override
public void onFailure(Throwable e, JSONArray errorResponse) {
Log.e(TAG, "OnFailure!", e);
}
Try this:
#Override
protected Object parseResponse(byte[] responseBody) throws JSONException {
return super.parseResponse(responseBody);
}