一、分析:
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();
}
}
}