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

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

效果图如下:

 

 

 

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

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

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

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

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

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

 

 

Android端的只有代码如下:

 

 

package henry.websocket.test;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 = "ws://172.16.50.126: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();        }    }}

 

 

 

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

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();            }        }    }}

 

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

 

 

 

 

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

====================================2018============================

由于CSDN积分规则的变化,原有的免费代码,现在都需要,违背开源精神,这里提供一个新的地址,供大家交流。

 

github:https://github.com/Henry-Mark/WebSocketConnectAndroid;

 

 

 

更多相关文章

  1. 成功的向android推送信息——android推技术!
  2. Android(安卓)手机蓝牙 (普通蓝牙篇)
  3. Android-小巫新闻客户端底部菜单切换实现
  4. 【android极光推送】—从客户端到后台,一文通吃
  5. android 创建socket失败
  6. 电脑通过豌豆荚连接手机或者平板不成功,豌豆荚版本6.8.*
  7. [置顶] Android即时通信软件设计(一)(网络通信)
  8. Android菜谱应用客户端
  9. 图片、缓存-Android仿人人客户端(v5.7.1)——对从服务器端(网络)获取

随机推荐

  1. Android中日期操作总结
  2. 转载 Android(安卓)脚本设计之 SL4A
  3. conversion to dalvik format failed wit
  4. 有关Android(安卓)SQLite编程的一些知识
  5. Mac OS X 下编译android源码
  6. Android命令行打包过程
  7. android 面试题经典
  8. 深入理解Android消息处理系统——Looper
  9. Android学习笔记(8) - GridView与ImageVi
  10. [置顶] android ScrollView滚动距离和判