I am new in web socket. I had learned some tutorial to implement web socket. But it is not working properly. I don't know what I have done wrongly.
note: I have not done any configuration (web.xml) and I have been used tomcat 7.0.47,jdk 1.6.0_24
This is My Server side code:
package com.hmkcode;
import java.io.IOException;
import java.util.LinkedList;
import javax.websocket.EncodeException;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
#ServerEndpoint(value="/websocket/{client-id}")
public class MyServerEndpoint {
private static final LinkedList<Session> clients = new LinkedList<Session>();
#OnOpen
public void onOpen(Session session) {
clients.add(session);
}
#OnMessage
public void onMessage(String message,#PathParam("client-id") String clientId) {
for (Session client : clients) {
try {
client.getBasicRemote().sendObject(clientId+": "+message);
} catch (IOException e) {
e.printStackTrace();
} catch (EncodeException e) {
e.printStackTrace();
}
}
}
#OnClose
public void onClose(Session peer) {
clients.remove(peer);
}
}
This is my Web client code
var URL = "ws://localhost:8080/WebSocket1/websocket/web-client";
var websocket;
$(document).ready(function(){
connect();
});
function connect(){
websocket = new WebSocket(URL);
websocket.onopen = function(evnt) { onOpen(evnt);};
websocket.onmessage = function(evnt) { onMessage(evnt); };
websocket.onerror = function(evnt) { onError(evnt); };
}
function sendMessage() {
websocket.send($("#message").val());
}
function onOpen() {
updateStatus("connected");
}
function onMessage(evnt) {
if (typeof evnt.data == "string") {
$("#received_messages").append(
$('<tr/>')
.append($('<td/>').text("1"))
.append($('<td/>').text(evnt.data.substring(0,evnt.data.indexOf(":"))))
.append($('<td/>').text(evnt.data.substring(evnt.data.indexOf(":")+1))));
}
}
function onError(evnt) {
alert('ERROR: ' + evnt.data);
}
function updateStatus(status){
if(status == "connected"){
$("#status").removeClass (function (index, css) {
return (css.match (/\blabel-\S+/g) || []).join(' ');
});
$("#status").text(status).addClass("label-success");
}
}
My guess is...
Since you ServerEndpoint maps an argument "{client-id}" it should be present in the URL your client uses to connect.
Either you remove the parameter on server-side or you need to include a value to it on client-side.
Again, just guessing. It would be useful if you include more information regarding the issue (e.g., server logs)
[]s
Heleno
Related
I have the following java socketio code
package me.summit.socketchatmc;
import java.net.URI;
import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
import java.net.URISyntaxException;
import static io.socket.client.IO.socket;
public class socketclient {
Socket sock;
private String uri="http://localhost";
public void start(){
sock = IO.socket(URI.create(uri));
sock.connect();
System.out.println("Socket connected");
sock.emit("message", "Hi from Java Plugin!");
System.out.println("Emitted message");
}
public void disconnect(){
sock.disconnect();
System.out.println("Socket disconnected");
}
}
(It's in a spigot plugin)
I call it in the Main.Java function like this
socketclient sock = new socketclient();
#Override
public void onEnable() {
//getLogger().info("onEnable is called!");
sock.start();
getServer().getPluginManager().registerEvents(this,this);
}
#Override
public void onDisable() {
//getLogger().info("onDisable is called!");
sock.disconnect();
}
However, when I run the java plugin, it says that it emits the message
picture of java plugin running
but when I check the socketio part, nothing is connected or emitted picture of socketio server
For reference, here is my socketio server code
const app = require("express")();
const httpServer = require("http").createServer(app);
const options = {
cors: {
origin: '*',
}
};
const io = require("socket.io")(httpServer, options);
const cors = require('cors')
app.use(cors());
app.use(
function(req, res, next) {
console.log(req.ip+": "+req.path);
next();
}
);
app.get('/', function(req, res) {
res.send('hi');
});
io.on("connection", (socket) => {
socket.broadcast.emit("join", socket.id);
console.log(socket.id+" has joined");
socket.on('disconnect', function () {
socket.broadcast.emit("leave", socket.id);
console.log(socket.id+' disconnected');
});
socket.on('message', (elem1) => {
socket.broadcast.emit("message", elem1, socket.id);
console.log(socket.id+' said '+elem1);
});
});
httpServer.listen(80);
console.log("Listening on *:80");
I am trying to use TooTallNate's Java-Websocket to connect to OkCoin. I found this simple code example somewhere, but I can't get it to work. The connection is immediately closed and so the call mWs.send(...) throws a WebsocketNotConnectedException. I can't figure out why; so far I have found a number of similar questions, none of which have an answer.
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.json.JSONObject;
import java.net.URI;
import java.net.URISyntaxException;
public class TestApp {
public static void main(String[] args) {
try {
URI uri = new URI("wss://real.okcoin.cn:10440/websocket/okcoinapi");
final WebSocketClient mWs = new WebSocketClient(uri) {
#Override
public void onMessage(String message) {
JSONObject obj = new JSONObject(message);
}
#Override
public void onOpen(ServerHandshake handshake) {
System.out.println("opened connection");
}
#Override
public void onClose(int code, String reason, boolean remote) {
System.out.println("closed connection");
}
#Override
public void onError(Exception ex) {
ex.printStackTrace();
}
};
mWs.connect();
JSONObject obj = new JSONObject();
obj.put("event", "addChannel");
obj.put("channel", "ok_btccny_ticker");
mWs.send(obj.toString());
} catch (URISyntaxException e) {
System.err.println("URI not formatted correctly");
}
}
}
Use mWs.connectBlocking() instead of mWs.connect() with this it will not close automatically.
See
I am exploring Websocket now. I need some clarifications. I am using websocket with tomcat.
How tomcat map websocket requests to specific java class. for an example, we can give servlet class in web.xml. But How it works for websocket?
1- Javascript :
Declare variables for the websocket as the following :
var websocket;
var address = "ws://localhost:8080/appName/MyServ";
notice that appName is your application name and MyServ is the Endpoint
also in your script add a function to open the connection :
var websocket;
var address = "ws://localhost:8080/appName/MyServ";
function openWS() {
websocket = new WebSocket(address);
websocket.onopen = function(evt) {
onOpen(evt)
};
websocket.onmessage = function(evt) {
onMessage(evt)
};
websocket.onerror = function(evt) {
onError(evt)
};
websocket.onclose = function(evt) {
onClose(evt)
};
}
function onOpen(evt) {
// what will happen after opening the websocket
}
function onClose(evt) {
alert("closed")
}
function onMessage(evt) {
// what do you want to do when the client receive the message?
alert(evt.data);
}
function onError(evt) {
alert("err!")
}
function SendIt(message) {
// call this function to send a msg
websocket.send(message);
}
2- At the server side, you need a ServerEndpoint : I call it myServ in the script above.
NOW, I think this is exactly what you need:
Declare any Java POJO class WebSocket server endpoint by annotating it with #ServerEndpoint
import java.io.IOException
import javax.servlet.ServletContext;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
#ServerEndpoint(value="/MyServ")
public class MyServ{
#OnMessage
public void onMessage(Session session, String msg) throws IOException {
// todo when client send msg
// tell the client that you received the message!
try {
session.getBasicRemote().sendText("I got your message :"+ msg);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#OnOpen
public void onOpen (Session session) {
// tell the client the connection is open!
try {
session.getBasicRemote().sendText("it is open!");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#OnClose
public void onClose (Session session) {
System.out.println("websocket closed");
}
#OnError
public void onError (Session session){
}
}
We are using Websockets from the Grizzly project and had expected that the implementation would allow multiple incoming messages over a connection to be processed at the same time. It appears that this is not the case or there is a configuration step that we have missed. To validate this I have created a modified echo test that delays in the onMessage after echoing the text. When a client sends multiple messages over the same connection the server always blocks until onMessage completes before processing a subsequent message. Is this the expected functionality?
The simplified server code is as follows:
package com.grorange.samples.echo;
import java.util.concurrent.atomic.AtomicBoolean;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.NetworkListener;
import org.glassfish.grizzly.websockets.DataFrame;
import org.glassfish.grizzly.websockets.WebSocket;
import org.glassfish.grizzly.websockets.WebSocketAddOn;
import org.glassfish.grizzly.websockets.WebSocketApplication;
import org.glassfish.grizzly.websockets.WebSocketEngine;
public class Echo extends WebSocketApplication {
private final AtomicBoolean inMessage = new AtomicBoolean(false);
#Override
public void onClose(WebSocket socket, DataFrame frame) {
super.onClose(socket, frame);
System.out.println("Disconnected!");
}
#Override
public void onConnect(WebSocket socket) {
System.out.println("Connected!");
}
#Override
public void onMessage(WebSocket socket, String text) {
System.out.println("Server: " + text);
socket.send(text);
if (this.inMessage.compareAndSet(false, true)) {
try {
Thread.sleep(10000);
} catch (Exception e) {}
this.inMessage.set(false);
}
}
#Override
public void onMessage(WebSocket socket, byte[] bytes) {
socket.send(bytes);
if (this.inMessage.compareAndSet(false, true)) {
try {
Thread.sleep(Long.MAX_VALUE);
} catch (Exception e) {}
this.inMessage.set(false);
}
}
public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.createSimpleServer("http://0.0.0.0", 8083);
WebSocketAddOn addOn = new WebSocketAddOn();
addOn.setTimeoutInSeconds(60);
for (NetworkListener listener : server.getListeners()) {
listener.registerAddOn(addOn);
}
WebSocketEngine.getEngine().register("", "/Echo", new Echo());
server.start();
Thread.sleep(Long.MAX_VALUE);
}
}
The simplified client code is:
Yes, it's expected.
The way to go is to pass message processing, inside onMessage, to a different thread.
I have a kryonet client/server that work find.. well mostly. The client remains idle and eventually disconnects after awhile but thats not the issue i'm trying to solve currently. Currently, the server and client can establish a connection and send data back and forth(Before the client times out) as long as the client and server are on the same computer. If you try to connect to a different computer on the LAN the connection times out and fails.
So here's my question(s):
What would be a possible cause for the connection issue?
What is the proper way to keep a client alive? ( secondary goal but if you know it, that'd be great)
*I'm using LibGDX and Kryonet for this. As far as I know, they shouldn't have any conflicts.
Server:
package com.me.mygdxgame;
import java.io.IOException;
import java.util.ArrayList;
import com.badlogic.gdx.math.Vector2;
import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener;
import com.esotericsoftware.kryonet.Server;
import com.me.mygdxgame.Network.Obstacles;
public class GameServer {
Server server;
public GameServer () throws IOException {
server = new Server() {
protected Connection newConnection () {
return new PlayerConnection();
}
};
Network.register(server);
//Sends Stuff to Client
server.addListener(new Listener() {
public void received (Connection c, Object object) {
PlayerConnection connection = (PlayerConnection)c;
if (object instanceof Obstacles) {
if (connection.name != null) return;
ArrayList<Vector2> obs = ((Obstacles)object).obstacles;
if (obs == null) return;
System.out.println("Obstacles recieved.");
for(int i = 0; i < obs.size(); i++)
System.out.println("Obstacle " + i + "- x: " + obs.get(i).x );
return;
}
}
});
server.bind(Network.port);
server.start();
}
public void sendAll () { //Send out data
Obstacles ob = new Obstacles();
ob.obstacles = new ArrayList<Vector2>();
for(int i =0; i < Map.obstacles.size(); i++){
ob.obstacles.add(new Vector2(Map.obstacles.get(i).x,Map.obstacles.get(i).y));
}
server.sendToAllTCP(ob);
}
static class PlayerConnection extends Connection {
public String name;
}
}
Client:
package com.me.mygdxgame;
import java.awt.EventQueue;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import com.badlogic.gdx.ApplicationListener;
import com.esotericsoftware.kryonet.Client;
import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener;
import com.me.mygdxgame.Network.Obstacles;
public class GameClient implements ApplicationListener{
Client client;
String name;
String RefreshHost;
boolean Connected = false;
ArrayList<String> hosts = new ArrayList<String>();
public static String host;
public GameClient (String host) {
client = new Client();
client.start();
this.host = host;
Network.register(client);
client.addListener(new Listener() {
public void connected (Connection connection) {
System.out.println("connected");
Connected = true;
}
public void received (Connection connection, Object object) {
if (object instanceof Obstacles) {
Obstacles obs = (Obstacles)object;
System.out.println("Obstacle recieved on client - " + obs.obstacles.size());
client.sendTCP(obs);
System.out.println("Obstacles sent back.");
return;
}else {
System.out.println("invalid packet");
}
}
public void disconnected (Connection connection) {
EventQueue.invokeLater(new Runnable() {
public void run () {
System.out.println("closed");
Connected = false;
client.close();
}
});
}
});
new Thread("Connect") {
public void run () {
try {
client.connect(5000, GameClient.host, Network.port);
System.out.println("Connected!");
client.setKeepAliveTCP(NORM_PRIORITY);
while(Connected) {
//System.out.println(client.isIdle());
}
client.run();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}.start();
}
#Override
public void create() {
// TODO Auto-generated method stub
}
#Override
public void resize(int width, int height) {
// TODO Auto-generated method stub
}
#Override
public void render() {
// TODO Auto-generated method stub
}
#Override
public void pause() {
// TODO Auto-generated method stub
}
#Override
public void resume() {
// TODO Auto-generated method stub
}
#Override
public void dispose() {
// TODO Auto-generated method stub
}
}
I suggest you set the host BEFORE you start the client
public GameClient (String host) {
client = new Client();
this.host = host;
client.start();
I am not familiar with kryonet Client, but it makes sense to do it that way.
Generally make sure that your client is trying to connect to the host that you have server running on...
One possible cause for such connection issue is a firewall blocking your Network.port
Another one, sorry but I have to ask: Is the server-app running in the other machine?
I ask because I dont'see a main function in your server code
public static void main(String[] args) throws IOException {
Log.set(Log.LEVEL_DEBUG);
new GameServer();
}
I use to get running my server-app with this terminal command
java -jar myserverfile.jar
How do you get it running in the "remote" machine?
By the way, I am using libgdx and kryonet for my game and so far I haven't get issues using them together.
In my case I have the server in a AWS instance listening for game-client testing from my computer.