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
原创粉丝点击