Java API实现WebSocket客户端
来源:互联网 发布:php程序员自我评价 编辑:程序博客网 时间:2024/06/05 07:11
上一篇是说浏览器与服务器建立WebSocket通信,而这篇来通过WebSocket-api提供的接口来实现客户端的功能。
客户端主要也是通过注解的方式来实现,但是创建的方式会用到其他类,注解为@ClientEndpoint,其他注解一样,WebSocketClient.java具体代码如下:
@ClientEndpointpublic class WebSocketClient { private Logger logger = Logger.getLogger(WebSocketServer.class); private Session session; @OnOpen public void open(Session session){ logger.info("Client WebSocket is opening..."); this.session = session; } @OnMessage public void onMessage(String message){ logger.info("Server send message: " + message); } @OnClose public void onClose(){ logger.info("Websocket closed"); } @OnError public void onError(Session session, Throwable t) { t.printStackTrace(); } public void send(String message){ this.session.getAsyncRemote().sendText(message); } public void close() throws IOException{ if(this.session.isOpen()){ this.session.close(); } }}
另外添加两个方法send
和close
,可以主动发送消息和关闭连接。只要可以获取到建立连接的session
,就可以进行相关的操作,如消息发送、状态判断等等。
以上为客户端的简单实现,接下来,来看看@ClientEndpoint
注解的代码:
@Retention(RetentionPolicy.RUNTIME)@Target({java.lang.annotation.ElementType.TYPE})public @interface ClientEndpoint{ String[] subprotocols() default {}; Class<? extends Decoder>[] decoders() default {}; Class<? extends Encoder>[] encoders() default {}; Class<? extends ClientEndpointConfig.Configurator> configurator() default ClientEndpointConfig.Configurator.class;}
可以看见,有四个配置参数,接下来分别对这些配置进行实现:
subprotocols: 为字符串数组,表示支持的子协议名称列表
无特别
Decoder的实现:
public class SampleDecoder implements Decoder.Text<String>{ public void init(EndpointConfig paramEndpointConfig) { // Auto-generated method stub } public void destroy() { // Auto-generated method stub } public String decode(String paramString) throws DecodeException { // Auto-generated method stub return paramString.toLowerCase(); } public boolean willDecode(String paramString) { // Auto-generated method stub return true; }}
Encoder实现
public class SimpleEncoder implements javax.websocket.Encoder.Text<String> { public void init(EndpointConfig paramEndpointConfig) { //Auto-generated method stub System.out.println("Encoder init: " + paramEndpointConfig.getUserProperties()); } public void destroy() { //Auto-generated method stub } public String encode(String paramT) throws EncodeException { //Auto-generated method stub return paramT.toUpperCase(); }}
encode
方法是接收到数据进行解码操作,如对字符串解码,对json格式转换为对象等等;
Configurator实现
public class SampleConfigurator extends Configurator { @Override public void beforeRequest(Map<String, List<String>> headers) { //Auto-generated method stub System.out.println(headers); } @Override public void afterResponse(HandshakeResponse handshakeResponse) { //Auto-generated method stub System.out.println(handshakeResponse); }}
可以通过打印来查看这些参数是什么,我们通过函数名称就可以知道,beforeRequest
是在请求之前调用,可以对请求头进行修改或者查看;afterResponse
是在握手成功后调用的,handshakeResponse
为握手响应头;
而现在的客户端配置如下:
@ClientEndpoint( configurator=SampleConfigurator.class, decoders={SampleDecoder.class}, encoders={SimpleEncoder.class}, subprotocols={"subprotocol1"})public class WebSocketClient { private Logger logger = Logger.getLogger(WebSocketServer.class); private Session session; ......}
添加主程序AppMain.java:
public class AppMain { public static void main(String[] args) throws DeploymentException, IOException, URISyntaxException, InterruptedException { // Auto-generated method stub WebSocketContainer conmtainer = ContainerProvider.getWebSocketContainer(); WebSocketClient client = new WebSocketClient(); conmtainer.connectToServer(client, new URI("ws://localhost:8080/websocket/chat?query=Picasso")); int turn = 0; while(turn++ < 10){ client.send("send text: " + turn); Thread.sleep(1000); } client.close(); }}
先启动服务器,之后启动客户端的应用程序,查看控制台
服务端控制台:
2015-12-21 23:28:10,673 INFO (cc.eabour.websocket.filter.DispatcherFilter:30) - Request URL: http://localhost:8080/websocket/chat2015-12-21 23:28:10,684 INFO (cc.eabour.websocket.WebSocketServer:23) - WebSocket is opening...2015-12-21 23:28:10,685 INFO (cc.eabour.websocket.WebSocketServer:25) - Sesson id: 1a2015-12-21 23:28:10,685 INFO (cc.eabour.websocket.WebSocketServer:26) - Query string: query=Picasso2015-12-21 23:28:10,731 INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: B2015-12-21 23:28:11,734 INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: C2015-12-21 23:28:12,739 INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: D2015-12-21 23:28:13,743 INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: E2015-12-21 23:28:14,746 INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: F2015-12-21 23:28:15,751 INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: G2015-12-21 23:28:16,753 INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: H2015-12-21 23:28:17,756 INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: I2015-12-21 23:28:18,758 INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: J2015-12-21 23:28:19,761 INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: send text: K2015-12-21 23:28:20,764 INFO (cc.eabour.websocket.WebSocketServer:42) - Websocket closed
客户端控制台:
{Sec-WebSocket-Version=[13], Upgrade=[websocket], Host=[localhost:8080], Sec-WebSocket-Key=[Wwy8SvU9vSmJClaLPw+z1w==], Connection=[upgrade]}org.apache.tomcat.websocket.WsHandshakeResponse@dd550cEncoder init: {}2015-12-21 23:28:10,700 INFO (cc.eabour.websocket.WebSocketServer:31) - Client WebSocket is opening...2015-12-21 23:28:10,731 INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server2015-12-21 23:28:11,735 INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server2015-12-21 23:28:12,740 INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server2015-12-21 23:28:13,744 INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server2015-12-21 23:28:14,748 INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server2015-12-21 23:28:15,752 INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server2015-12-21 23:28:16,754 INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server2015-12-21 23:28:17,757 INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server2015-12-21 23:28:18,759 INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server2015-12-21 23:28:19,762 INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket server
仔细一看,在注解中配置的Encoder和Decoder没有起作用,分别在encode和decode方法中添加打印语句,都没有生效:
public String decode(String paramString) throws DecodeException { // Auto-generated method stub return "MESS:" + paramString.toLowerCase(); } ..... public String encode(String paramT) throws EncodeException { //Auto-generated method stub System.out.println("encode: " + paramT); return "mess:" + paramT.toUpperCase(); }
最后通过查看encode和decode方法的调用堆栈,而得知调用这些方法的方法为sendObject,这时才恍然大悟,当客户端发送的为Object类型的时候,才会去调用Encoder和Decoder,所以修改方法:
//WebSocketClient.java public void send(Object message){ this.session.getAsyncRemote().sendObject(message); }
到此,大功告成:
--服务器2015-12-21 23:37:47,637 INFO (cc.eabour.websocket.WebSocketServer:23) - WebSocket is opening...2015-12-21 23:37:47,638 INFO (cc.eabour.websocket.WebSocketServer:25) - Sesson id: 1b2015-12-21 23:37:47,638 INFO (cc.eabour.websocket.WebSocketServer:26) - Query string: query=Picasso2015-12-21 23:37:47,670 INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: mess:SEND TEXT: B2015-12-21 23:37:48,671 INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: mess:SEND TEXT: C2015-12-21 23:37:49,673 INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: mess:SEND TEXT: D2015-12-21 23:37:50,683 INFO (cc.eabour.websocket.WebSocketServer:32) - Client send message: mess:SEND TEXT: E......--客户端{Sec-WebSocket-Version=[13], Upgrade=[websocket], Host=[localhost:8080], Sec-WebSocket-Key=[NGvTXYipeBUGuMn9SpwZWg==], Connection=[upgrade]}org.apache.tomcat.websocket.WsHandshakeResponse@1d28d39Encoder init: {}2015-12-21 23:37:47,639 INFO (cc.eabour.websocket.WebSocketServer:31) - Client WebSocket is opening...encode: send text: B2015-12-21 23:37:47,670 INFO (cc.eabour.websocket.WebSocketServer:37) - Server send message: Server message form Websocket serverencode: send text: C......
Java API WebSocket客户端基本实现,可以参照,实现更复杂的功能。
不吝赐教
项目Github地址:https://github.com/FlowerBirds/WebSocketExplorer
参考资料:
- https://tools.ietf.org/html/rfc6455#section-11.5
- https://tyrus.java.net/documentation/1.12/index/websocket-api.html
- Java API实现WebSocket客户端
- Java WebSocket客户端实现
- java websocket网页端客户端实现
- websocket客户端的实现
- js实现webSocket客户端
- WebSocket客户端java代码
- WebSocket 之 Java API
- 2、Java WebSocket实现服务端主动发消息给客户端
- Java Websocket实例【服务端与客户端实现全双工通讯】
- Websocket客户端的实现例子
- Android连接webSocket客户端实现
- php 异步websocket客户端实现
- C/C++ 实现websocket客户端
- 用java写websocket客户端
- 用java写websocket客户端
- Java实现WebSocket聊天
- Java实现WebSocket
- WebSocket的java实现
- Java爬取百度图片
- MAC下Android的Eclipse开发环境的搭建
- OOP思想与Java实现
- 保存输入和读取文件【python】
- android EditText 设置密码明文 密文 显示方法
- Java API实现WebSocket客户端
- 如何查找安装的 Java 版本(而不在 Windows 或 Mac 中运行小应用程序)?
- ubuntu更新时"Not enough free disk space"
- Android-Session Initiation Protocol(SIP)
- Linux Socket绑定的端口号和实际端口号不一致
- 黑马程序员——Eclipse快捷键
- 组合与继承
- msf笔记
- SQLLDR