注意:代码仅供参考,需要根据具体的设备做调整
同系列文章:
依赖关系:
- FaceIdProtocolCodecFactory.jar
- mina-core-2.0.9.jar
- slf4j-api-1.7.13.jar
- slf4j-simple-1.7.13.jar
演示程序界面
源代码
UdpServerDemo.java
package Splash; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.stage.Stage; import javafx.stage.WindowEvent; public class UdpServerDemo extends Application { @Override public void start(Stage stage) throws Exception { FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml")); Parent root = loader.load(); Scene scene = new Scene(root); stage.setScene(scene); // 设置窗体标题 stage.setTitle("UdpServerDemo"); // 设置窗体图标 stage.getIcons().add(new Image(getClass().getResourceAsStream("FireEyes.png"))); // 设置到屏幕中心 stage.centerOnScreen(); // 设置窗口关闭处理函数 stage.setOnCloseRequest((WindowEvent e) -> { FXMLDocumentController controller = loader.getController(); if(controller.mUdpServer != null) { controller.mUdpServer.dispose(true); controller.mUdpServer = null; } }); // 显示窗体 stage.show(); } /** * @param args the command line arguments */ public static void main(String[] args) { launch(args); } }
FXMLDocumentController.java
/* ---------------------------------------------------------- * 文件名称:FXMLDocumentController.java * * 作者:秦建辉 * * QQ:36748897 * * 博客:http://www.firstsolver.com/wordpress/ * * 开发环境: * NetBeans 8.1 * JDK 8u66 * * 版本历史: * V1.0 2015年12月11日 * 验证心跳包服务器端 ------------------------------------------------------------ */ package Splash; import Com.FirstSolver.FaceId.FaceIdProtocolCodecFactory; import Com.FirstSolver.FaceId.Utils; import java.io.IOException; import java.net.Inet4Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.net.URL; import java.util.Enumeration; import java.util.LinkedList; import java.util.List; import java.util.ResourceBundle; import javafx.collections.FXCollections; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Button; import javafx.scene.control.CheckBox; import javafx.scene.control.ComboBox; import javafx.scene.control.TextArea; import javafx.scene.control.TextField; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.transport.socket.nio.NioDatagramAcceptor; public class FXMLDocumentController extends IoHandlerAdapter implements Initializable { private final String DeviceCharset = "GBK"; private boolean IsServerRunning = false; public IoAcceptor mUdpServer = null; @FXML private ComboBox comboBoxServerIP; @FXML private TextField textFieldServerPort; @FXML private TextField textFieldSecretKey; @FXML private TextArea textAreaRecords; @FXML private Button buttonStartListener; @FXML private CheckBox checkBoxTask; @FXML private void handleButtonClearAction(ActionEvent event) { textAreaRecords.clear(); } @FXML private void handleButtonStartListenerAction(ActionEvent event) throws IOException, Exception { if(IsServerRunning) { if(mUdpServer != null) { mUdpServer.dispose(true); mUdpServer = null; } IsServerRunning = false; buttonStartListener.setText("开始侦听"); } else { // 创建侦听服务器 mUdpServer = new NioDatagramAcceptor(); mUdpServer.getFilterChain().addLast("codec", new ProtocolCodecFilter(new FaceIdProtocolCodecFactory(DeviceCharset))); mUdpServer.setHandler(this); mUdpServer.bind(new InetSocketAddress(InetAddress.getByName(comboBoxServerIP.getValue().toString()), Integer.parseInt(textFieldServerPort.getText()))); IsServerRunning = true; buttonStartListener.setText("停止侦听"); } } @Override public void sessionOpened(IoSession session) throws Exception { String SecretKey = textFieldSecretKey.getText(); if (!Utils.IsNullOrEmpty(SecretKey)) { FaceIdProtocolCodecFactory.setEncoderKey(session, SecretKey); FaceIdProtocolCodecFactory.setDecoderKey(session, SecretKey); } } @Override public void messageReceived(IoSession session, Object message) throws Exception { // 显示消息内容 String Answer = message.toString(); textAreaRecords.appendText(Answer + "\r\n"); // 判断是否有命令下发 if (checkBoxTask.isSelected()) { // 通知设备有命令要发送 session.write("PostRequest()"); } } @Override public void initialize(URL url, ResourceBundle rb) { // 设置服务器地址 try { List<String> IPList = new LinkedList<>(); Enumeration<NetworkInterface> InterfaceList = NetworkInterface.getNetworkInterfaces(); while (InterfaceList.hasMoreElements()) { NetworkInterface iFace = InterfaceList.nextElement(); if(iFace.isLoopback() || iFace.isVirtual() || iFace.isPointToPoint() || !iFace.isUp()) continue; Enumeration<InetAddress> AddrList = iFace.getInetAddresses(); while (AddrList.hasMoreElements()) { InetAddress address = AddrList.nextElement(); if (address instanceof Inet4Address) { IPList.add(address.getHostAddress()); } } } if (!IPList.isEmpty()) { comboBoxServerIP.setItems(FXCollections.observableList(IPList)); comboBoxServerIP.setValue(IPList.get(0)); } } catch (SocketException ex) { // 异常处理 } } }
FXMLDocument.fxml
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.text.*?> <?import javafx.scene.effect.*?> <?import javafx.geometry.*?> <?import java.lang.*?> <?import java.util.*?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <AnchorPane id="AnchorPane" minWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Splash.FXMLDocumentController"> <children> <GridPane minWidth="600.0"> <columnConstraints> <ColumnConstraints /> </columnConstraints> <rowConstraints> <RowConstraints /> <RowConstraints /> <RowConstraints /> </rowConstraints> <children> <GridPane GridPane.hgrow="ALWAYS" GridPane.rowIndex="0"> <columnConstraints> <ColumnConstraints /> <ColumnConstraints hgrow="ALWAYS" /> </columnConstraints> <rowConstraints> <RowConstraints /> <RowConstraints /> <RowConstraints /> </rowConstraints> <children> <Label text="心跳包接收服务器地址" GridPane.columnIndex="0" GridPane.halignment="RIGHT" GridPane.rowIndex="0"> <GridPane.margin> <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" /> </GridPane.margin> </Label> <Label text="心跳包接收服务器端口" GridPane.columnIndex="0" GridPane.halignment="RIGHT" GridPane.rowIndex="1"> <GridPane.margin> <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" /> </GridPane.margin> </Label> <Label text="通信密钥" GridPane.columnIndex="0" GridPane.halignment="RIGHT" GridPane.rowIndex="2"> <GridPane.margin> <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" /> </GridPane.margin> </Label> <ComboBox fx:id="comboBoxServerIP" minWidth="200.0" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" GridPane.rowIndex="0"> <GridPane.margin> <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" /> </GridPane.margin> </ComboBox> <TextField fx:id="textFieldServerPort" text="9904" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1"> <GridPane.margin> <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" /> </GridPane.margin> </TextField> <TextField fx:id="textFieldSecretKey" disable="true" editable="false" text="" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" GridPane.rowIndex="2" GridPane.vgrow="ALWAYS"> <GridPane.margin> <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" /> </GridPane.margin> </TextField> </children> </GridPane> <GridPane GridPane.rowIndex="1"> <columnConstraints> <ColumnConstraints /> <ColumnConstraints /> <ColumnConstraints /> </columnConstraints> <rowConstraints> <RowConstraints /> </rowConstraints> <children> <Button fx:id="buttonClear" minHeight="40.0" minWidth="80.0" onAction="#handleButtonClearAction" text="清空" GridPane.columnIndex="0" GridPane.halignment="LEFT" GridPane.hgrow="ALWAYS"> <GridPane.margin> <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" /> </GridPane.margin> </Button> <Button fx:id="buttonStartListener" minHeight="40.0" minWidth="80.0" onAction="#handleButtonStartListenerAction" text="开启侦听" GridPane.columnIndex="2" GridPane.halignment="RIGHT" GridPane.hgrow="ALWAYS"> <GridPane.margin> <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" /> </GridPane.margin> </Button> <CheckBox fx:id="checkBoxTask" mnemonicParsing="false" text="是否有命令下发" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS"> <GridPane.margin> <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" /> </GridPane.margin> </CheckBox> </children> <GridPane.margin> <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" /> </GridPane.margin> </GridPane> <TextArea fx:id="textAreaRecords" editable="false" minHeight="400.0" minWidth="600.0" wrapText="true" GridPane.hgrow="ALWAYS" GridPane.rowIndex="2" GridPane.vgrow="ALWAYS"> <GridPane.margin> <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" /> </GridPane.margin> </TextArea> </children> </GridPane> </children> </AnchorPane>