基于WebSocket的Android与服务端通信

之前写了一篇socket简单的聊天,前些天同学问我android的websocket是怎么玩的,捣鼓了一番决定用websocket也来写个例子看看,就有了本篇文章。

服务端采用的是:Servlet+websocket,因为自己javaEE也是半桶水哈
哈,所以就简单的写了下,先来看看效果图:

websocket聊天

Android端使用的是Autobahn的包,支持Android 使用Websocket,下载地址:http://autobahn.ws/android/downloads/
具体与服务器的连接方法WebSocketConnection. Connect()方法,通过WebSocketHandler进行与服务器连接通讯。里面的具体方法不再详述。
与不同的客户端进行通讯的思路为:

Step1:在连接成功的时候,向服务器发送自己的用户名,服务器做用户标记;

Step2: 发送消息,格式为“XX@XXX”,@前面表示将要发送的对象,“all”表示群发,@后面表示发送的消息。

具体实现为,android端代码:

import android.support.v7.app.AppCompatActivity;  
import android.os.Bundle;  
import android.util.Log;  
import android.view.View;  
import android.widget.Button;  
import android.widget.EditText;  
import android.widget.TextView;  
import android.widget.Toast;  

import de.tavendo.autobahn.WebSocketConnection;  
import de.tavendo.autobahn.WebSocketException;  
import de.tavendo.autobahn.WebSocketHandler;  

public class MainActivity extends AppCompatActivity implements View.OnClickListener {  

    private static final String wsurl = "http://192.168.0.101:8080/websocketServer";  
    private static final String TAG = "MainActivity";  
    private WebSocketConnection mConnect = new WebSocketConnection();  
    private EditText mContent;  
    private Button mSend;  
    private TextView mText;  
    private EditText mUserName;  
    private EditText mToSb;  

    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        bindObject();  
        connect();  
    }  

    /** 
     * 绑定控件 
     */  
    private void bindObject() {  
        mContent = (EditText) findViewById(R.id.et_content);  
        mSend = (Button) findViewById(R.id.btn_send);  
        mText = (TextView) findViewById(R.id.tv_test);  
        mUserName = (EditText) findViewById(R.id.et_username);  
        mToSb = (EditText) findViewById(R.id.et_to);  
        mSend.setOnClickListener(this);  
    }  

    /** 
     * websocket连接,接收服务器消息 
     */  
    private void connect() {  
        Log.i(TAG, "ws connect....");  
        try {  
            mConnect.connect(wsurl, new WebSocketHandler() {  
                @Override  
                public void onOpen() {  
                    Log.i(TAG, "Status:Connect to " + wsurl);  
                    sendUsername();  
                }  

                @Override  
                public void onTextMessage(String payload) {  
                    Log.i(TAG, payload);  
                    mText.setText(payload != null ? payload : "");  
//                    mConnect.sendTextMessage("I am android client");  
                }  

                @Override  
                public void onClose(int code, String reason) {  
                    Log.i(TAG, "Connection lost..");  
                }  
            });  
        } catch (WebSocketException e) {  
            e.printStackTrace();  
        }  
    }  

    /** 
     * 发送用户名给服务器 
     */  
    private void sendUsername() {  
        String user = mUserName.getText().toString();  
        if (user != null && user.length() != 0)  
            mConnect.sendTextMessage(user);  
        else  
            Toast.makeText(getApplicationContext(), "不能为空", Toast.LENGTH_SHORT).show();  
    }  

    /** 
     * 发送消息 
     * 
     * @param msg 
     */  
    private void sendMessage(String msg) {  
        if (mConnect.isConnected()) {  
            mConnect.sendTextMessage(msg);  
        } else {  
            Log.i(TAG, "no connection!!");  
        }  
    }  

    @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        mConnect.disconnect();  
    }  

    @Override  
    public void onClick(View view) {  
        if (view == mSend) {  
            String content = mToSb.getText().toString() + "@" + mContent.getText().toString();  
            if (content != null && content.length() != 0)  
                sendMessage(content);  
            else  
                Toast.makeText(getApplicationContext(), "内容不能为空", Toast.LENGTH_SHORT).show();  
        }  
    }  
}  

服务端主要是对于客户端连接的用户进行处理与标记,并且根据客户端的要求向不同对象转发消息,实现不同客户端之间的通讯。具体代码如下:

import javax.websocket.*;  
import javax.websocket.server.ServerEndpoint;  
import java.io.IOException;  
import java.util.HashMap;  
import java.util.concurrent.CopyOnWriteArraySet;  

/** 
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端, 
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端 
 */  
@ServerEndpoint("/websocketServer")  
public class WebSocketTest {  

    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。  
    private static int onlineCount = 0;  

    //connect key为session的ID,value为此对象this  
    private static final HashMap<String, Object> connect = new HashMap<String, Object>();  
    //userMap key为session的ID,value为用户名  
    private static final HashMap<String, String> userMap = new HashMap<String, String>();  
    //与某个客户端的连接会话,需要通过它来给客户端发送数据  
    private Session session;  
    //判断是否是第一次接收的消息  
    private boolean isfirst = true;  

    private String username;  

    /** 
     * 连接建立成功调用的方法 
     * 
     * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据 
     */  
    @OnOpen  
    public void onOpen(Session session) {  
        this.session = session;  
        connect.put(session.getId(), this);//获取Session,存入Hashmap中  
    }  

