WebSocket实现Android客户端之间的简单通讯

来源:互联网 发布:linux 发送arp包 编辑:程序博客网 时间:2024/06/06 11:42

作为一个刚毕业的程序猴,自觉的自己能力比较欠缺,正好最近公司没有什么项目,就考虑自己动手做个项目。想来想去,就把自己一直想做的即时通讯拿出来做做。可是问题来了,作为一个Android开发人员,一直没有接触后台的人来说,做一个完整的项目还是比较麻烦的。于是只有边学边做了。

对于通讯来说,我对Websocket情有独钟,可能是因为在学校的时候听说过吧。话不多说,经过几天的调研,终于在搭了一个简单的Servlet+websocket服务器,并且能在android客户端上实现不同客户端之间的通讯。我想这是万里长征的第一步的成功吧。话不多说,进入正题。

效果图如下:




Android端这里使用的是Autobahn的包,支持Android 使用Websocket,下载地址:http://autobahn.ws/android/downloads/;

具体与服务器的连接方法WebSocketConnection. Connect()方法,通过WebSocketHandler进行与服务器连接通讯。里面的具体方法不再详述。

与不同的客户端进行通讯的思路为:

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

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

Step3: 当然不能忘了网路权限。

 

 

Android端的只有代码如下:


[java] view plain copy
  1. package henry.websocket.test;  
  2.   
  3. import android.support.v7.app.AppCompatActivity;  
  4. import android.os.Bundle;  
  5. import android.util.Log;  
  6. import android.view.View;  
  7. import android.widget.Button;  
  8. import android.widget.EditText;  
  9. import android.widget.TextView;  
  10. import android.widget.Toast;  
  11.   
  12. import de.tavendo.autobahn.WebSocketConnection;  
  13. import de.tavendo.autobahn.WebSocketException;  
  14. import de.tavendo.autobahn.WebSocketHandler;  
  15.   
  16. public class MainActivity extends AppCompatActivity implements View.OnClickListener {  
  17.   
  18.     private static final String wsurl = "ws://172.16.50.126:8080/websocketServer";  
  19.     private static final String TAG = "MainActivity";  
  20.     private WebSocketConnection mConnect = new WebSocketConnection();  
  21.     private EditText mContent;  
  22.     private Button mSend;  
  23.     private TextView mText;  
  24.     private EditText mUserName;  
  25.     private EditText mToSb;  
  26.   
  27.     @Override  
  28.     protected void onCreate(Bundle savedInstanceState) {  
  29.         super.onCreate(savedInstanceState);  
  30.         setContentView(R.layout.activity_main);  
  31.         bindObject();  
  32.         connect();  
  33.     }  
  34.   
  35.     /** 
  36.      * 绑定控件 
  37.      */  
  38.     private void bindObject() {  
  39.         mContent = (EditText) findViewById(R.id.et_content);  
  40.         mSend = (Button) findViewById(R.id.btn_send);  
  41.         mText = (TextView) findViewById(R.id.tv_test);  
  42.         mUserName = (EditText) findViewById(R.id.et_username);  
  43.         mToSb = (EditText) findViewById(R.id.et_to);  
  44.         mSend.setOnClickListener(this);  
  45.     }  
  46.   
  47.     /** 
  48.      * websocket连接,接收服务器消息 
  49.      */  
  50.     private void connect() {  
  51.         Log.i(TAG, "ws connect....");  
  52.         try {  
  53.             mConnect.connect(wsurl, new WebSocketHandler() {  
  54.                 @Override  
  55.                 public void onOpen() {  
  56.                     Log.i(TAG, "Status:Connect to " + wsurl);  
  57.                     sendUsername();  
  58.                 }  
  59.   
  60.                 @Override  
  61.                 public void onTextMessage(String payload) {  
  62.                     Log.i(TAG, payload);  
  63.                     mText.setText(payload != null ? payload : "");  
  64. //                    mConnect.sendTextMessage("I am android client");  
  65.                 }  
  66.   
  67.                 @Override  
  68.                 public void onClose(int code, String reason) {  
  69.                     Log.i(TAG, "Connection lost..");  
  70.                 }  
  71.             });  
  72.         } catch (WebSocketException e) {  
  73.             e.printStackTrace();  
  74.         }  
  75.     }  
  76.   
  77.     /** 
  78.      * 发送用户名给服务器 
  79.      */  
  80.     private void sendUsername() {  
  81.         String user = mUserName.getText().toString();  
  82.         if (user != null && user.length() != 0)  
  83.             mConnect.sendTextMessage(user);  
  84.         else  
  85.             Toast.makeText(getApplicationContext(), "不能为空", Toast.LENGTH_SHORT).show();  
  86.     }  
  87.   
  88.     /** 
  89.      * 发送消息 
  90.      * 
  91.      * @param msg 
  92.      */  
  93.     private void sendMessage(String msg) {  
  94.         if (mConnect.isConnected()) {  
  95.             mConnect.sendTextMessage(msg);  
  96.         } else {  
  97.             Log.i(TAG, "no connection!!");  
  98.         }  
  99.     }  
  100.   
  101.     @Override  
  102.     protected void onDestroy() {  
  103.         super.onDestroy();  
  104.         mConnect.disconnect();  
  105.     }  
  106.   
  107.     @Override  
  108.     public void onClick(View view) {  
  109.         if (view == mSend) {  
  110.             String content = mToSb.getText().toString() + "@" + mContent.getText().toString();  
  111.             if (content != null && content.length() != 0)  
  112.                 sendMessage(content);  
  113.             else  
  114.                 Toast.makeText(getApplicationContext(), "不能为空", Toast.LENGTH_SHORT).show();  
  115.         }  
  116.     }  
  117. }  

