Android 使用Socket实现服务器与手机客户端的长连接七:定义消息体,区分是响应还是回复信息
来源:互联网 发布:如何在淘宝上找同款 编辑:程序博客网 时间:2024/05/21 08:47
一、分析:
1、示例图:
如上图可以知道服务器给客户端会发送两条信息,一个是回复,另一个是推送信息,如何区分这些信息呢?就必须定义消息体协议*
2、消息体协议:
1)请求部分:
{ "sequence": "9f4c696e-9ab5-46cf-959c-b1e2e35200d2", "type": "request", "action": "text"}
2)响应部分:
{ "sequence": "9f4c696e-9ab5-46cf-959c-b1e2e35200d2", "type": "response", "flag": "true"}
3)说明:
sequece : 标记 请求 和 响应,用来表明 响应 是 针对 哪次 请求的
type : 用来标记 是 请求 还是 响应
action : 请求发送方 的 发送类型,由具体请求 决定取值。
3、验证信息内容:
1)请求的 key-Value
key 类型 说明
type String 请求:request
sequence String 请求的序列号
action String 请求的行为:auth
sender String 发送者账号
token String 发送者token标志
2)请求的json 格式:
{ "sequence": "9f4c696e-9ab5-46cf-959c-b1e2e35200d2", "type": "request", "action": "auth", "sender":"xxxx", "token":"xxxx"}{"sequence":"1","type":"request","action":"auth","sender":"iphone1","token":"0dce6f76ac1a29d276c0c6dabe60519c"}
3)响应的格式:
成功 :
{ "sequence": "9f4c696e-9ab5-46cf-959c-b1e2e35200d2", "type": "response", "flag": "true",}
失败 :
{ "sequence": "9f4c696e-9ab5-46cf-959c-b1e2e35200d2", "type": "response", "flag": "false", "errorCode":"", "errorString":""}
二、封装数据
1、创建接口
public interface Request { String getData();}
2、创建认证信息
public class AuthRequest implements Request { private Map<String, String> map = new HashMap<String, String>(); public AuthRequest(String sender, String token) { map.put("type", "request"); map.put("sequence", UUID.randomUUID().toString()); map.put("action", "auth"); map.put("sender", sender); map.put("token", token); } @Override public String getData() { return new Gson().toJson(map); }}
3、创建消息实体
public class TextRequest implements Request { private Map<String, String> map = new HashMap<String, String>(); public TextRequest(String sender, String token, String receiver, String content) { map.put("type", "request"); map.put("sequence", UUID.randomUUID().toString()); map.put("action", "text"); map.put("sender", sender); map.put("token", token); map.put("receiver", receiver); map.put("content", content); } @Override public String getData() { return new Gson().toJson(map); }}
三、更改ConnectorManager
添加方法:
public void connect(AuthRequest auth) { connector = new Connector(); connector.setConnectorListener(this); connector.connect(); connector.auth(auth.getData()); } public void putRequest(Request request) { connector.putRequest(request.getData()); }
四、修改service
1、原来连接方法
/** * 连接服务 */ @Override public void onCreate() { super.onCreate(); new Thread(new Runnable() { @Override public void run() { mConnManager = ConnectorManager.getInstance(); mConnManager.setConnectorListener(ConnService.this); mConnManager.connect("#A"); } }).start(); }
2、发送的string类型更改为request类型
@Override public void onCreate() { super.onCreate(); mConnManager = ConnectorManager.getInstance(); new Thread(new Runnable() { @Override public void run() { mConnManager.setConnectorListener(ConnService.this); AuthRequest request = null; if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) { request = new AuthRequest("B", "BToken"); } else { request = new AuthRequest("A", "AToken"); } mConnManager.connect(request); } }).start(); }
五、修改主界面发送信息方法
/** * 发送信息 * @param view */ public void clickMessage(View view){ if (!TextUtils.isEmpty(mEtContent.getText())) { String sender = "A"; String token = "AToken"; String receiver = "B"; //mConnectorManager.putRequest(mEtContent.getText().toString()); Request request = new TextRequest(sender, token, receiver, mEtContent.getText().toString()); mConnectorManager.putRequest(request); } }
六、修改服务器
1、原来只接收字符串信息
public class Copy_2_of_TCPServer { public static void main(String[] args) { //final LinkedList<Socket> list = new LinkedList<Socket>(); final Map<String, Socket> map = new HashMap<String, Socket>(); int port = 10002; try { ServerSocket server = new ServerSocket(port); while (true) { // 获得客户端连接 // 阻塞式方法 System.out.println("准备阻塞..."); final Socket client = server.accept(); System.out.println("阻塞完成..."); // 添加到集合里 //list.add(client); new Thread(new Runnable() { @Override public void run() { try { // 输入流,为了获取客户端发送的数据 InputStream is = client.getInputStream(); // 得到输出流 OutputStream out = client.getOutputStream(); byte[] buffer = new byte[1024]; int len = -1; System.out.println("准备read..."); while ((len = is.read(buffer)) != -1) { String text = new String(buffer, 0, len); if (text.startsWith("#")) { map.put(text, client); // 回复认证信息 out.write("认证成功,over".getBytes()); }else { out.write("发送成功,over".getBytes()); String[] split = text.split(":");//发送信息时,用户名+“:” + content; String key = "#" + split[0];//split[0]表示用户名称 String content = split[1]; //发送信息给其它用户 Socket s = map.get(key); OutputStream outputStream = s.getOutputStream(); outputStream.write(content.getBytes()); } } } catch (Exception e) { e.printStackTrace(); } } }).start(); } } catch (Exception e) { e.printStackTrace(); } }}
2、修改后接收request信息
public class TCPServer { public static void main(String[] args) { final Map<String, Socket> clientMap = new HashMap<String, Socket>(); int port = 10002; try { ServerSocket server = new ServerSocket(port); while (true) { // 获得客户端连接 // 阻塞式方法 System.out.println("准备阻塞..."); final Socket client = server.accept(); new Thread(new Runnable() { @Override public void run() { try { // 输入流,为了获取客户端发送的数据 InputStream is = client.getInputStream(); // 得到输出流 OutputStream out = client.getOutputStream(); byte[] buffer = new byte[1024]; int len = -1; System.out.println("准备read..."); while ((len = is.read(buffer)) != -1) { String text = new String(buffer, 0, len); TypeToken typeToken = new TypeToken<Map<String, String>>(){}; Map<String, String> msgMap = new Gson().fromJson(text, typeToken.getType()); String type = msgMap.get("type"); if ("request".equals(type)) { String action = msgMap.get("action"); if ("auth".equals(action)) { // 认证消息处理 String sender = msgMap.get("sender"); System.out.println(sender + "认证"); // 放到容器当中 clientMap.put(sender, client); } else if ("text".equals(action)) { // 文本消息 String sender = msgMap.get("sender"); String receiver = msgMap.get("receiver"); String content = msgMap.get("content"); Socket s = clientMap.get(receiver); if (s != null) { // 在线 OutputStream output = s.getOutputStream(); output.write((sender + content).getBytes()); } else { // 离线 TODO: } } } } } catch (Exception e) { e.printStackTrace(); } } }).start(); } } catch (Exception e) { e.printStackTrace(); } }}
0 0
- Android 使用Socket实现服务器与手机客户端的长连接七:定义消息体,区分是响应还是回复信息
- Android 使用Socket实现服务器与手机客户端的长连接七:定义消息体,区分是响应还是回复信息
- Android 使用Socket实现服务器与手机客户端的长连接五:使用队列封装请求
- Android 使用Socket实现服务器与手机客户端的长连接一:一对一聊天
- Android 使用Socket实现服务器与手机客户端的长连接六:二次封装
- Android 使用Socket实现服务器与手机客户端的长连接八
- Android 使用Socket实现服务器与手机客户端的长连接四:使用回调函数与Service调用
- Android 使用Socket实现服务器与手机客户端的长连接二:多Client对一Server聊天
- Android 使用Socket实现服务器与手机客户端的长连接三:clientA 发送给clientB,定点发送
- 什么是socket?什么是socket的长、短连接?java如何简单实现socket客户端和服务器?
- 基于Java Socket的自定义协议,实现Android与服务器的长连接(一)
- 基于Java Socket的自定义协议,实现Android与服务器的长连接(二)
- 基于Java Socket的自定义协议,实现Android与服务器的长连接(二)
- 基于Java Socket的自定义协议,实现Android与服务器的长连接(一)
- android使用Mina实现与服务器长连接
- 多线程Socket编程实现服务器与客户端的连接
- 如何区分 使用的是手机还是平板?
- 如何区分 使用的是手机还是平板? 续
- 使用IntelliJ IDEA 14和Maven创建java web项目
- python 学习简记 《编程导论》 CH6&CH7
- Linux:-bash: ***: command not found
- 算术平均、几何平均、平方平均、调和平均
- Android 使用Socket实现服务器与手机客户端的长连接七:定义消息体,区分是响应还是回复信息
- Android 使用Socket实现服务器与手机客户端的长连接七:定义消息体,区分是响应还是回复信息
- Android基础--BroadcastReceiver应用详解
- Spring中bean用法详解
- Kafka Scala Producer API
- 提高项目12-数组大折腾
- DPDK研究之枚举类型
- 程序员面经:面试前到底该不该刷题以及面试前该如何准备
- 微信账号绑定
- linux编程-守护进程编写