    /** 
     * 连接关闭调用的方法 
     */  
    @OnClose  
    public void onClose(Session session) {  

        String usr = userMap.get(session.getId());  
        userMap.remove(session.getId());  
        connect.remove(session.getId());  


        System.out.println(usr + "退出!当前在线人数为" + connect.size());  
    }  

    /** 
     * 收到客户端消息后调用的方法 
     * 
     * @param message 客户端发送过来的消息 
     * @param session 可选的参数 
     */  
    @OnMessage  
    public void onMessage(String message, Session session) {  

        if (isfirst) {  
            this.username = message;  
            System.out.println("用户" + username + "上线,在线人数:" + connect.size());  
            userMap.put(session.getId(), username);  
            isfirst = false;  
        } else {  
            String[] msg = message.split("@", 2);//以@为分隔符把字符串分为xxx和xxxxx两部分,msg[0]表示发送至的用户名,all则表示发给所有人  
            if (msg[0].equals("all")) {  
                sendToAll(msg[1], session);  
            } else {  
                sendToUser(msg[0], msg[1], session);  
            }  
        }  
    }  

    /** 
     * 发生错误时调用 
     * 
     * @param session 
     * @param error 
     */  
    @OnError  
    public void onError(Session session, Throwable error) {  
        System.out.println("发生错误");  
        error.printStackTrace();  
    }  

    /** 
     * 给所有人发送消息 
     * 
     * @param msg     发送的消息 
     * @param session 
     */  
    private void sendToAll(String msg, Session session) {  
        String who = "";  
        //群发消息  
        for (String key : connect.keySet()) {  
            WebSocketTest client = (WebSocketTest) connect.get(key);  
            if (key.equalsIgnoreCase(userMap.get(key))) {  
                who = "自己对大家说 : ";  
            } else {  
                who = userMap.get(session.getId()) + "对大家说 :";  
            }  
            synchronized (client) {  
                try {  
                    client.session.getBasicRemote().sendText(who + msg);  
                } catch (IOException e) {  
                    connect.remove(client);  
                    e.printStackTrace();  
                    try {  
                        client.session.close();  
                    } catch (IOException e1) {  
                        e1.printStackTrace();  
                    }  
                }  
            }  

        }  
    }  

    /** 
     * 发送给指定用户 
     * 
     * @param user    用户名 
     * @param msg     发送的消息 
     * @param session 
     */  
    private void sendToUser(String user, String msg, Session session) {  
        boolean you = false;//标记是否找到发送的用户  
        for (String key : userMap.keySet()) {  
            if (user.equalsIgnoreCase(userMap.get(key))) {  
                WebSocketTest client = (WebSocketTest) connect.get(key);  
                synchronized (client) {  
                    try {  
                        client.session.getBasicRemote().sendText(userMap.get(session.getId()) + "对你说:" + msg);  
                    } catch (IOException e) {  
                        connect.remove(client);  
                        try {  
                            client.session.close();  
                        } catch (IOException e1) {  
                            e1.printStackTrace();  
                        }  
                    }  
                }  
                you = true;//找到指定用户标记为true  
                break;  
            }  

        }  
        //you为true则在自己页面显示自己对xxx说xxxxx,否则显示系统:无此用户  
        if (you) {  
            try {  
                session.getBasicRemote().sendText("自己对" + user + "说:" + msg);  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        } else {  
            try {  
                session.getBasicRemote().sendText("系统:无此用户");  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  

    }  

}  

完整演示代码

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用和引用的内容,AndroidWebSocket通常被用作客户的应用场景,而较少用作服务。但是,在引用中提到,作者通过学习了解了WebSocket,并成功搭建了一个Android WebSocket服务。不过,作者也指出自己在WebSocket方面并不是特别精通,并希望能够得到指正。所以,我们可以根据作者提供的代码和引用中的相关内容,来了解如何在Android中搭建WebSocket服务。 首先,根据引用中提到的代码,作者使用了Java-WebSocket库来实现WebSocket服务,具体的依赖为"org.java-websocket:Java-WebSocket:1.3.6"。这个库提供了WebSocket服务器的实现,可以用于搭建WebSocket服务。 其次,根据引用中提到的第一步和第二步,我们需要在Android项目中添加权限和依赖,其中权限是指定网络权限,依赖则是引用了版本为1.5.1的Java-WebSocket库。这些步骤是为了确保项目能够正常使用WebSocket功能。 最后,根据引用中提到的第三步,我们需要创建一个WebSocket客户工具类,继承自org.java_websocket.client.WebSocketClient。这个工具类可以用于建立连接并处理WebSocket通信。 总结来说,要在Android中搭建WebSocket服务,我们可以使用Java-WebSocket库,并按照作者提供的代码和引用中的相关内容来实现。这样我们就可以在Android应用中建立WebSocket服务,并进行WebSocket通信了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Android搭建WebSocket服务](https://blog.csdn.net/android_fcp/article/details/82983236)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Android WebSocket 简单 Demo](https://download.csdn.net/download/han1202012/85012130)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Android 网络通信WebSocket使用详解](https://blog.csdn.net/fusu2178192/article/details/125603554)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值