服务器端主要是借鉴别人的,具体见http://www.mobile-open.com/2016/968477.html;主要是对于客户端连接的用户进行处理与标记,并且根据客户端的要求向不同对象转发消息,实现不同客户端之间的通讯。具体代码如下:

[java] view plain copy
  1. import javax.websocket.*;  
  2. import javax.websocket.server.ServerEndpoint;  
  3. import java.io.IOException;  
  4. import java.util.HashMap;  
  5. import java.util.concurrent.CopyOnWriteArraySet;  
  6.   
  7. /** 
  8.  * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端, 
  9.  * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端 
  10.  */  
  11. @ServerEndpoint("/websocketServer")  
  12. public class WebSocketTest {  
  13.   
  14.     //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。  
  15.     private static int onlineCount = 0;  
  16.   
  17.     //connect key为session的ID,value为此对象this  
  18.     private static final HashMap<String, Object> connect = new HashMap<String, Object>();  
  19.     //userMap key为session的ID,value为用户名  
  20.     private static final HashMap<String, String> userMap = new HashMap<String, String>();  
  21.     //与某个客户端的连接会话,需要通过它来给客户端发送数据  
  22.     private Session session;  
  23.     //判断是否是第一次接收的消息  
  24.     private boolean isfirst = true;  
  25.   
  26.     private String username;  
  27.   
  28.     /** 
  29.      * 连接建立成功调用的方法 
  30.      * 
  31.      * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据 
  32.      */  
  33.     @OnOpen  
  34.     public void onOpen(Session session) {  
  35.         this.session = session;  
  36.         connect.put(session.getId(), this);//获取Session,存入Hashmap中  
  37.     }  
  38.   
  39.     /** 
  40.      * 连接关闭调用的方法 
  41.      */  
  42.     @OnClose  
  43.     public void onClose(Session session) {  
  44.   
  45.         String usr = userMap.get(session.getId());  
  46.         userMap.remove(session.getId());  
  47.         connect.remove(session.getId());  
  48.   
  49.   
  50.         System.out.println(usr + "退出!当前在线人数为" + connect.size());  
  51.     }  
  52.   
  53.     /** 
  54.      * 收到客户端消息后调用的方法 
  55.      * 
  56.      * @param message 客户端发送过来的消息 
  57.      * @param session 可选的参数 
  58.      */  
  59.     @OnMessage  
  60.     public void onMessage(String message, Session session) {  
  61.   
  62.         if (isfirst) {  
  63.             this.username = message;  
  64.             System.out.println("用户" + username + "上线,在线人数:" + connect.size());  
  65.             userMap.put(session.getId(), username);  
  66.             isfirst = false;  
  67.         } else {  
  68.             String[] msg = message.split("@"2);//以@为分隔符把字符串分为xxx和xxxxx两部分,msg[0]表示发送至的用户名,all则表示发给所有人  
  69.             if (msg[0].equals("all")) {  
  70.                 sendToAll(msg[1], session);  
  71.             } else {  
  72.                 sendToUser(msg[0], msg[1], session);  
  73.             }  
  74.         }  
  75.     }  
  76.   
  77.     /** 
  78.      * 发生错误时调用 
  79.      * 
  80.      * @param session 
  81.      * @param error 
  82.      */  
  83.     @OnError  
  84.     public void onError(Session session, Throwable error) {  
  85.         System.out.println("发生错误");  
  86.         error.printStackTrace();  
  87.     }  
  88.   
  89.     /** 
  90.      * 给所有人发送消息 
  91.      * 
  92.      * @param msg     发送的消息 
  93.      * @param session 
  94.      */  
  95.     private void sendToAll(String msg, Session session) {  
  96.         String who = "";  
  97.         //群发消息  
  98.         for (String key : connect.keySet()) {  
  99.             WebSocketTest client = (WebSocketTest) connect.get(key);  
  100.             if (key.equalsIgnoreCase(userMap.get(key))) {  
  101.                 who = "自己对大家说 : ";  
  102.             } else {  
  103.                 who = userMap.get(session.getId()) + "对大家说 :";  
  104.             }  
  105.             synchronized (client) {  
  106.                 try {  
  107.                     client.session.getBasicRemote().sendText(who + msg);  
  108.                 } catch (IOException e) {  
  109.                     connect.remove(client);  
  110.                     e.printStackTrace();  
  111.                     try {  
  112.                         client.session.close();  
  113.                     } catch (IOException e1) {  
  114.                         e1.printStackTrace();  
  115.                     }  
  116.                 }  
  117.             }  
  118.   
  119.         }  
  120.     }  
  121.   
  122.     /** 
  123.      * 发送给指定用户 
  124.      * 
  125.      * @param user    用户名 
  126.      * @param msg     发送的消息 
  127.      * @param session 
  128.      */  
  129.     private void sendToUser(String user, String msg, Session session) {  
  130.         boolean you = false;//标记是否找到发送的用户  
  131.         for (String key : userMap.keySet()) {  
  132.             if (user.equalsIgnoreCase(userMap.get(key))) {  
  133.                 WebSocketTest client = (WebSocketTest) connect.get(key);  
  134.                 synchronized (client) {  
  135.                     try {  
  136.                         client.session.getBasicRemote().sendText(userMap.get(session.getId()) + "对你说:" + msg);  
  137.                     } catch (IOException e) {  
  138.                         connect.remove(client);  
  139.                         try {  
  140.                             client.session.close();  
  141.                         } catch (IOException e1) {  
  142.                             e1.printStackTrace();  
  143.                         }  
  144.                     }  
  145.                 }  
  146.                 you = true;//找到指定用户标记为true  
  147.                 break;  
  148.             }  
  149.   
  150.         }  
  151.         //you为true则在自己页面显示自己对xxx说xxxxx,否则显示系统:无此用户  
  152.         if (you) {  
  153.             try {  
  154.                 session.getBasicRemote().sendText("自己对" + user + "说:" + msg);  
  155.             } catch (IOException e) {  
  156.                 e.printStackTrace();  
  157.             }  
  158.         } else {  
  159.             try {  
  160.                 session.getBasicRemote().sendText("系统:无此用户");  
  161.             } catch (IOException e) {  
  162.                 e.printStackTrace();  
  163.             }  
  164.         }  
  165.   
  166.     }  
  167.   
  168. }  

