我正在開發一個需要用戶之間進行實時交互的項目。我想有一個HTML5 Web客戶端(足夠簡單),並且還有一個本地客戶端(最好是Java),它們都能夠連接到服務器。我已經做了一些研究,並沒有找到一個確定的答案,以確定本地客戶端是否可以在沒有瀏覽器的情況下連接到服務器。沒有瀏覽器的Java Websocket客戶端
問:有沒有辦法從本地Java客戶端連接到websocket服務器而無需瀏覽?我已經看到了其他語言中的一些瀏覽器包裝可能會使這成爲可能。如果沒有,我願意接受建議。
謝謝。
我正在開發一個需要用戶之間進行實時交互的項目。我想有一個HTML5 Web客戶端(足夠簡單),並且還有一個本地客戶端(最好是Java),它們都能夠連接到服務器。我已經做了一些研究,並沒有找到一個確定的答案,以確定本地客戶端是否可以在沒有瀏覽器的情況下連接到服務器。沒有瀏覽器的Java Websocket客戶端
問:有沒有辦法從本地Java客戶端連接到websocket服務器而無需瀏覽?我已經看到了其他語言中的一些瀏覽器包裝可能會使這成爲可能。如果沒有,我願意接受建議。
謝謝。
您也可以考慮使用JSR 356 - Java API for WebSocket。它是Java EE 7的一部分,但客戶端可以從普通的Java SE運行而不會出現任何問題。可以使用多種實現方式,現在和下面將在所有這些工作:
編程API:
final WebSocketContainer webSocketContainer = ContainerProvider.getWebSocketContainer();
Session session = webSocketContainer.connectToServer(new Endpoint() {
@Override
public void onOpen(Session session, EndpointConfig config) {
// session.addMessageHandler(...);
}
}, URI.create("ws://some.uri"));
註解API:
public static void main(String[] args) throws IOException, DeploymentException {
final WebSocketContainer webSocketContainer = ContainerProvider.getWebSocketContainer();
webSocketContainer.connectToServer(MyEndpoint.class, URI.create("ws://some.uri"));
}
@ClientEndpoint
public static class MyEndpoint {
// text
@OnMessage
void onMessage(Session session, String message) {
// ...
}
// binary
@OnMessage
void onMessage(Session session, ByteBuffer message) {
// ...
}
// @OnClose, @OnOpen, @OnError
}
請詳情見鏈接的頁面(全規格)。
這裏有各種實現,基本上每個Java容器都有一個。我正在開發Glassfish/WebLogic實現,並且它的Tyrus可以隨時試用(我們提供易於使用的所有功能,請參閱http://search.maven.org/...)。
您肯定可以在瀏覽器沙箱以外的Java中使用桌面應用程序中的WebSockets。這背後的想法是,您可以創建創建TCP連接的胖客戶端,所以當然他們應該能夠在這些TCP連接之上創建WebSocket連接。
這樣做的最新和最好的API之一是由Kaazing編寫的,他認爲WebSocket就像一個套接字,可以使用簡單的「ws://」URI來創建。
該API詳細討論on the Kaazing Gateway 5.0 Java WebSocket Documentation site。您可以從的Kaazing here
創建的WebSocket下載普通網關:
import com.kaazing.net.ws.WebSocket;
import com.kaazing.net.ws.WebSocketFactory;
wsFactory = WebSocketFactory.createWebSocketFactory();
ws = wsFactory.createWebSocket(URI.create("ws://example.com:8001/path"));
ws.connect(); // This will block or throw an exception if failed.
要發送信息,添加一個WebSocketMessageWriter對象:
WebSocketMessageWriter writer = ws.getMessageWriter();
String text = "Hello WebSocket!";
writer.writeText(text); // Send text message
要接收或接收消息,添加的WebSocket和WebSocketMessageReader物件:
wsFactory = WebSocketFactory.createWebSocketFactory();
ws = wsFactory.createWebSocket(URI.create("ws://example.com:8001/path"));
ws.connect(); // This will block or throw an exception if failed.
WebSocketMessageReader reader = ws.getMessageReader();
WebSocketMessageType type = null; // Block till a message arrives
// Loop till the connection goes away
while ((type = reader.next()) != WebSocketMessageType.EOS) {
switch (type) { // Handle both text and binary messages
case TEXT:
CharSequence text = reader.getText();
log("RECEIVED TEXT MESSAGE: " + text.toString());
break;
case BINARY:
ByteBuffer buffer = reader.getBinary();
log("RECEIVED BINARY MESSAGE: " + getHexDump(buffer));
break;
}
}
(完全披露:我曾在Kaazing公司擔任服務器工程師。)
Vert.x有一個Java的WebSocket客戶端:
VertxFactory.newVertx()
.createHttpClient()
.setHost("localhost")
.setPort(8080)
.connectWebsocket("/ws", new Handler<WebSocket>() {
@Override
public void handle(final WebSocket webSocket) {
// Listen
webSocket.dataHandler(new Handler<Buffer>() {
@Override
public void handle(Buffer buff) {
log.info("Received {}", buff.toString());
}
});
// Publish
webSocket.writeTextFrame("Heya");
}
});
Netty
是這樣的任務一個很好的選擇,它是一個高性能的網絡應用程序框架,它支持SSL優雅,這裏是netty websocket client example從網狀github上:
public final class WebSocketClient {
static final String URL = System.getProperty("url", "ws://127.0.0.1:8080/websocket");
public static void main(String[] args) throws Exception {
URI uri = new URI(URL);
String scheme = uri.getScheme() == null? "ws" : uri.getScheme();
final String host = uri.getHost() == null? "127.0.0.1" : uri.getHost();
final int port;
if (uri.getPort() == -1) {
if ("ws".equalsIgnoreCase(scheme)) {
port = 80;
} else if ("wss".equalsIgnoreCase(scheme)) {
port = 443;
} else {
port = -1;
}
} else {
port = uri.getPort();
}
if (!"ws".equalsIgnoreCase(scheme) && !"wss".equalsIgnoreCase(scheme)) {
System.err.println("Only WS(S) is supported.");
return;
}
final boolean ssl = "wss".equalsIgnoreCase(scheme);
final SslContext sslCtx;
if (ssl) {
sslCtx = SslContextBuilder.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE).build();
} else {
sslCtx = null;
}
EventLoopGroup group = new NioEventLoopGroup();
try {
// Connect with V13 (RFC 6455 aka HyBi-17). You can change it to V08 or V00.
// If you change it to V00, ping is not supported and remember to change
// HttpResponseDecoder to WebSocketHttpResponseDecoder in the pipeline.
final WebSocketClientHandler handler =
new WebSocketClientHandler(
WebSocketClientHandshakerFactory.newHandshaker(
uri, WebSocketVersion.V13, null, true, new DefaultHttpHeaders()));
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline();
if (sslCtx != null) {
p.addLast(sslCtx.newHandler(ch.alloc(), host, port));
}
p.addLast(
new HttpClientCodec(),
new HttpObjectAggregator(8192),
WebSocketClientCompressionHandler.INSTANCE,
handler);
}
});
Channel ch = b.connect(uri.getHost(), port).sync().channel();
handler.handshakeFuture().sync();
BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String msg = console.readLine();
if (msg == null) {
break;
} else if ("bye".equals(msg.toLowerCase())) {
ch.writeAndFlush(new CloseWebSocketFrame());
ch.closeFuture().sync();
break;
} else if ("ping".equals(msg.toLowerCase())) {
WebSocketFrame frame = new PingWebSocketFrame(Unpooled.wrappedBuffer(new byte[] { 8, 1, 8, 1 }));
ch.writeAndFlush(frame);
} else {
WebSocketFrame frame = new TextWebSocketFrame(msg);
ch.writeAndFlush(frame);
}
}
} finally {
group.shutdownGracefully();
}
}
}
public class WebSocketClientHandler extends SimpleChannelInboundHandler<Object> {
private final WebSocketClientHandshaker handshaker;
private ChannelPromise handshakeFuture;
public WebSocketClientHandler(WebSocketClientHandshaker handshaker) {
this.handshaker = handshaker;
}
public ChannelFuture handshakeFuture() {
return handshakeFuture;
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) {
handshakeFuture = ctx.newPromise();
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
handshaker.handshake(ctx.channel());
}
@Override
public void channelInactive(ChannelHandlerContext ctx) {
System.out.println("WebSocket Client disconnected!");
}
@Override
public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
Channel ch = ctx.channel();
if (!handshaker.isHandshakeComplete()) {
handshaker.finishHandshake(ch, (FullHttpResponse) msg);
System.out.println("WebSocket Client connected!");
handshakeFuture.setSuccess();
return;
}
if (msg instanceof FullHttpResponse) {
FullHttpResponse response = (FullHttpResponse) msg;
throw new IllegalStateException(
"Unexpected FullHttpResponse (getStatus=" + response.status() +
", content=" + response.content().toString(CharsetUtil.UTF_8) + ')');
}
WebSocketFrame frame = (WebSocketFrame) msg;
if (frame instanceof TextWebSocketFrame) {
TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
System.out.println("WebSocket Client received message: " + textFrame.text());
} else if (frame instanceof PongWebSocketFrame) {
System.out.println("WebSocket Client received pong");
} else if (frame instanceof CloseWebSocketFrame) {
System.out.println("WebSocket Client received closing");
ch.close();
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
if (!handshakeFuture.isDone()) {
handshakeFuture.setFailure(cause);
}
ctx.close();
}
}
答案應該站在它自己的。請稍微擴大這個答案。 – klutt
可能重複:http://stackoverflow.com/questions/7257068/java-websocket-client-needed?lq=1 – blackcompe