由于毕设的需要,需要搭建一个简单的本地服务器,与单片机的WIFI模块进行UDP通信。服务器包含UDP客户端的发送部分和UDP服务器的接收部分。采用UDP是考虑到内网的网络状况较好,面向无连接的简单高效的UDP完全能够满足需求。这个服务器还用到了spring、maven、log4j和发送邮件。
温馨提示
其他帖子也有实现UDP的双向通信的,不过在编写代码的时候发现了一个问题,就是当我在UDP客户端线程和UDP服务器线程分别创建了一个DatagramSocket对象时,发现只要发送一个数据后,就会出现接收不到的情况。所以我是采取UDP客户端和UDP服务器共用一个DatagramSocket对象。
主程序代码:
- package smarthome.platform;
- import java.util.TimeZone;
- import java.net.DatagramPacket;
- import java.net.DatagramSocket;
- import java.net.InetAddress;
- import org.apache.log4j.Logger;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- import smarthome.mail.SendMail;
- import smarthome.socket.ReceiveMsg;
- import smarthome.socket.SendMsg;
- import smarthome.socket.UdpParams;
- public class App {
- private static final Logger logger = Logger.getLogger(App.class);
- static {
- TimeZone tz = TimeZone.getTimeZone("Etc/GMT-8");
- TimeZone.setDefault(tz);
- }
- public static void main(String[] args) {
- InetAddress host_ip;
- int host_port;
- String usr_ip;
- int usr_port;
- final Thread scanhread;
- final Thread listenThread;
- DatagramSocket receiveds = null;
- try {
- // 加载spring 配置文件
- ApplicationContext ctx = new ClassPathXmlApplicationContext("spring_beans.xml");
- UdpParams udp = (UdpParams) ctx.getBean("UdpParams");
- SendMail sendmail = (SendMail) ctx.getBean("SendMail");
- // 获取主机ip
- host_ip = java.net.InetAddress.getLocalHost();
- host_port = udp.getHost_port();
- usr_ip = udp.getUsr_ip();
- usr_port = udp.getUsr_port();
- logger.info(host_ip);
- logger.info("host port:" + host_port);
- logger.info("usr ip:" + usr_ip);
- logger.info("usr port:" + usr_port);
- // 初始化串口
- receiveds = new DatagramSocket(host_port, host_ip);
- byte[] b = "initialize".getBytes();
- DatagramPacket pack = new DatagramPacket(b, 0, b.length, InetAddress.getByName(usr_ip), udp.getUsr_port());
- receiveds.send(pack);
- // 监听端口
- ReceiveMsg receiveMsg = new ReceiveMsg(receiveds, sendmail);
- listenThread = new Thread(receiveMsg);
- listenThread.start();
- // 读取键盘输入并发送到串口
- SendMsg sendMsg = new SendMsg(receiveds, InetAddress.getByName(usr_ip), udp.getUsr_port());
- scanhread = new Thread(sendMsg);
- scanhread.start();
- logger.info("**********************************");
- logger.info("** **");
- logger.info("** start-up **");
- logger.info("** **");
- logger.info("**********************************");
- } catch (Exception e) {
- logger.error("Port occupied", e);
- }
- }
- }
发送邮件代码:
- package smarthome.mail;
- import java.util.Properties;
- import javax.mail.Authenticator;
- import javax.mail.MessagingException;
- import javax.mail.PasswordAuthentication;
- import javax.mail.Session;
- import javax.mail.Transport;
- import javax.mail.Message.RecipientType;
- import javax.mail.internet.AddressException;
- import javax.mail.internet.InternetAddress;
- import javax.mail.internet.MimeMessage;
- import org.apache.log4j.Logger;
- public class SendMail {
- private static final Logger logger = Logger.getLogger(SendMail.class);
- String mail_smtp_auth;
- String mail_smtp_host;
- String mail_smtp_port;
- String mail_user;
- String mail_password;
- String mail_termini;
- public String getMail_smtp_auth() {
- return mail_smtp_auth;
- }
- public void setMail_smtp_auth(String mail_smtp_auth) {
- this.mail_smtp_auth = mail_smtp_auth;
- }
- public String getMail_smtp_host() {
- return mail_smtp_host;
- }
- public void setMail_smtp_host(String mail_smtp_host) {
- this.mail_smtp_host = mail_smtp_host;
- }
- public String getMail_smtp_port() {
- return mail_smtp_port;
- }
- public void setMail_smtp_port(String mail_smtp_port) {
- this.mail_smtp_port = mail_smtp_port;
- }
- public String getMail_user() {
- return mail_user;
- }
- public void setMail_user(String mail_user) {
- this.mail_user = mail_user;
- }
- public String getMail_password() {
- return mail_password;
- }
- public void setMail_password(String mail_password) {
- this.mail_password = mail_password;
- }
- public String getMail_termini() {
- return mail_termini;
- }
- public void setMail_termini(String mail_termini) {
- this.mail_termini = mail_termini;
- }
- public void sendMail(String title, String context) {
- // 创建Properties 类用于记录邮箱的一些属性
- final Properties props = new Properties();
- // 表示SMTP发送邮件,必须进行身份验证
- props.put("mail.smtp.auth", getMail_smtp_auth());
- // 此处填写SMTP服务器
- props.put("mail.smtp.host", getMail_smtp_host());
- // 端口号,QQ邮箱给出了两个端口,但是另一个我一直使用不了,所以就给出这一个587
- props.put("mail.smtp.port", getMail_smtp_port());
- // 此处填写你的账号
- props.put("mail.user", getMail_user());
- // 此处的密码就是前面说的16位STMP口令
- props.put("mail.password", getMail_password());
- // 构建授权信息,用于进行SMTP进行身份验证
- Authenticator authenticator = new Authenticator() {
- protected PasswordAuthentication getPasswordAuthentication() {
- // 用户名、密码
- String userName = props.getProperty("mail.user");
- String password = props.getProperty("mail.password");
- return new PasswordAuthentication(userName, password);
- }
- };
- // 使用环境属性和授权信息,创建邮件会话
- Session mailSession = Session.getInstance(props, authenticator);
- // 创建邮件消息
- MimeMessage message = new MimeMessage(mailSession);
- // 设置发件人
- InternetAddress form;
- try {
- form = new InternetAddress(props.getProperty("mail.user"));
- message.setFrom(form);
- // 设置收件人的邮箱
- InternetAddress to = new InternetAddress(getMail_termini());
- message.setRecipient(RecipientType.TO, to);
- // 设置邮件标题
- message.setSubject(title);
- // 设置邮件的内容体
- message.setContent(context, "text/html;charset=UTF-8");
- // 最后发送邮件啦
- Transport.send(message);
- } catch (AddressException e) {
- logger.error("InternetAddress出错!");
- e.printStackTrace();
- } catch (MessagingException e) {
- logger.error("message出错!");
- e.printStackTrace();
- }
- }
- }
UDP服务器线程代码:
- ppackage smarthome.socket;
- import java.io.IOException;
- import java.net.DatagramPacket;
- import java.net.DatagramSocket;
- import java.util.TimeZone;
- import org.apache.log4j.Logger;
- import smarthome.mail.SendMail;
- public class ReceiveMsg implements Runnable {
- private static final Logger logger = Logger.getLogger(ReceiveMsg.class);
- private DatagramSocket datagramSocket;
- private SendMail sendmail;
- public ReceiveMsg(DatagramSocket datagramSocket, SendMail sendmail) {
- this.datagramSocket = datagramSocket;
- this.sendmail = sendmail;
- }
- public void run() {
- // 存放当天的人次
- int man_time = 0;
- // 存放当天零点的毫秒值
- long zero = System.currentTimeMillis() / (1000 * 3600 * 24) * (1000 * 3600 * 24)
- - TimeZone.getDefault().getRawOffset();
- // 一天的毫秒值为89999999
- long oneday = 90000000;
- int flag_smoke = 1;
- int flag_break = 1;
- int add_status = 1;
- while (true) {
- byte[] buf = new byte[1024];
- DatagramPacket pc = new DatagramPacket(buf, buf.length);
- try {
- datagramSocket.receive(pc);
- if (add_status % 2 == 1) {
- String str = new String(buf, 0, buf.length);
- String string = str.replaceAll("\0", "");
- logger.info("receive data:" + string);
- if (string.equals("SA")) {
- if (flag_smoke == 1) {
- logger.info("High smoke alarm!");
- sendmail.sendMail("来着传感器烟雾浓度过高的警报", "当前烟雾浓度为:" + string + ";疑似气体泄漏检测或火灾。");
- flag_smoke = 0;
- }
- } else if (string.equals("MA")) {
- if (flag_break == 1) {
- logger.info("Outsider invading alert!");
- sendmail.sendMail("来着传感器检测到移动物的警报", "在门窗关闭情况下,检测到了有人从门窗移动,疑似有人入侵警报。");
- flag_break = 0;
- }
- } else if (string.equals("RM")) {
- if (((System.currentTimeMillis() - zero)) > oneday) {
- man_time = 0;
- zero = +oneday;
- }
- man_time++;
- logger.info("Current Man Time:" + man_time);
- } else {
- logger.info("Current smoke concentration:" + string);
- }
- } else {
- }
- } catch (IOException e) {
- logger.error("receiving data failed!");
- e.printStackTrace();
- }finally {
- add_status++;
- }
- }
- }
- }
UDP客户端线程代码:
- package smarthome.socket;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.net.DatagramPacket;
- import java.net.DatagramSocket;
- import java.net.InetAddress;
- import org.apache.log4j.Logger;
- public class SendMsg implements Runnable {
- private static final Logger logger = Logger.getLogger(ReceiveMsg.class);
- private InetAddress ip;
- private int port;
- private DatagramSocket datagramSocket;
- public static Logger getLogger() {
- return logger;
- }
- public DatagramSocket getDatagramSocket() {
- return datagramSocket;
- }
- public InetAddress getIp() {
- return ip;
- }
- public int getPort() {
- return port;
- }
- public SendMsg(DatagramSocket datagramSocket, InetAddress ip, int port) {
- this.datagramSocket = datagramSocket;
- this.ip = ip;
- this.port = port;
- }
- public void run() {
- BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
- String line = null;
- try {
- while ((line = bufr.readLine()) != null) {
- byte[] receiveByte = line.getBytes();
- DatagramPacket receivePack = new DatagramPacket(receiveByte, 0, receiveByte.length, getIp(), getPort());
- datagramSocket.send(receivePack);
- logger.info("send data:" + line);
- }
- } catch (IOException e) {
- logger.error("sending data failed!");
- e.printStackTrace();
- }
- }
- }