您的位置:首页 > 移动开发 > Android开发

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

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

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

效果图如下:



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

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

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

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

Step2: 发送消息,格式为“XX@XXX”,@前面表示将要发送的对象,“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<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();
}
}

}

}

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

 

 

 

代码地址:http://download.csdn.net/detail/henry__mark/9637322
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  websocket android 通讯