ฉันประสบปัญหาในการทำให้เซิร์ฟเวอร์ Tyrus websocket แบบสแตนด์อโลนที่เรียบง่ายอย่างยิ่งทำงานได้ ฉันได้ดำเนินการนี้ภายใต้สถานการณ์ที่เฉพาะเจาะจงซึ่งไม่สมเหตุสมผลสำหรับฉัน
กรณีที่ทำงานอย่างถูกต้องคือที่ฉันกำหนดคลาสจุดสิ้นสุดเซิร์ฟเวอร์ระดับบนสุด (ในไฟล์ของตัวเอง) และใส่คำอธิบายประกอบด้วย @ServerEndpoint คลาสนี้รวมวิธีการที่มีคำอธิบายประกอบด้วย @OnOpen, @OnMessage และ @OnClose ซึ่งเป็นสิ่งทั่วไปทั้งหมด ฉันส่งคลาสนี้ไปยังตัวสร้างเซิร์ฟเวอร์ ไคลเอนต์ธรรมดาของฉันสามารถเชื่อมต่อกับเซิร์ฟเวอร์นี้ และส่งข้อความที่เซิร์ฟเวอร์ได้รับได้สำเร็จ
ปัญหาเกิดขึ้นเมื่อฉันเปลี่ยนคลาสจุดสิ้นสุดเซิร์ฟเวอร์ระดับบนสุดให้เป็นคลาสภายในของคลาสที่กำลังเตรียมใช้งานเซิร์ฟเวอร์ (นี่เป็นการเปลี่ยนแปลงเดียวที่ฉันทำ) ในกรณีนี้ ลูกค้าของฉันสามารถเชื่อมต่อได้และเรียกใช้เมธอด @OnOpen ของลูกค้า แต่เซิร์ฟเวอร์ไม่สร้างอินสแตนซ์จุดสิ้นสุดของเซิร์ฟเวอร์ และด้วยเหตุนี้ จึงไม่มีการเรียกใช้เมธอด @OnOpen แน่นอนว่าการรับข้อความจากเซิร์ฟเวอร์ไม่เกิดขึ้น
มีข้อกำหนดใน Tyrus ที่ว่าคลาสจุดสิ้นสุดของเซิร์ฟเวอร์ที่มีคำอธิบายประกอบไม่สามารถเป็นคลาสภายในได้หรือไม่ ถ้าไม่ มีสิทธิ์เฉพาะสำหรับคลาสจุดสิ้นสุดของเซิร์ฟเวอร์ (ทุกอย่างถูกเปิดเผยต่อสาธารณะโดยพยายามทำให้สิ่งนี้ทำงานได้โดยไม่มีโชค) ฉันใช้ Tyrus 1.9 กับ JDK 1.7 บน Mac, OSX 1.9.5
เซิร์ฟเวอร์แบบธรรมดา (รวมถึงและกำหนดค่าให้ใช้จุดสิ้นสุดเซิร์ฟเวอร์ภายในที่ล้มเหลว):
package tyrus.example;
import java.util.concurrent.TimeUnit;
import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.glassfish.tyrus.server.Server;
public class SimpleServer
{
private static final String HOST_ADDR = "localhost";
private static final int HOST_PORT = 8025;
public static void main(String[] args) {
Server websocketServer = new Server(HOST_ADDR, HOST_PORT, "/ws", null, InnerSimpleServerEndpoint.class);
try {
websocketServer.start();
Thread.sleep(TimeUnit.MINUTES.toMillis(5));
}
catch (Exception e) {
e.printStackTrace();
}
websocketServer.stop();
System.out.println("Done.");
}
@ServerEndpoint("/myapp")
public class InnerSimpleServerEndpoint {
@OnOpen
public void onOpen(Session session) {
System.out.println("Connection received for "+session.getRequestURI());
}
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("Message received: "+message);
}
@OnClose
public void onClose(Session session, CloseReason closeReason) {
System.out.println("Session closed, reason: "+closeReason);
}
}
}
ลูกค้าธรรมดา:
package tyrus.example;
import java.io.IOException;
import java.net.URI;
import javax.websocket.ClientEndpointConfig;
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.MessageHandler;
import javax.websocket.Session;
import org.glassfish.tyrus.client.ClientManager;
public class SimpleClient
{
private static final String DEF_WS_URL = "ws://localhost:8025/ws/myapp";
public static void main(String[] args) {
ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build();
ClientManager client = ClientManager.createClient();
try {
client.connectToServer(new ClientEndpoint(), cec, new URI(DEF_WS_URL));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Done.");
}
private static class ClientEndpoint extends Endpoint {
@Override
public void onOpen(Session session, EndpointConfig config) {
System.out.println("ClientEndpoint: server session opened: "+session);
session.addMessageHandler(new MessageHandler.Whole<String>() {
@Override
public void onMessage(String message) {
System.out.println("ClientEndpoint: received message: "+message);
}
});
try {
session.getBasicRemote().sendText("Hello server!");
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
และสุดท้ายคือจุดสิ้นสุดเซิร์ฟเวอร์ที่ไม่ใช่คลาสภายในที่ทำงานเมื่อเซิร์ฟเวอร์ใช้งาน:
package tyrus.example;
import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/myapp")
public class SimpleServerEndpoint {
@OnOpen
public void onOpen(Session session) {
System.out.println("Connection received for "+session.getRequestURI());
}
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("Message received: "+message);
}
@OnClose
public void onClose(Session session, CloseReason closeReason) {
System.out.println("Session closed, reason: "+closeReason);
}
}