文档章节

websocket服务端,android客户端示例

Hackway
 Hackway
发布于 2016/03/02 01:55
字数 1184
阅读 332
收藏 2
点赞 1
评论 3

服务端库依赖详见章末

#####spring websocket服务端代码(会话过程)

public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor {
    private static final Logger logger = LoggerFactory.getLogger(HandshakeInterceptor.class);

    //会话开始
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        attributes.put(Constant.WEBSOCKET_USERNAME,"LSH");
        //  从session中获取用户
        /*if (request instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest) request;
            HttpSession session = serverHttpRequest.getServletRequest().getSession(false);
            if (session!=null) {
                String username = (String) session.getAttribute(Constant.SESSION_USERNAME);
                attributes.put(Constant.WEBSOCKET_USERNAME,username);
            }
        }*/
        return true;
    }

    //会话结束
    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {
        System.out.println("After Handshake");
        super.afterHandshake(request, response, wsHandler, ex);
    }
}

#####服务端websocket消息处理

import com.beesgame.sanguo.constant.Constant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.ArrayList;

/**
 * Created by hackway on
 * Date: 2016/1/15.
 * Time:11:15
 */
public class WebSocketEndPoint extends TextWebSocketHandler {

    private static final ArrayList<WebSocketSession> users;
    private static final Logger logger;

