- 浏览: 361368 次
- 性别:
- 来自: 南京
文章分类
最新评论
-
nglxl:
点赞啊,必须点赞!!深度好文,解决了困扰我多年的疑惑。
tcp 长连接与短连接 -
cofftech:
opengl源码http://www.eyesourcecod ...
OPenGL ES 关键API小结 -
mail_j:
不是很好用,很多情况都不能处理 1、没有区分关键字的大小写2、 ...
Java解析sql语句,分析出调用到的所有表 -
a455642158:
就算监听到变成了cmwap还不行,还得监听网络连接状态Stat ...
android APN切换cmwap实现 -
xuhl1022:
看了您的android 4篇 浏览器二次开发,感触颇深,写的很 ...
Android浏览器Browser二次开发(四)浏览器中的APN切换
先上个游戏截图:
豌豆荚地址: http://apps.wandoujia.com/search?key=%E5%85%A8%E6%B0%91%E7%AD%94%E9%A2%98&source=index
本文概要介绍如何通过java nio来开发android客户端与服务器socket通信的过程。
1. 为什么要用java NIO
常规的socket通信为阻塞方式,服务器接收到消息并进行处理,处理完一个才能处理下一个。 如果要同时处理,就得自己开线程,为每一个客户端连接做一个线程,这样当连接数大的情况下,上万以上,服务器就难以承受了。 JAVA NIO是jdk1.4提供的API, 主要原理是以监听机制来处理客户端的连接。主要包含buffer和channel.
2. 服务器示例代码
package com.seya.onlineserver.socket.nio;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Vector;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.seya.onlineserver.jpush.JPushManager;
import com.seya.onlineserver.socket.dao.UserDAO;
import com.seya.onlineserver.socket.nio.Room.State;
/**
* NIO服务端
* @author Seyason
*/
public class NIOServer implements MsgProcessor{
//用户在线标示
public static final int STATUS_ONLINE = 1;
public static final int STATUS_OFFLINE = 0;
private static final int PORT = 2121;
//全部用户集合
private Vector<UserClient> allUserList = new Vector<UserClient>();
//房间数
private Vector<Room> oneVRoomList = new Vector<Room>();
private Vector<Room> twoVRoomList = new Vector<Room>();
private Vector<Room> threeVRoomList = new Vector<Room>();
public static Vector<UserClient> idleUserList = new Vector<UserClient>();
public Vector<UserClient> challegePendingList = new Vector<UserClient>();
//通道管理器
private Selector selector;
UserDAO uDao = new UserDAO();
/**
* 获得一个ServerSocket通道,并对该通道做一些初始化的工作
* @param port 绑定的端口号
* @throws IOException
*/
public void initServer(int port) throws IOException {
// 获得一个ServerSocket通道
ServerSocketChannel serverChannel = ServerSocketChannel.open();
// 设置通道为非阻塞
serverChannel.configureBlocking(false);
// 将该通道对应的ServerSocket绑定到port端口
serverChannel.socket().bind(new InetSocketAddress(port));
// 获得一个通道管理器
this.selector = Selector.open();
//将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_ACCEPT事件,注册该事件后,
//当该事件到达时,selector.select()会返回,如果该事件没到达selector.select()会一直阻塞。
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
}
public static void startUp() {
NIOServer server = new NIOServer();
try {
server.initServer(PORT);
server.listen();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 采用轮询的方式监听selector上是否有需要处理的事件,如果有,则进行处理
* @throws IOException
*/
@SuppressWarnings("unchecked")
public void listen() throws IOException {
System.out.println("服务端启动成功!");
// 轮询访问selector
while (true) {
//当注册的事件到达时,方法返回;否则,该方法会一直阻塞
selector.select();
// 获得selector中选中的项的迭代器,选中的项为注册的事件
Iterator ite = this.selector.selectedKeys().iterator();
while (ite.hasNext()) {
SelectionKey key = (SelectionKey) ite.next();
// 删除已选的key,以防重复处理
ite.remove();
// 客户端请求连接事件
if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key
.channel();
// 获得和客户端连接的通道
SocketChannel channel = server.accept();
// 设置成非阻塞
channel.configureBlocking(false);
UserClient uClient = new UserClient(channel, this);
//在和客户端连接成功之后,为了可以接收到客户端的信息,需要给通道设置读的权限。
channel.register(this.selector, SelectionKey.OP_READ, uClient);
} else if (key.isReadable()) {
read(key);
}
}
}
}
public void addIdleMemb(UserClient uClient) {
idleUserList.add(uClient);
}
private int getOnlineMembCnt() {
int oneVMembCount = 0;
for(Room room : oneVRoomList) {
oneVMembCount += room.getMembCount();
}
int twoVMembCount = 0;
for(Room room : twoVRoomList) {
twoVMembCount += room.getMembCount();
}
int threeVMembCount = 0;
for(Room room : threeVRoomList) {
threeVMembCount += room.getMembCount();
}
int idleCount = 0;
for (UserClient userClient : idleUserList) {
if (userClient.state == UserClient.STATE_IN_HALL) {
if (userClient.getReqRoomSize() == 2) {
oneVMembCount++;
} else if (userClient.getReqRoomSize() == 4) {
twoVMembCount++;
} else if (userClient.getReqRoomSize() == 6) {
threeVMembCount++;
}
} else if (userClient.state == UserClient.STATE_IN_HOME) {
idleCount++;
}
}
//总在线人数
int totalCount = idleCount + oneVMembCount + twoVMembCount + threeVMembCount;
return totalCount;
}
private JSONObject getHomeJsonInfo() {
JSONObject json = new JSONObject();
int oneVMembCount = 0;
for(Room room : oneVRoomList) {
oneVMembCount += room.getMembCount();
}
int twoVMembCount = 0;
for(Room room : twoVRoomList) {
twoVMembCount += room.getMembCount();
}
int threeVMembCount = 0;
for(Room room : threeVRoomList) {
threeVMembCount += room.getMembCount();
}
int idleCount = 0;
for (UserClient userClient : idleUserList) {
if (userClient.state == UserClient.STATE_IN_HALL) {
if (userClient.getReqRoomSize() == 2) {
oneVMembCount++;
} else if (userClient.getReqRoomSize() == 4) {
twoVMembCount++;
} else if (userClient.getReqRoomSize() == 6) {
threeVMembCount++;
}
} else if (userClient.state == UserClient.STATE_IN_HOME) {
idleCount++;
}
}
if (oneVMembCount == 0) {
Random r = new Random();
oneVMembCount = r.nextInt(5);
}
json.put("oneVMembCount", oneVMembCount);
json.put("twoVMembCount", twoVMembCount);
json.put("threeVMembCount", threeVMembCount);
//总在线人数
int totalCount = idleCount + oneVMembCount + twoVMembCount + threeVMembCount;
// Random r = new Random();
// totalCount = r.nextInt(10000);
json.put("totalCount", totalCount);
return json;
}
/**
* 处理读取客户端发来的信息 的事件
* @param key
* @throws IOException
*/
public void read(SelectionKey key) {
// 服务器可读取消息:得到事件发生的Socket通道
UserClient uClient = (UserClient) key.attachment();
boolean isSuccess = uClient.onMessage();
if (!isSuccess) {
//发送失败,连接异常
removeFromIdle(uClient.getUserId());
}
}
@Override
public void process(String msg, UserClient userClient) {
try {
JSONObject json = JSON.parseObject(msg);
String cmd = json.getString("cmd");
if (Cmd.JOIN.equals(cmd)) {
//加入房间
json = json.getJSONObject("data");
String type = json.getString("type");
userClient.populateFromJson(json);
Room room = null;
if ("new".equals(type)) {
room = createNewRoom(userClient);
userClient.setFromHome(false);
} else if ("fast".equals(type)) {
room = fastJoin(userClient);
if (json.containsKey("isFromHome")) {
userClient.setFromHome(json.getBooleanValue("isFromHome"));
} else {
userClient.setFromHome(false);
}
} else if (Cmd.ENTERHALL.equals(cmd)) {
json = json.getJSONObject("data");
userClient.populateFromJson(json);
userClient.state = UserClient.STATE_IN_HALL;
notifyHomeInfo();
Cmd enter = new Cmd(Cmd.ENTERHALL);
JSONObject msgData = new JSONObject();
msgData.put("userid", userClient.getUserId());
msgData.put("username", userClient.userInfo.getUsername());
msgData.put("nickname", userClient.userInfo.getNickname());
msgData.put("msg", userClient.userInfo.getNickname() + "刚刚走进了" + getHallName(userClient.getReqRoomSize()) + "房间");
enter.data = msgData;
sendToIdle(enter);
} else if (Cmd.QUIT.equals(cmd)) {
//退出房间大厅,回到主界面
userClient.state = UserClient.STATE_IN_HOME;
notifyHomeInfo();
} else if (Cmd.UNPRESENCE.equals(cmd)) {
//退出登录, 断开连接
System.out.println("===退出登录===" + userClient.getUserId());
idleUserList.remove(userClient);
allUserList.remove(userClient);
//从挑战者列表中清除
for (int i=0; i < challegePendingList.size(); i++) {
if (challegePendingList.get(i).getUserId() == userClient.getUserId()) {
challegePendingList.remove(i);
i--;
}
}
uDao.setStatus(STATUS_OFFLINE, userClient.getUserId());
System.gc();
notifyHomeInfo();
} else if (Cmd.ROOMLIST.equals(cmd)) {
//客户端主动获取房间列表
sendRoomList(userClient);
} else if (Cmd.HOME_INFO.equals(cmd)) {
//客户端主动获取主页数据
sendHomeInfo(userClient);
} else if (Cmd.PRESENCE.equals(cmd)) {
Cmd alert = new Cmd(Cmd.ALERT);
JSONObject data = new JSONObject();
json = json.getJSONObject("data");
userClient.populateFromJson(json);
***********
alert.data = data;
userClient.sendCmd(alert);
notifyHomeInfo();
//给不在多人对战房间的人发送消息
sendToIdle(msg);
}
} catch (JSONException ex) {
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void sendToIdle(String msg) throws IOException {
for (UserClient idleUser : idleUserList) {
idleUser.sendJsonMsg(msg);
}
}
private void sendToIdle(Cmd msg) throws IOException {
for (UserClient idleUser : idleUserList) {
idleUser.sendCmd(msg);
}
}
/**
* 删除无效链接对象
*/
private void checkInvalidUserClient(int userId) {
removeFromIdle(userId);
for (Room room : oneVRoomList) {
room.checkInvalidMember(userId);
}
for (Room room : twoVRoomList) {
room.checkInvalidMember(userId);
}
for (Room room : threeVRoomList) {
room.checkInvalidMember(userId);
}
}
/**
* 给处在主页面的人发送人数变动信息
*/
private void notifyHomeInfo() {
for (UserClient uClient : idleUserList) {
if (uClient.state == UserClient.STATE_IN_HOME) {
sendHomeInfo(uClient);
}
}
}
/**
* 房间列表变化
* @param room
*/
public void refreshRoom(Room room) {
Cmd cmd = new Cmd(Cmd.REFRESH_ROOM);
cmd.data = room.toJsonSummary();
for (UserClient uClient : idleUserList) {
if (uClient.state == UserClient.STATE_IN_HALL && uClient.getReqRoomSize() == room.capicity) {
uClient.sendCmd(cmd);
}
}
notifyHomeInfo();
}
/*
* 创建新房间
*/
public Room createNewRoom(UserClient uClient) {
List<Room> roomList = getMatchRoomList(uClient.getReqRoomSize());
boolean find = false;
Room rRoom = null;
//查找是否有空房间可以使用
for (Room room : roomList) {
if (room.state == State.EMPTY) {
rRoom = room;
room.addMember(uClient);
find = true;
break;
}
}
//无空房间,重新创建
if (!find) {
Room room = new Room(uClient);
roomList.add(room);
rRoom = room;
}
return rRoom;
}
/**
* 用户加入房间
* @param uClient
* @param roomId : 房间id
*/
public Room joinRoom(UserClient uClient, int roomId) {
int capicity = uClient.getReqRoomSize();
List<Room> roomList = getMatchRoomList(capicity);
int size = roomList.size();
Room room = null;
for (int i = size - 1; i >= 0; i--) {
room = roomList.get(i);
if (room.id == roomId) {
room.addMember(uClient);
break;
}
}
return room;
}
}
3. android 客户端连接ServerConn
package com.seya.onlineanswer.logic;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Timer;
import java.util.TimerTask;
import org.json.JSONException;
import org.json.JSONObject;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import com.seya.onlineanswer.ui.Cmd;
import com.seya.onlineanswer.ui.StageActivity;
import com.seya.onlineanswer.util.GlobalVar;
import com.seya.onlineanswer.util.LogX;
import com.seya.onlineanswer.util.PreferencesUtil;
/**
* Server connection thread
* @author Administrator
*
*/
public class ServerConn implements Runnable {
public static final int PING_DELAY = 2*1000; //2秒ping一次
Timer timer;
private BufferedReader in = null;
private PrintWriter out = null;
private Handler mHandler = null;
public ServerConn(Socket server, Handler handler) throws IOException {
/* obtain an input stream from the server */
in = new BufferedReader(new InputStreamReader(
server.getInputStream()));
out = new PrintWriter(server.getOutputStream(), true);
mHandler = handler;
}
public void setHandler (Handler handler) {
mHandler = handler;
}
private void sendMsg(String msg) {
new AsyncTask<String, Object, Boolean>() {
@Override
protected Boolean doInBackground(String... params) {
//防止消息连在一起发送
synchronized (out) {
out.println(params[0]);
out.flush();
}
return null;
}
}.execute(msg);
}
/**
* 客户端Ping服务器,测试连接
*/
public void ping() {
timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
sendMsg("");
}
};
timer.schedule(timerTask, 0, PING_DELAY);
}
public void cancelPing() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
public void sendUnPresenceMsg(String msg) {
new AsyncTask<String, Object, Boolean>() {
@Override
protected Boolean doInBackground(String... params) {
out.println(params[0]);
return null;
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
mHandler.sendEmptyMessage(StageActivity.MSG_SHUTDOWN_CONN);
}
}.execute(msg);
}
public void run() {
String msg = null;
try {
/**
* loop message from server and process
*/
while ((msg = in.readLine()) != null) {
LogX.print("服务器返回=="+msg);
Message uiMsg = mHandler.obtainMessage(StageActivity.MSG_SERVER_PUSH);
uiMsg.obj = msg;
uiMsg.sendToTarget();
}
} catch (IOException e) {
System.err.println(e);
}
}
public void quit() {
JSONObject quit = new JSONObject();
try {
quit.put("cmd", Cmd.QUIT);
JSONObject data = new JSONObject();
data.put("userid", GlobalVar.userId);
quit.put("data", data);
sendMsg(quit.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
//下线
public void unPresence() {
JSONObject quit = new JSONObject();
try {
LogX.print("===unPresence===");
quit.put("cmd", Cmd.UNPRESENCE);
JSONObject data = new JSONObject();
data.put("userid", GlobalVar.userId);
quit.put("data", data);
sendUnPresenceMsg(quit.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* 进入房间
* @param roomSize
*/
public void join(int roomSize, String type, int roomId, boolean isFromHome, int challegeUid) {
JSONObject join = new JSONObject();
try {
join.put("cmd", Cmd.JOIN);
//进入房间, 再次验证
JSONObject data = new JSONObject();
data.put("userid", GlobalVar.userId);
data.put("roomsize", roomSize);
data.put("type", type);
data.put("roomid", roomId);
data.put("isFromHome", isFromHome);
data.put("chaUid", challegeUid);
join.put("data", data);
LogX.print("發送登錄: "+join.toString());
sendMsg(join.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* 发送就绪命令
*/
public void ready() {
JSONObject ready = new JSONObject();
try {
ready.put("cmd", Cmd.READY);
//进入房间, 再次验证
JSONObject data = new JSONObject();
data.put("userid", GlobalVar.userId);
ready.put("data", data);
LogX.print("發送就绪: "+ready.toString());
sendMsg(ready.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
}
欢迎了解学习交流
豌豆荚地址: http://apps.wandoujia.com/search?key=%E5%85%A8%E6%B0%91%E7%AD%94%E9%A2%98&source=index
豌豆荚地址: http://apps.wandoujia.com/search?key=%E5%85%A8%E6%B0%91%E7%AD%94%E9%A2%98&source=index
本文概要介绍如何通过java nio来开发android客户端与服务器socket通信的过程。
1. 为什么要用java NIO
常规的socket通信为阻塞方式,服务器接收到消息并进行处理,处理完一个才能处理下一个。 如果要同时处理,就得自己开线程,为每一个客户端连接做一个线程,这样当连接数大的情况下,上万以上,服务器就难以承受了。 JAVA NIO是jdk1.4提供的API, 主要原理是以监听机制来处理客户端的连接。主要包含buffer和channel.
2. 服务器示例代码
package com.seya.onlineserver.socket.nio;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Vector;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.seya.onlineserver.jpush.JPushManager;
import com.seya.onlineserver.socket.dao.UserDAO;
import com.seya.onlineserver.socket.nio.Room.State;
/**
* NIO服务端
* @author Seyason
*/
public class NIOServer implements MsgProcessor{
//用户在线标示
public static final int STATUS_ONLINE = 1;
public static final int STATUS_OFFLINE = 0;
private static final int PORT = 2121;
//全部用户集合
private Vector<UserClient> allUserList = new Vector<UserClient>();
//房间数
private Vector<Room> oneVRoomList = new Vector<Room>();
private Vector<Room> twoVRoomList = new Vector<Room>();
private Vector<Room> threeVRoomList = new Vector<Room>();
public static Vector<UserClient> idleUserList = new Vector<UserClient>();
public Vector<UserClient> challegePendingList = new Vector<UserClient>();
//通道管理器
private Selector selector;
UserDAO uDao = new UserDAO();
/**
* 获得一个ServerSocket通道,并对该通道做一些初始化的工作
* @param port 绑定的端口号
* @throws IOException
*/
public void initServer(int port) throws IOException {
// 获得一个ServerSocket通道
ServerSocketChannel serverChannel = ServerSocketChannel.open();
// 设置通道为非阻塞
serverChannel.configureBlocking(false);
// 将该通道对应的ServerSocket绑定到port端口
serverChannel.socket().bind(new InetSocketAddress(port));
// 获得一个通道管理器
this.selector = Selector.open();
//将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_ACCEPT事件,注册该事件后,
//当该事件到达时,selector.select()会返回,如果该事件没到达selector.select()会一直阻塞。
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
}
public static void startUp() {
NIOServer server = new NIOServer();
try {
server.initServer(PORT);
server.listen();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 采用轮询的方式监听selector上是否有需要处理的事件,如果有,则进行处理
* @throws IOException
*/
@SuppressWarnings("unchecked")
public void listen() throws IOException {
System.out.println("服务端启动成功!");
// 轮询访问selector
while (true) {
//当注册的事件到达时,方法返回;否则,该方法会一直阻塞
selector.select();
// 获得selector中选中的项的迭代器,选中的项为注册的事件
Iterator ite = this.selector.selectedKeys().iterator();
while (ite.hasNext()) {
SelectionKey key = (SelectionKey) ite.next();
// 删除已选的key,以防重复处理
ite.remove();
// 客户端请求连接事件
if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key
.channel();
// 获得和客户端连接的通道
SocketChannel channel = server.accept();
// 设置成非阻塞
channel.configureBlocking(false);
UserClient uClient = new UserClient(channel, this);
//在和客户端连接成功之后,为了可以接收到客户端的信息,需要给通道设置读的权限。
channel.register(this.selector, SelectionKey.OP_READ, uClient);
} else if (key.isReadable()) {
read(key);
}
}
}
}
public void addIdleMemb(UserClient uClient) {
idleUserList.add(uClient);
}
private int getOnlineMembCnt() {
int oneVMembCount = 0;
for(Room room : oneVRoomList) {
oneVMembCount += room.getMembCount();
}
int twoVMembCount = 0;
for(Room room : twoVRoomList) {
twoVMembCount += room.getMembCount();
}
int threeVMembCount = 0;
for(Room room : threeVRoomList) {
threeVMembCount += room.getMembCount();
}
int idleCount = 0;
for (UserClient userClient : idleUserList) {
if (userClient.state == UserClient.STATE_IN_HALL) {
if (userClient.getReqRoomSize() == 2) {
oneVMembCount++;
} else if (userClient.getReqRoomSize() == 4) {
twoVMembCount++;
} else if (userClient.getReqRoomSize() == 6) {
threeVMembCount++;
}
} else if (userClient.state == UserClient.STATE_IN_HOME) {
idleCount++;
}
}
//总在线人数
int totalCount = idleCount + oneVMembCount + twoVMembCount + threeVMembCount;
return totalCount;
}
private JSONObject getHomeJsonInfo() {
JSONObject json = new JSONObject();
int oneVMembCount = 0;
for(Room room : oneVRoomList) {
oneVMembCount += room.getMembCount();
}
int twoVMembCount = 0;
for(Room room : twoVRoomList) {
twoVMembCount += room.getMembCount();
}
int threeVMembCount = 0;
for(Room room : threeVRoomList) {
threeVMembCount += room.getMembCount();
}
int idleCount = 0;
for (UserClient userClient : idleUserList) {
if (userClient.state == UserClient.STATE_IN_HALL) {
if (userClient.getReqRoomSize() == 2) {
oneVMembCount++;
} else if (userClient.getReqRoomSize() == 4) {
twoVMembCount++;
} else if (userClient.getReqRoomSize() == 6) {
threeVMembCount++;
}
} else if (userClient.state == UserClient.STATE_IN_HOME) {
idleCount++;
}
}
if (oneVMembCount == 0) {
Random r = new Random();
oneVMembCount = r.nextInt(5);
}
json.put("oneVMembCount", oneVMembCount);
json.put("twoVMembCount", twoVMembCount);
json.put("threeVMembCount", threeVMembCount);
//总在线人数
int totalCount = idleCount + oneVMembCount + twoVMembCount + threeVMembCount;
// Random r = new Random();
// totalCount = r.nextInt(10000);
json.put("totalCount", totalCount);
return json;
}
/**
* 处理读取客户端发来的信息 的事件
* @param key
* @throws IOException
*/
public void read(SelectionKey key) {
// 服务器可读取消息:得到事件发生的Socket通道
UserClient uClient = (UserClient) key.attachment();
boolean isSuccess = uClient.onMessage();
if (!isSuccess) {
//发送失败,连接异常
removeFromIdle(uClient.getUserId());
}
}
@Override
public void process(String msg, UserClient userClient) {
try {
JSONObject json = JSON.parseObject(msg);
String cmd = json.getString("cmd");
if (Cmd.JOIN.equals(cmd)) {
//加入房间
json = json.getJSONObject("data");
String type = json.getString("type");
userClient.populateFromJson(json);
Room room = null;
if ("new".equals(type)) {
room = createNewRoom(userClient);
userClient.setFromHome(false);
} else if ("fast".equals(type)) {
room = fastJoin(userClient);
if (json.containsKey("isFromHome")) {
userClient.setFromHome(json.getBooleanValue("isFromHome"));
} else {
userClient.setFromHome(false);
}
} else if (Cmd.ENTERHALL.equals(cmd)) {
json = json.getJSONObject("data");
userClient.populateFromJson(json);
userClient.state = UserClient.STATE_IN_HALL;
notifyHomeInfo();
Cmd enter = new Cmd(Cmd.ENTERHALL);
JSONObject msgData = new JSONObject();
msgData.put("userid", userClient.getUserId());
msgData.put("username", userClient.userInfo.getUsername());
msgData.put("nickname", userClient.userInfo.getNickname());
msgData.put("msg", userClient.userInfo.getNickname() + "刚刚走进了" + getHallName(userClient.getReqRoomSize()) + "房间");
enter.data = msgData;
sendToIdle(enter);
} else if (Cmd.QUIT.equals(cmd)) {
//退出房间大厅,回到主界面
userClient.state = UserClient.STATE_IN_HOME;
notifyHomeInfo();
} else if (Cmd.UNPRESENCE.equals(cmd)) {
//退出登录, 断开连接
System.out.println("===退出登录===" + userClient.getUserId());
idleUserList.remove(userClient);
allUserList.remove(userClient);
//从挑战者列表中清除
for (int i=0; i < challegePendingList.size(); i++) {
if (challegePendingList.get(i).getUserId() == userClient.getUserId()) {
challegePendingList.remove(i);
i--;
}
}
uDao.setStatus(STATUS_OFFLINE, userClient.getUserId());
System.gc();
notifyHomeInfo();
} else if (Cmd.ROOMLIST.equals(cmd)) {
//客户端主动获取房间列表
sendRoomList(userClient);
} else if (Cmd.HOME_INFO.equals(cmd)) {
//客户端主动获取主页数据
sendHomeInfo(userClient);
} else if (Cmd.PRESENCE.equals(cmd)) {
Cmd alert = new Cmd(Cmd.ALERT);
JSONObject data = new JSONObject();
json = json.getJSONObject("data");
userClient.populateFromJson(json);
***********
alert.data = data;
userClient.sendCmd(alert);
notifyHomeInfo();
//给不在多人对战房间的人发送消息
sendToIdle(msg);
}
} catch (JSONException ex) {
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void sendToIdle(String msg) throws IOException {
for (UserClient idleUser : idleUserList) {
idleUser.sendJsonMsg(msg);
}
}
private void sendToIdle(Cmd msg) throws IOException {
for (UserClient idleUser : idleUserList) {
idleUser.sendCmd(msg);
}
}
/**
* 删除无效链接对象
*/
private void checkInvalidUserClient(int userId) {
removeFromIdle(userId);
for (Room room : oneVRoomList) {
room.checkInvalidMember(userId);
}
for (Room room : twoVRoomList) {
room.checkInvalidMember(userId);
}
for (Room room : threeVRoomList) {
room.checkInvalidMember(userId);
}
}
/**
* 给处在主页面的人发送人数变动信息
*/
private void notifyHomeInfo() {
for (UserClient uClient : idleUserList) {
if (uClient.state == UserClient.STATE_IN_HOME) {
sendHomeInfo(uClient);
}
}
}
/**
* 房间列表变化
* @param room
*/
public void refreshRoom(Room room) {
Cmd cmd = new Cmd(Cmd.REFRESH_ROOM);
cmd.data = room.toJsonSummary();
for (UserClient uClient : idleUserList) {
if (uClient.state == UserClient.STATE_IN_HALL && uClient.getReqRoomSize() == room.capicity) {
uClient.sendCmd(cmd);
}
}
notifyHomeInfo();
}
/*
* 创建新房间
*/
public Room createNewRoom(UserClient uClient) {
List<Room> roomList = getMatchRoomList(uClient.getReqRoomSize());
boolean find = false;
Room rRoom = null;
//查找是否有空房间可以使用
for (Room room : roomList) {
if (room.state == State.EMPTY) {
rRoom = room;
room.addMember(uClient);
find = true;
break;
}
}
//无空房间,重新创建
if (!find) {
Room room = new Room(uClient);
roomList.add(room);
rRoom = room;
}
return rRoom;
}
/**
* 用户加入房间
* @param uClient
* @param roomId : 房间id
*/
public Room joinRoom(UserClient uClient, int roomId) {
int capicity = uClient.getReqRoomSize();
List<Room> roomList = getMatchRoomList(capicity);
int size = roomList.size();
Room room = null;
for (int i = size - 1; i >= 0; i--) {
room = roomList.get(i);
if (room.id == roomId) {
room.addMember(uClient);
break;
}
}
return room;
}
}
3. android 客户端连接ServerConn
package com.seya.onlineanswer.logic;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Timer;
import java.util.TimerTask;
import org.json.JSONException;
import org.json.JSONObject;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import com.seya.onlineanswer.ui.Cmd;
import com.seya.onlineanswer.ui.StageActivity;
import com.seya.onlineanswer.util.GlobalVar;
import com.seya.onlineanswer.util.LogX;
import com.seya.onlineanswer.util.PreferencesUtil;
/**
* Server connection thread
* @author Administrator
*
*/
public class ServerConn implements Runnable {
public static final int PING_DELAY = 2*1000; //2秒ping一次
Timer timer;
private BufferedReader in = null;
private PrintWriter out = null;
private Handler mHandler = null;
public ServerConn(Socket server, Handler handler) throws IOException {
/* obtain an input stream from the server */
in = new BufferedReader(new InputStreamReader(
server.getInputStream()));
out = new PrintWriter(server.getOutputStream(), true);
mHandler = handler;
}
public void setHandler (Handler handler) {
mHandler = handler;
}
private void sendMsg(String msg) {
new AsyncTask<String, Object, Boolean>() {
@Override
protected Boolean doInBackground(String... params) {
//防止消息连在一起发送
synchronized (out) {
out.println(params[0]);
out.flush();
}
return null;
}
}.execute(msg);
}
/**
* 客户端Ping服务器,测试连接
*/
public void ping() {
timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
sendMsg("");
}
};
timer.schedule(timerTask, 0, PING_DELAY);
}
public void cancelPing() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
public void sendUnPresenceMsg(String msg) {
new AsyncTask<String, Object, Boolean>() {
@Override
protected Boolean doInBackground(String... params) {
out.println(params[0]);
return null;
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
mHandler.sendEmptyMessage(StageActivity.MSG_SHUTDOWN_CONN);
}
}.execute(msg);
}
public void run() {
String msg = null;
try {
/**
* loop message from server and process
*/
while ((msg = in.readLine()) != null) {
LogX.print("服务器返回=="+msg);
Message uiMsg = mHandler.obtainMessage(StageActivity.MSG_SERVER_PUSH);
uiMsg.obj = msg;
uiMsg.sendToTarget();
}
} catch (IOException e) {
System.err.println(e);
}
}
public void quit() {
JSONObject quit = new JSONObject();
try {
quit.put("cmd", Cmd.QUIT);
JSONObject data = new JSONObject();
data.put("userid", GlobalVar.userId);
quit.put("data", data);
sendMsg(quit.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
//下线
public void unPresence() {
JSONObject quit = new JSONObject();
try {
LogX.print("===unPresence===");
quit.put("cmd", Cmd.UNPRESENCE);
JSONObject data = new JSONObject();
data.put("userid", GlobalVar.userId);
quit.put("data", data);
sendUnPresenceMsg(quit.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* 进入房间
* @param roomSize
*/
public void join(int roomSize, String type, int roomId, boolean isFromHome, int challegeUid) {
JSONObject join = new JSONObject();
try {
join.put("cmd", Cmd.JOIN);
//进入房间, 再次验证
JSONObject data = new JSONObject();
data.put("userid", GlobalVar.userId);
data.put("roomsize", roomSize);
data.put("type", type);
data.put("roomid", roomId);
data.put("isFromHome", isFromHome);
data.put("chaUid", challegeUid);
join.put("data", data);
LogX.print("發送登錄: "+join.toString());
sendMsg(join.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* 发送就绪命令
*/
public void ready() {
JSONObject ready = new JSONObject();
try {
ready.put("cmd", Cmd.READY);
//进入房间, 再次验证
JSONObject data = new JSONObject();
data.put("userid", GlobalVar.userId);
ready.put("data", data);
LogX.print("發送就绪: "+ready.toString());
sendMsg(ready.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
}
欢迎了解学习交流
豌豆荚地址: http://apps.wandoujia.com/search?key=%E5%85%A8%E6%B0%91%E7%AD%94%E9%A2%98&source=index
发表评论
-
enable android deviceconnection under linux
2013-04-24 15:45 1001开发环境搭建完毕,Eclipse,Java,ADT都已经折腾 ... -
set CCache for building android source code
2013-04-24 15:14 1190Setting up ccache You can opti ... -
android 源码下载403 forbidden, 406 not acceptable 错误
2013-04-24 08:46 2453解决方法 1. 浏览器登录https://android.g ... -
ubuntu11.10 编译android4.0 错处
2013-04-08 21:45 1225今天使用ubuntu11.10编译android4.0出现以下 ... -
常用WebService列表
2013-01-31 23:22 2638快递查询接口 http://webservice.36wu.c ... -
startActivityForResult 无响应问题
2013-01-24 13:57 3851今天开发遇到了个问题, 就是从一个Activity中使用sta ... -
Android中仿新浪微博刷新列表
2012-11-22 17:35 7344大家看到新浪微博中的列表往下拉的时候, 头部出现正在刷新,然后 ... -
Grid调整间距
2012-09-29 08:52 1746今天使用GridView, 发现点中某一Item时选中部分的背 ... -
android gallery和Animation组合使用, 看美女美图
2012-09-11 21:01 4447今天主要探究Gallery和Animation的使用。 制作一 ... -
Android执行 shell command
2012-03-24 17:00 7254Android执行shell命令 一、方法 1. /* ... -
BBBBBB111
2012-03-23 11:42 10陈波: 本周:代码review,解决findbugs中bug以 ... -
MonkeyTestError
2012-03-21 10:15 903-20 21:36:42.439 W/dalvikvm( ... -
INSTALL_FAILED_OLDER_SDK ERROR
2012-03-12 15:52 4467Install APK with adb: $ platfo ... -
4.0源码编译问题
2012-03-07 17:12 31561、fatal error: GL/glx.h: No suc ... -
4.0 编译apk中无classes.dex
2012-03-07 17:11 3961下载完android 4.0代码,模拟器里面的gallery不 ... -
Android 4.0源码编译错误
2012-03-05 10:19 2580UNEXPECTED TOP-LEVEL EXCEPTION: ... -
AndroidLockScreenDemo
2012-02-18 15:54 991锁屏解锁的成功案例。 -
G14 root权限获取
2012-02-13 23:36 2868HTC G14 ROOT权限获取后就能删除系统自带的程序,相信 ... -
锁屏d ds
2011-12-15 00:49 903private final IDevicePolicyMana ... -
HuHug
2011-11-14 00:30 955gfjijgsdklgkg
相关推荐
Java作为一门广泛使用的编程语言,其经典问答涵盖了众多领域,包括基础语法、面向对象特性、集合框架、多线程、异常处理、IO流、网络编程、反射机制、JVM优化、设计模式等。这份"Java经典问答"资料,无疑是准备面试...
在IT行业中,构建一个基于Java的在线考试系统是一项常见的任务,尤其当涉及到网络通信和数据交换时,Socket编程成为不可或缺的技术。本项目“java基于socket手写协议的在线考试系统”着重于使用Java语言实现自定义...
j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是一个用来操作Windows注册表的 Java 类库,你可以用来对注册表信息进行读写。 GIF...
j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是一个用来操作Windows注册表的 Java 类库,你可以用来对注册表信息进行读写。 GIF...
j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是一个用来操作Windows注册表的 Java 类库,你可以用来对注册表信息进行读写。 GIF...
j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是一个用来操作Windows注册表的 Java 类库,你可以用来对注册表信息进行读写。 GIF...
j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是一个用来操作Windows注册表的 Java 类库,你可以用来对注册表信息进行读写。 GIF...
j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是一个用来操作Windows注册表的 Java 类库,你可以用来对注册表信息进行读写。 GIF...
j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是一个用来操作Windows注册表的 Java 类库,你可以用来对注册表信息进行读写。 GIF...
j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是一个用来操作Windows注册表的 Java 类库,你可以用来对注册表信息进行读写。 GIF...
j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是一个用来操作Windows注册表的 Java 类库,你可以用来对注册表信息进行读写。 GIF...
j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是一个用来操作Windows注册表的 Java 类库,你可以用来对注册表信息进行读写。 GIF...
【标题】"答题系统V2.0.zip"是一款基于JAVA编程语言开发的答题应用程序,它提供了用户友好的界面和实用的功能。此系统的核心亮点在于它的计时和计分机制,使得在线测试或知识竞赛等活动更加公正且具有挑战性。然而,...
j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是一个用来操作Windows注册表的 Java 类库,你可以用来对注册表信息进行读写。 GIF...
j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是一个用来操作Windows注册表的 Java 类库,你可以用来对注册表信息进行读写。 GIF...
j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是一个用来操作Windows注册表的 Java 类库,你可以用来对注册表信息进行读写。 GIF...
Stackoverflow作为一个全球知名的程序员问答社区,汇集了各种技术问题和解决方案,尤其对于Java这样的主流编程语言,其讨论热度更是不言而喻。这些热门问题反映了Java开发中常见的痛点、难点以及开发者需要掌握的...
在本项目中,“2021山东大学软件学院JAVA高程课设-考试平台的设计”是一个基于Java技术的课程设计项目,旨在让学生掌握高级Java编程技能,并应用到实际的在线考试系统开发中。这个项目的核心目标是设计并实现一个...
本课程对应着系统架构1.0,即第一阶段,主要的目标在于实现一个完整的系统,可以学到的技术还是比较多的:Spring Boot2.X、Java基础、Java8、JUC、NIO、微服务、分布式、系统架构设计、SpringMVC、MySQL、Luc
Java Jeopardy是一款基于Java开发的开源问答游戏,灵感来源于美国的知名电视游戏节目"Jeopardy!"。这个游戏设计主要用于教育环境,特别是课堂互动,它允许教师或学生以一种有趣的方式学习和复习Java编程语言的知识点...