mirror of
https://gitee.com/wujiawei1207537021/wu-lazy-cloud-network.git
synced 2025-06-06 21:37:56 +08:00
[fix] add server send message to client
This commit is contained in:
parent
be9cf25233
commit
2ec8dad5ef
@ -0,0 +1,28 @@
|
||||
package wu.framework.lazy.cloud.heartbeat.client.netty.advanced;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import wu.framework.lazy.cloud.heartbeat.common.NettyProxyMsg;
|
||||
import wu.framework.lazy.cloud.heartbeat.common.advanced.client.AbstractDistributeSingleClientMessageTypeAdvanced;
|
||||
|
||||
/**
|
||||
* 接收服务端发送过来的聊天信息
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ClientDistributeSingleClientMessageTypeAdvanced extends AbstractDistributeSingleClientMessageTypeAdvanced<NettyProxyMsg> {
|
||||
/**
|
||||
* 处理当前数据
|
||||
*
|
||||
* @param channel 当前通道
|
||||
* @param nettyProxyMsg 通道数据
|
||||
*/
|
||||
@Override
|
||||
protected void doHandler(Channel channel, NettyProxyMsg nettyProxyMsg) {
|
||||
byte[] clientId = nettyProxyMsg.getClientId();
|
||||
byte[] data = nettyProxyMsg.getData();
|
||||
log.info("接收客户端:{},发送过来的聊天信息:{}",new String( clientId),new String( data ));
|
||||
|
||||
}
|
||||
}
|
@ -31,6 +31,14 @@ public class HeartbeatClientConfiguration {
|
||||
public ClientDistributeSingleClientRealAutoReadConnectTypeAdvanced clientDistributeSingleClientRealAutoReadConnectTypeAdvanced(){
|
||||
return new ClientDistributeSingleClientRealAutoReadConnectTypeAdvanced();
|
||||
}
|
||||
/**
|
||||
* 处理 接收服务端发送过来的聊天信息
|
||||
* @return ClientDistributeSingleClientMessageTypeAdvanced
|
||||
*/
|
||||
@Bean
|
||||
public ClientDistributeSingleClientMessageTypeAdvanced clientDistributeSingleClientMessageTypeAdvanced(){
|
||||
return new ClientDistributeSingleClientMessageTypeAdvanced();
|
||||
}
|
||||
@Bean
|
||||
public ClientDistributeSingleClientRealCloseVisitorTypeAdvanced clientDistributeSingleClientRealCloseVisitorTypeAdvanced(){
|
||||
return new ClientDistributeSingleClientRealCloseVisitorTypeAdvanced();
|
||||
|
@ -73,6 +73,13 @@ public class MessageType {
|
||||
*/
|
||||
public static final byte REPORT_SINGLE_CLIENT_CLOSE_VISITOR = 0X08;
|
||||
|
||||
/**
|
||||
* 上报 客户端消息到另一个客户端
|
||||
*
|
||||
* @see MessageTypeEnums#REPORT_SINGLE_CLIENT_MESSAGE
|
||||
* @see AbstractReportSingleClientMessage2OtherClientTypeAdvanced
|
||||
*/
|
||||
public static final byte REPORT_SINGLE_CLIENT_MESSAGE = 0X09;
|
||||
|
||||
/**
|
||||
* 下发 客户端接收连接成功通知
|
||||
@ -134,5 +141,11 @@ public class MessageType {
|
||||
*/
|
||||
public static final byte DISTRIBUTE_SINGLE_CLIENT_REAL_CLOSE_VISITOR = -0X08;
|
||||
|
||||
|
||||
/**
|
||||
* 下发 客户端消息
|
||||
*
|
||||
* @see MessageTypeEnums#DISTRIBUTE_SINGLE_CLIENT_MESSAGE
|
||||
* @see AbstractDistributeSingleClientMessageTypeAdvanced
|
||||
*/
|
||||
public static final byte DISTRIBUTE_SINGLE_CLIENT_MESSAGE = -0X09;
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
package wu.framework.lazy.cloud.heartbeat.common.advanced.client;
|
||||
|
||||
|
||||
import wu.framework.lazy.cloud.heartbeat.common.NettyProxyMsg;
|
||||
import wu.framework.lazy.cloud.heartbeat.common.advanced.AbstractChannelTypeAdvanced;
|
||||
import wu.framework.lazy.cloud.heartbeat.common.advanced.ChannelTypeAdvanced;
|
||||
import wu.framework.lazy.cloud.heartbeat.common.enums.MessageTypeEnums;
|
||||
|
||||
/**
|
||||
* 下发 客户端关闭代理服务通道
|
||||
*/
|
||||
|
||||
public abstract class AbstractDistributeSingleClientMessageTypeAdvanced<MSG> extends AbstractChannelTypeAdvanced<NettyProxyMsg> implements ChannelTypeAdvanced {
|
||||
|
||||
/**
|
||||
* 是否支持当前类型
|
||||
*
|
||||
* @param msg 通道数据
|
||||
* @return 布尔类型 是、否
|
||||
*/
|
||||
@Override
|
||||
public boolean doSupport(NettyProxyMsg msg) {
|
||||
return MessageTypeEnums.DISTRIBUTE_SINGLE_CLIENT_MESSAGE.getTypeByte() == msg.getType();
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package wu.framework.lazy.cloud.heartbeat.common.advanced.server;
|
||||
|
||||
|
||||
import wu.framework.lazy.cloud.heartbeat.common.NettyProxyMsg;
|
||||
import wu.framework.lazy.cloud.heartbeat.common.advanced.AbstractChannelTypeAdvanced;
|
||||
import wu.framework.lazy.cloud.heartbeat.common.advanced.ChannelTypeAdvanced;
|
||||
import wu.framework.lazy.cloud.heartbeat.common.enums.MessageTypeEnums;
|
||||
|
||||
|
||||
/**
|
||||
* 服务端处理客户端 关闭一个访客
|
||||
* REPORT_SINGLE_CLIENT_CLOSE_VISITOR
|
||||
*/
|
||||
public abstract class AbstractReportSingleClientMessage2OtherClientTypeAdvanced<MSG> extends AbstractChannelTypeAdvanced<NettyProxyMsg> implements ChannelTypeAdvanced {
|
||||
|
||||
|
||||
/**
|
||||
* 是否支持当前类型
|
||||
*
|
||||
* @param msg 通道数据
|
||||
* @return 布尔类型 是、否
|
||||
*/
|
||||
@Override
|
||||
public boolean doSupport(NettyProxyMsg msg) {
|
||||
return MessageTypeEnums.REPORT_SINGLE_CLIENT_MESSAGE.getTypeByte() == msg.getType();
|
||||
}
|
||||
}
|
@ -46,6 +46,10 @@ public enum MessageTypeEnums {
|
||||
* @see AbstractReportSingleClientCloseVisitorTypeAdvanced
|
||||
*/
|
||||
REPORT_SINGLE_CLIENT_CLOSE_VISITOR(MessageType.REPORT_SINGLE_CLIENT_CLOSE_VISITOR, "上报 客户端关闭一个访客通道"),
|
||||
/**
|
||||
* @see AbstractReportSingleClientMessage2OtherClientTypeAdvanced
|
||||
*/
|
||||
REPORT_SINGLE_CLIENT_MESSAGE(MessageType.REPORT_SINGLE_CLIENT_MESSAGE, "上报 客户端消息到另一个客户端"),
|
||||
/**
|
||||
* @see AbstractDistributeConnectSuccessNotificationTypeAdvanced
|
||||
*/
|
||||
@ -83,6 +87,10 @@ public enum MessageTypeEnums {
|
||||
* @see AbstractDistributeSingleClientRealCloseVisitorTypeAdvanced
|
||||
*/
|
||||
DISTRIBUTE_SINGLE_CLIENT_REAL_CLOSE_VISITOR(MessageType.DISTRIBUTE_SINGLE_CLIENT_REAL_CLOSE_VISITOR, "下发 客户端关闭代理服务通道"),
|
||||
/**
|
||||
* @see AbstractDistributeSingleClientMessageTypeAdvanced
|
||||
*/
|
||||
DISTRIBUTE_SINGLE_CLIENT_MESSAGE(MessageType.DISTRIBUTE_SINGLE_CLIENT_MESSAGE, "下发 客户端消息"),
|
||||
|
||||
;
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
spring:
|
||||
lazy:
|
||||
netty:
|
||||
# inet-host: 127.0.0.1
|
||||
# inet-port: 7001
|
||||
# inet-path: middleground-on-cloud-heartbeat-server
|
||||
inet-host: 124.222.48.62 # 服务端地址
|
||||
inet-port: 30676 #服务端端口
|
||||
inet-host: 127.0.0.1
|
||||
inet-port: 7001
|
||||
inet-path: middleground-on-cloud-heartbeat-server
|
||||
# inet-host: 124.222.48.62 # 服务端地址
|
||||
# inet-port: 30676 #服务端端口
|
||||
# inet-path: middleground-on-cloud-heartbeat-server
|
||||
client-id: local # 客户端ID
|
||||
data:
|
||||
redis:
|
||||
|
@ -104,4 +104,10 @@ public interface NettyClientStateApplication {
|
||||
|
||||
Result<NettyClientState> remove(NettyClientStateRemoveCommand nettyClientStateRemoveCommand);
|
||||
|
||||
/**
|
||||
* 通过客户端心跳通道发送客户端请求
|
||||
* @param nettyClientMessageCommand 发送请求到客户端
|
||||
* @return {@link Result<Void>}
|
||||
*/
|
||||
Result<Void> sendMessage2HeartbeatClient(NettyClientMessageCommand nettyClientMessageCommand);
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package wu.framework.lazy.cloud.heartbeat.server.application.command.netty.client.state;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import wu.framework.lazy.cloud.heartbeat.common.enums.NettyClientStatus;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* describe 发送请求到客户端
|
||||
*
|
||||
* @author Jia wei Wu
|
||||
* @date 2023/12/27 03:46 下午
|
||||
* @see com.wu.framework.inner.lazy.persistence.reverse.lazy.ddd.DefaultDDDLazyRemoveCommand
|
||||
**/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "netty_client_message_command", description = "客户端状态")
|
||||
public class NettyClientMessageCommand {
|
||||
|
||||
|
||||
/**
|
||||
* 客户端ID
|
||||
*/
|
||||
@Schema(description = "客户端ID", name = "clientId", example = "")
|
||||
private String clientId;
|
||||
|
||||
|
||||
/**
|
||||
* 发送的消息
|
||||
*/
|
||||
@Schema(description = "发送的消息", name = "message", example = "")
|
||||
private String message;
|
||||
|
||||
}
|
@ -2,7 +2,11 @@ package wu.framework.lazy.cloud.heartbeat.server.application.impl;
|
||||
|
||||
|
||||
|
||||
import com.wu.framework.response.ResultFactory;
|
||||
import io.netty.channel.Channel;
|
||||
import wu.framework.lazy.cloud.heartbeat.common.ChannelContext;
|
||||
import wu.framework.lazy.cloud.heartbeat.common.MessageType;
|
||||
import wu.framework.lazy.cloud.heartbeat.common.NettyProxyMsg;
|
||||
import wu.framework.lazy.cloud.heartbeat.server.application.NettyClientStateApplication;
|
||||
import wu.framework.lazy.cloud.heartbeat.server.application.assembler.NettyClientStateDTOAssembler;
|
||||
import wu.framework.lazy.cloud.heartbeat.server.application.command.netty.client.state.NettyClientStateStoryCommand;
|
||||
@ -15,6 +19,7 @@ import com.wu.framework.inner.lazy.database.expand.database.persistence.domain.L
|
||||
import com.wu.framework.response.Result;
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
/**
|
||||
@ -143,4 +148,28 @@ public class NettyClientStateApplicationImpl implements NettyClientStateApplicat
|
||||
return nettyClientStateRepository.remove(nettyClientState);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过客户端心跳通道发送客户端请求
|
||||
*
|
||||
* @param nettyClientMessageCommand 发送请求到客户端
|
||||
* @return {@link Result<Void>}
|
||||
*/
|
||||
@Override
|
||||
public Result<Void> sendMessage2HeartbeatClient(NettyClientMessageCommand nettyClientMessageCommand) {
|
||||
// 获取客户端ID
|
||||
String clientId = nettyClientMessageCommand.getClientId();
|
||||
String message = nettyClientMessageCommand.getMessage();
|
||||
ChannelContext.ClientChannel clientChannel = ChannelContext.get(clientId);
|
||||
if(clientChannel==null){
|
||||
return ResultFactory.errorOf("客户端:"+clientId+"不存在");
|
||||
}
|
||||
// 发送消息到客户端
|
||||
Channel channel = clientChannel.getChannel();
|
||||
NettyProxyMsg nettyProxyMsg = new NettyProxyMsg();
|
||||
nettyProxyMsg.setClientId("服务端");
|
||||
nettyProxyMsg.setData(message.getBytes(StandardCharsets.UTF_8));
|
||||
nettyProxyMsg.setType(MessageType.DISTRIBUTE_SINGLE_CLIENT_MESSAGE);
|
||||
channel.writeAndFlush(nettyProxyMsg);
|
||||
return ResultFactory.successOf();
|
||||
}
|
||||
}
|
@ -136,4 +136,19 @@ public class NettyClientStateProvider {
|
||||
public Result<NettyClientState> remove(@ModelAttribute NettyClientStateRemoveCommand nettyClientStateRemoveCommand){
|
||||
return nettyClientStateApplication.remove(nettyClientStateRemoveCommand);
|
||||
}
|
||||
|
||||
/**
|
||||
* describe 通过客户端心跳通道发送客户端请求
|
||||
* @param nettyClientMessageCommand 发送请求到客户端
|
||||
* @return {@link Result<NettyClientState>}
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2023/12/27 03:46 下午
|
||||
**/
|
||||
|
||||
@Operation(summary = "通过客户端心跳通道发送客户端请求")
|
||||
@PostMapping("/sendMessage2HeartbeatClient")
|
||||
public Result<Void> sendMessage2HeartbeatClient(@RequestBody NettyClientMessageCommand nettyClientMessageCommand){
|
||||
return nettyClientStateApplication.sendMessage2HeartbeatClient(nettyClientMessageCommand);
|
||||
}
|
||||
}
|
@ -11,6 +11,10 @@ module.exports = {
|
||||
url: "/netty/client/state/remove",
|
||||
type: "delete",
|
||||
},
|
||||
sendMessage2HeartbeatClient: {
|
||||
url: "/netty/client/state/sendMessage2HeartbeatClient",
|
||||
type: "post",
|
||||
},
|
||||
visitorPage: {
|
||||
url: "/netty/server/visitor/findPage",
|
||||
type: "get",
|
||||
|
@ -63,9 +63,24 @@
|
||||
>
|
||||
{{ buttons.del.name }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-permission="['sendMessage']"
|
||||
@click.prevent="handleArouse2SendMessage(row)"
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
{{ buttons.sendMessage.name }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ve-table>
|
||||
<!--发送消息到客户端-->
|
||||
<cloud-server-send-message2-clinet
|
||||
v-if="showDialog"
|
||||
:rowData="rowData"
|
||||
:showDialog="showDialog"
|
||||
@closeDialog="handelDialog($event)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@ -79,6 +94,7 @@ export default {
|
||||
add: { name: "添加" },
|
||||
edit: { name: "编辑" },
|
||||
del: { name: "删除" },
|
||||
sendMessage: { name: "发送消息" },
|
||||
export: { name: "导出用户" },
|
||||
},
|
||||
// type 0:目录 1:菜单 2:按钮
|
||||
@ -99,10 +115,15 @@ import {
|
||||
handleSizeChange,
|
||||
handleCurrentChange,
|
||||
} from "@/views/layoutpages/common";
|
||||
import CloudServerSendMessage2Clinet from "@/views/layoutpages/cloud_network/components/CloudServerSendMessage2Clinet.vue";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const queryForm = ref(null);
|
||||
const tableData = ref([]);
|
||||
|
||||
const rowData = ref(null);
|
||||
const showDialog = ref(false);
|
||||
|
||||
const params = reactive({
|
||||
clientId: "",
|
||||
size: 10,
|
||||
@ -111,6 +132,25 @@ const params = reactive({
|
||||
});
|
||||
const { clientId, size, current, total } = toRefs(params);
|
||||
|
||||
/**
|
||||
* @description: dialog事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handelDialog = (e) => {
|
||||
showDialog.value = e;
|
||||
getDataList();
|
||||
};
|
||||
/**
|
||||
* @description:添加or编辑事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const handleArouse2SendMessage = (row = null) => {
|
||||
showDialog.value = true;
|
||||
rowData.value = row;
|
||||
};
|
||||
|
||||
/**删除行数据
|
||||
* @description:
|
||||
* @param {*}
|
||||
|
@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:model-value="showDialog"
|
||||
@close="closeDialog()"
|
||||
>
|
||||
<!-- 表单 -->
|
||||
<el-form
|
||||
:model="form"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
label-width="80px"
|
||||
:inline="false"
|
||||
>
|
||||
<el-form-item label="客户端ID" prop="clientId">
|
||||
<el-input v-model="clientId" placeholder="" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="发送的消息" prop="describe">
|
||||
<el-input v-model="message" placeholder="" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template v-slot:footer>
|
||||
<span>
|
||||
<el-button @click="closeDialog()">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit()">发送</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
toRefs,
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
onMounted,
|
||||
} from "vue";
|
||||
const rules = {
|
||||
clientId: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入选择客户端",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
clientTargetIp: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入客户端目标IP",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
clientTargetPort: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入客户端目标端口",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
visitorPort: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择访客端口",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
};
|
||||
const props = defineProps({
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "添加",
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["closeDialog"]);
|
||||
const { title, rowData } = toRefs(props);
|
||||
const closeDialog = () => {
|
||||
emit("closeDialog", false);
|
||||
};
|
||||
const formRef = ref(null);
|
||||
|
||||
const form = reactive({
|
||||
message: "",
|
||||
clientId: "",
|
||||
});
|
||||
const { clientId, message } = toRefs(form);
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
rowData.value && (clientId.value = rowData.value.clientId);
|
||||
/**
|
||||
* @description:提交
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const onSubmit = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res = (res =
|
||||
await VE_API.cloudNetwork.sendMessage2HeartbeatClient(form));
|
||||
const { code } = res;
|
||||
if (code === 0) {
|
||||
closeDialog();
|
||||
}
|
||||
} else {
|
||||
console.log("error submit!!");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
onMounted(async () => {});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
Loading…
x
Reference in New Issue
Block a user