    static {
        users = new ArrayList<WebSocketSession>();
        logger = LoggerFactory.getLogger(WebSocketEndPoint.class);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        super.handleTextMessage(session, message);
        TextMessage returnMessage = new TextMessage(message.getPayload()+" received at server");
        session.sendMessage(returnMessage);
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        logger.info("connect to the websocket success......");
        //添加用户到session
        users.add(session);
        String username = (String) session.getAttributes().get(Constant.WEBSOCKET_USERNAME);
        if (username!=null) {
            session.sendMessage(new TextMessage("用户名:"+username));
        }
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        if (session.isOpen()) {
            session.close();
        }
        logger.info("websocket transport error, connection closed......");
        users.remove(session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        logger.info("websocket connection closed......");
        users.remove(session);
    }

    @Override
    public boolean supportsPartialMessages() {
        return super.supportsPartialMessages();
    }

    // 发送信息给特定用户(LSH)
    public void sendMessageToUser(String username, TextMessage message) {
        for (WebSocketSession user:users) {
            if (user.getAttributes().get(Constant.WEBSOCKET_USERNAME).equals(username)) {
                try {
                    if (user.isOpen()) {
                        user.sendMessage(message);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            }
        }
    }

     //发送信息给所用用户,广播
    public void sendMessageToAllUser(TextMessage message) {
        for (WebSocketSession user:users) {
            try {
                if (user.isOpen()) {
                    user.sendMessage(message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

#####使用注解配置websocket(需要在springmvc配置文件中开启相应注解支持)

@Configuration
//@EnableWebMvc
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
        webSocketHandlerRegistry.addHandler(getWebSocketEndPoint(),"/websocket").addInterceptors(new HandshakeInterceptor());
        webSocketHandlerRegistry.addHandler(getWebSocketEndPoint(),"/websocket/sockjs").addInterceptors(new HandshakeInterceptor()).withSockJS();
    }

    @Bean
    public WebSocketEndPoint getWebSocketEndPoint() {
        return new WebSocketEndPoint();
    }
}

#####controller调用websocket发送信息

@Controller("/*")
public class IndexController extends BaseController {



    @Autowired
    private UserInfoService userInfoService;
    
    //注入websocket
    @Bean
    public WebSocketEndPoint getWebSocketEndpoint() {
        return new WebSocketEndPoint();
    }

    @RequestMapping(value = "socket.do", produces = "text/json;charset=UTF-8", method = RequestMethod.GET)
    @ResponseBody
    public String socket(@RequestParam(value = "uid") long uid) throws IOException {
        UserInfoVO userToken = userInfoService.getUserInfoVOByUid(uid);
        String result = objectMapper.writeValueAsString(userToken);
        getWebSocketEndpoint().sendMessageToUser("LSH", new TextMessage(result));
        return result;
    }
}

#####服务端启动截图 
输入图片说明

#####客户端websocket链接服务端(android) java-websocket 项目地址 https://github.com/TooTallNate/Java-WebSocket

gradle中添加java-websocket依赖 ######compile 'org.java-websocket:Java-WebSocket:1.3.0'

#####websocket客户端类

import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.drafts.Draft_17;
import org.java_websocket.handshake.ServerHandshake;

import java.net.URI;
import java.util.Date;

/**
 * Created by hackway on 16/2/24.
 */
public class SiteWebsocket extends WebSocketClient {


    //handler通知主线程更新textview
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            textView.setText(String.valueOf(msg.obj));
        }
    };
    private TextView textView;
    public SiteWebsocket(URI serverUri, Draft draft, TextView tv) {
        super(serverUri, draft);
        this.textView = tv;
    }
    @Override
    public void onOpen(ServerHandshake handshakedata) {
        Log.d("websocket","open connection");
    }

    @Override
    public void onMessage(String message) {
        Log.d("websocket","receive: "+message);
        Message msg = new Message();
        msg.obj = message;
        handler.sendMessage(msg);
    }

    @Override
    public void onClose(int code, String reason, boolean remote) {
        Log.d("websocket","Connection close by "+(remote?"remote peer":"us") +" at "+new Date(System.currentTimeMillis()));
    }

    @Override
    public void onError(Exception ex) {
        ex.printStackTrace();
    }
}



#####客户端建立链接(MainActivity.java)

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;

import org.java_websocket.drafts.Draft_17;

import java.net.URI;
import java.net.URISyntaxException;

import site.hackway.www.androidsite.websocket.SiteWebsocket;

public class MainActivity extends AppCompatActivity {

    private TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        textView = (TextView) findViewById(R.id.txvw);
        SiteWebsocket siteWebsocket = null;
        try {
            siteWebsocket = new SiteWebsocket(new URI("ws://192.168.1.103:8080/sanguo/websocket"),new Draft_17(),textView);
            siteWebsocket.connectBlocking();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        /*FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }

        });*/
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

客户端代码编写完毕,启动模拟器(注意客户端服务端需处于统一局域网)

输入图片说明

出现 用户名:LSH 说明连接成功

接着测试服务端向客户端发送消息 通过浏览器访问 http://ip:port/your project name/socket.do?uid=1

输入图片说明

服务端推送信息成功

服务端maven依赖,(其中spring的版本需要大于4)

    <properties>
		<spring.version>4.2.4.RELEASE</spring.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-expression</artifactId>
			<version>${spring.version}</version>
		</dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-websocket</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-messaging</artifactId>
            <version>${spring.version}</version>
        </dependency>
		<dependency>
			<groupId>org.freemarker</groupId>
			<artifactId>freemarker</artifactId>
			<version>2.3.20</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-core</artifactId>
			<version>2.1.0</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.1.0</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-annotations</artifactId>
			<version>2.1.0</version>
		</dependency>

		<!-- logback日志配置 -->
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>1.1.3</version>
		</dependency>
		<dependency>
			<groupId>org.logback-extensions</groupId>
			<artifactId>logback-ext-spring</artifactId>
			<version>0.1.2</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>1.7.12</version>
		</dependency>
	</dependencies>

© 著作权归作者所有

共有 人打赏支持
Hackway
粉丝 2
博文 7
码字总数 2711
作品 0
广州
程序员
加载中

评论(3)

k
klx502

引用来自“klx502”的评论

大神,那个ios的例子没在你下一遍看到啊13

引用来自“Hackway”的评论

不好意思最近比较忙,没时间整理!
大神,我Android端传过来的参数都是乱码,我是用maven搭建的。请问怎么解决啊?
Hackway
Hackway

引用来自“klx502”的评论

大神,那个ios的例子没在你下一遍看到啊13
不好意思最近比较忙,没时间整理!
k
klx502
大神,那个ios的例子没在你下一遍看到啊13
Spring实践--Websocket集成和XML配置

WebSocket 简介 WebSocket 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在 TCP 之上,同 HTTP 一样通过 TCP 来传输数据,...

spinachgit ⋅ 05/03 ⋅ 0

从HTML5 WebSocket到Socket.io

HTML5 WebSocket 作为新一代的web标准,HTML5为我们提供了很多有用的东西,比如canvas,本地存储(已经分离出去了),多媒体编程接口,当然还有我们的WebSocket。WebSocket是HTML5开始提供的...

Srtian ⋅ 05/11 ⋅ 0

Workerman如何在WebSocket响应中添加Header

最近在用 Workerman 学习 WebSocket 的时候,遇到了一个问题: 结果浏览器报了这个错: Error during WebSocket handshake: Sent non-empty ‘Sec-WebSocket-Protocol’ header but no resp...

supergao222 ⋅ 04/28 ⋅ 0

Dva 中使用 WebSocket

一、概述 Websocket 是 H5 自带的一个 API,随着越来越多的浏览器都自适应了 H5 的特性,许多浏览器也内置了 WebSocket API。也就是说 WebSocket 和 window、document 一样作为全局变量可以直...

dkvirus ⋅ 05/28 ⋅ 0

基于 JavaFX 开发的聊天客户端 - OIM

一、简介 OIM是一套即时通讯的聊天系统,在这里献给大家,一方面希望能够帮助对即时通讯有兴趣研究的朋友,希望我们能够共同进步,另一个就是希望能够帮助到需要即时通讯系统的朋友或者企业,...

烙灵 ⋅ 2017/06/09 ⋅ 23

推荐2个前端工具:Charles和Postman

5.1假期第二天,依然窝在家里,不过今天来客了,我的好朋友「晓哥」来看小宝,中午喝了点,各自「吹嘘」了一阵,聊聊各自职业的发展,工作中遇到的问题,以及对未来的规划。 他现在发展的特别...

情情说 ⋅ 05/02 ⋅ 0

JavaScript 工作原理之五-深入理解 WebSockets 和带有 SSE 机制的HTTP/2 以及正确的使用姿势(译)

原文请查阅这里,略有改动,本文采用知识共享署名 3.0 中国大陆许可协议共享,BY Troland。 本系列持续更新中,Github 地址请查阅这里。 这是 JavaScript 工作原理的第五章。 现在,我们将会...

tristan ⋅ 05/11 ⋅ 0

使用WebSocket制作简单的聊天室

使用WebSocket制作简单的聊天室 一、功能需求 ①第一次进入聊天室,输入用户的昵称,用于聊天消息显示名称 ②用户进入系统后,系统需要提示所有用户,有新用户进入系统了 ③用户发送消息时要...

JS_HCX ⋅ 05/27 ⋅ 0

HTML5 WebSocket JavaWeb 实现简单的聊天室功能

本实例使用websocket实现了即时聊天系统,websocket技术可以在网页中使用js技术完成与后台的通讯, 而后台tomcat集成了websocket功能, 只需要很少的代码就可以完成很强大的功能, 基于此聊天系...

智慧点点 ⋅ 04/23 ⋅ 0

从Chrome源码看WebSocket

WebSocket是为了解决双向通信的问题,因为一方面HTTP的设计是单向的,只能是一边发另一边收。而另一方面,HTTP等都是建立在TCP连接之上的,HTTP请求完就会把TCP给关了,而TCP连接本身就是一个...

人人网FED ⋅ 05/27 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Mahout推荐算法API详解

前言 用Mahout来构建推荐系统,是一件既简单又困难的事情。简单是因为Mahout完整地封装了“协同过滤”算法,并实现了并行化,提供非常简单的API接口;困难是因为我们不了解算法细节,很难去根...

xiaomin0322 ⋅ 22分钟前 ⋅ 0

WampServer默认web服务器根目录位置

安装WampServer之后的web服务器根目录默认位置在WampServer安装目录下的www:

临江仙卜算子 ⋅ 23分钟前 ⋅ 0

Redux的一些手法记录

Redux Redux的基本概念见另一篇文。 这里记录一下Redux在项目中的实际操作的手法。 actions 首先定义action.js,actions的type,可以另起一个action-type.js文件。 action-type.js用来存...

LinearLaw ⋅ 24分钟前 ⋅ 0

android 手势检测(左右滑动、上下滑动)

GestureDetector类可以让我们快速的处理手势事件,如点击,滑动等。 使用GestureDetector分三步: 1. 定义GestureDetector类 2. 初始化手势类,同时设置手势监听 3. 将touch事件交给gesture...

王先森oO ⋅ 39分钟前 ⋅ 0

java 方法的执行时间监控 设置超时(Future 接口)

java 方法的执行时间监控 设置超时(Future 接口) import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor......

青峰Jun19er ⋅ 43分钟前 ⋅ 0

一名开源小白的Apache成长自述

今天收到了来自Apache Vote我成为Serviceomb项目Committer的邮件,代表自己的贡献得到了充分的肯定;除了感谢团队的给力支持,我更希望将自己的成长经历——如何践行Apache Way的心得介绍给大...

微服务框架 ⋅ 45分钟前 ⋅ 0

vim介绍、颜色显示和移动光标、一般模式下复制、剪切和粘贴

1.vim 是 vi 的升级版 vim 是带有颜色显示的 mini安装的系统,一般都不带有vim [root@aminglinux-128 ~]# yum install -y vim-enhanced已加载插件:fastestmirror, langpacksLoading mir...

oschina130111 ⋅ 46分钟前 ⋅ 0

Deepin 操作系统四面楚歌

作为国内做的最好的 Linux 发行版,源自 Debian sid 的 Deepin 目前正面临重重困境,新版本不断延期,开发人员离职,bug 长期得不到修复,和 Debian/Ubuntu 的兼容性问题也面临越来越严重的挑...

六库科技 ⋅ 46分钟前 ⋅ 0

MyBatis之动态sql

我们需要知道的是,使用mybatis重点是对sql的灵活解析和处理。在原先的UserMappser.xml中,我们这样查询表中满足条件的记录 : 123 <select id="findUserList" parameterType="userQuery...

瑟青豆 ⋅ 46分钟前 ⋅ 0

这届俄罗斯世界杯的冷门那么多怎么办?

最纯粹的世界杯,最神奇的大冷门。 德国0比1被墨西哥摩擦了。 日本历史性的赢了哥伦比亚。 C罗也挑平了西班牙。 梅西被冰岛狮吼吼愣神了。 就连11次进世界杯4强的巴西也被瑞士逼平了。 天台已...

开源中国众包平台 ⋅ 47分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部