虽然实现了简单的通讯,但要做成一个完整的项目,这还远远不够,下面要考虑的东西还很多。

 

 

 

代码地址:http://download.csdn.net/detail/henry__mark/9637322;

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 医保卡丢了补办后卡里余额怎么办 银行卡丢了记不住卡号怎么办 哈尔滨医保卡挂失后又找到了怎么办 孩子在哈尔滨户口在外地医保怎么办 椒江二桥通行证被扣走了怎么办 住建委查到买房材料不真怎么办 房子租出去被别人又租出去了怎么办 在成都乘出租车房产证掉了怎么办 电信不限量卡限网速了怎么办 only实体店换货没有小票怎么办 运管所包车单不给盖章怎么办 上海留学生落户过了取号时间怎么办 电信固话怎么办才能显示自己公司 日本跟团签证没有资产证明怎么办 摇号手机号换了密码忘了怎么办 小客车摇号的账号密码忘了怎么办 去银行交违章罚款单子丢了怎么办 我的身份证被别人办了信用卡怎么办 北京驾驶证在深圳扣了分怎么办 c照一次被扣12分怎么办 教师资格证认定申请表填错了怎么办 外地车在北京违章没有牡丹卡怎么办 护士辞职了原单位不给延续怎么办 护士证注册的单位倒闭了怎么办 护士证注册的医院倒闭了怎么办 显示发货了但没物流信息怎么办 考科目三被别人举报了怎么办 科目一考了5没过怎么办 常州c1驾驶证满了12分怎么办 预约科目三成功后没交钱怎么办 预约成功后驾校不提交档案怎么办 c2刚满一年的驾照扣12分怎么办 怀孕6个月咳嗽很厉害怎么办 家门口有电线杆影响我建楼房怎么办 卡丢了不知道卡号怎么办 驾考网上预约用户被锁定了怎么办 人才中心拿出来的户口掉了怎么办 父母是南京集体户孩子没户口怎么办 二建挂靠中介单位不给证怎么办 小包工头遇到工人在工地摔伤怎么办 外地人买了城中村的房子改造怎么办