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

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

基于WebSocket的Android与服务端通信_第1张图片

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 connect = new HashMap();      //userMap key为session的ID,value为用户名      private static final HashMap userMap = new HashMap();      //与某个客户端的连接会话,需要通过它来给客户端发送数据      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();              }          }      }  }  

完整演示代码

更多相关文章

  1. Android几种消息推送方案总结
  2. Android socket 编程 实现消息推送(二)
  3. [原]Android应用程序消息处理机制(Looper、Handler)分析
  4. Android消息推送完美解决方案全析
  5. Android客户端性能参数监控
  6. Android连接SQLServer详细教程(数据库+服务器+客户端),并在微软Azur

随机推荐

  1. 上线俩月,TensorFlow 2.0被吐槽太难用,网友
  2. Virtual Apps and Desktops 2103版发布
  3. 【uni-app】引入阿里巴巴图标库
  4. 用 Python 来了解一下《安家》
  5. 让隐藏视窗的Dock成半透明状态
  6. 【微信小程序】自定义导航栏(一)
  7. 【微信小程序】自定义导航栏(二)
  8. 如何在Safari浏览器中设置活跃及其他网站
  9. 20210225-1 Python错误与异常
  10. 如何在Mac上的“照片”中使用滤镜来更改