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

Android 使用Socket实现服务器与手机客户端的长连接七:定义消息体,区分是响应还是回复信息

2016-06-28 22:50 911 查看

一、分析:

1、示例图:



如上图可以知道服务器给客户端会发送两条信息,一个是回复,另一个是推送信息,如何区分这些信息呢?就必须定义消息体协议*

———————————————————————

有需求者请加qq:136137465,非诚勿扰

(java 架构师全套教程,共760G, 让你从零到架构师,每月轻松拿3万)

01.高级架构师四十二个阶段高

02.Java高级系统培训架构课程148课时

03.Java高级互联网架构师课程

04.Java互联网架构Netty、Nio、Mina等-视频教程

05.Java高级架构设计2016整理-视频教程

06.架构师基础、高级片

07.Java架构师必修linux运维系列课程

08.Java高级系统培训架构课程116课时

(送:hadoop系列教程,java设计模式与数据结构, Spring Cloud微服务, SpringBoot入门)

——————————————————————–

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

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android socket 服务器