多线程UDP服务器

        由于毕设的需要,需要搭建一个简单的本地服务器,与单片机的WIFI模块进行UDP通信。服务器包含UDP客户端的发送部分和UDP服务器的接收部分。采用UDP是考虑到内网的网络状况较好,面向无连接的简单高效的UDP完全能够满足需求。这个服务器还用到了spring、maven、log4j和发送邮件。

温馨提示       
         其他帖子也有实现UDP的双向通信的,不过在编写代码的时候发现了一个问题,就是当我在UDP客户端线程和UDP服务器线程分别创建了一个DatagramSocket对象时,发现只要发送一个数据后,就会出现接收不到的情况。所以我是采取UDP客户端和UDP服务器共用一个DatagramSocket对象。

主程序代码:

  1. package smarthome.platform;  
  2.   
  3. import java.util.TimeZone;  
  4. import java.net.DatagramPacket;  
  5. import java.net.DatagramSocket;  
  6. import java.net.InetAddress;  
  7. import org.apache.log4j.Logger;  
  8. import org.springframework.context.ApplicationContext;  
  9. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  10.   
  11. import smarthome.mail.SendMail;  
  12. import smarthome.socket.ReceiveMsg;  
  13. import smarthome.socket.SendMsg;  
  14. import smarthome.socket.UdpParams;  
  15.   
  16. public class App {  
  17.   
  18.     private static final Logger logger = Logger.getLogger(App.class);  
  19.   
  20.     static {  
  21.         TimeZone tz = TimeZone.getTimeZone("Etc/GMT-8");  
  22.         TimeZone.setDefault(tz);  
  23.     }  
  24.   
  25.     public static void main(String[] args) {  
  26.   
  27.         InetAddress host_ip;  
  28.         int host_port;  
  29.         String usr_ip;  
  30.         int usr_port;  
  31.   
  32.         final Thread scanhread;  
  33.         final Thread listenThread;  
  34.         DatagramSocket receiveds = null;  
  35.   
  36.         try {  
  37.   
  38.             // 加载spring 配置文件  
  39.             ApplicationContext ctx = new ClassPathXmlApplicationContext("spring_beans.xml");  
  40.             UdpParams udp = (UdpParams) ctx.getBean("UdpParams");  
  41.             SendMail sendmail = (SendMail) ctx.getBean("SendMail");  
  42.               
  43.             // 获取主机ip  
  44.             host_ip = java.net.InetAddress.getLocalHost();  
  45.             host_port = udp.getHost_port();  
  46.             usr_ip = udp.getUsr_ip();  
  47.             usr_port = udp.getUsr_port();  
  48.             logger.info(host_ip);  
  49.             logger.info("host port:" + host_port);  
  50.             logger.info("usr  ip:" + usr_ip);  
  51.             logger.info("usr  port:" + usr_port);  
  52.   
  53.             // 初始化串口  
  54.             receiveds = new DatagramSocket(host_port, host_ip);  
  55.             byte[] b = "initialize".getBytes();  
  56.             DatagramPacket pack = new DatagramPacket(b, 0, b.length, InetAddress.getByName(usr_ip), udp.getUsr_port());  
  57.             receiveds.send(pack);  
  58.   
  59.             // 监听端口  
  60.             ReceiveMsg receiveMsg = new ReceiveMsg(receiveds, sendmail);  
  61.             listenThread = new Thread(receiveMsg);  
  62.             listenThread.start();  
  63.   
  64.             // 读取键盘输入并发送到串口  
  65.             SendMsg sendMsg = new SendMsg(receiveds, InetAddress.getByName(usr_ip), udp.getUsr_port());  
  66.             scanhread = new Thread(sendMsg);  
  67.             scanhread.start();  
  68.   
  69.             logger.info("**********************************");  
  70.             logger.info("**                              **");  
  71.             logger.info("**            start-up          **");  
  72.             logger.info("**                              **");  
  73.             logger.info("**********************************");  
  74.   
  75.         } catch (Exception e) {  
  76.             logger.error("Port occupied", e);  
  77.         }  
  78.     }  
  79. }  
发送邮件代码:

  1. package smarthome.mail;  
  2.   
  3. import java.util.Properties;  
  4.   
  5. import javax.mail.Authenticator;  
  6. import javax.mail.MessagingException;  
  7. import javax.mail.PasswordAuthentication;  
  8. import javax.mail.Session;  
  9. import javax.mail.Transport;  
  10. import javax.mail.Message.RecipientType;  
  11. import javax.mail.internet.AddressException;  
  12. import javax.mail.internet.InternetAddress;  
  13. import javax.mail.internet.MimeMessage;  
  14.   
  15. import org.apache.log4j.Logger;  
  16.   
  17. public class SendMail {  
  18.     private static final Logger logger = Logger.getLogger(SendMail.class);  
  19.     String mail_smtp_auth;  
  20.     String mail_smtp_host;  
  21.     String mail_smtp_port;  
  22.     String mail_user;  
  23.     String mail_password;  
  24.     String mail_termini;  
  25.   
  26.     public String getMail_smtp_auth() {  
  27.         return mail_smtp_auth;  
  28.     }  
  29.   
  30.     public void setMail_smtp_auth(String mail_smtp_auth) {  
  31.         this.mail_smtp_auth = mail_smtp_auth;  
  32.     }  
  33.   
  34.     public String getMail_smtp_host() {  
  35.         return mail_smtp_host;  
  36.     }  
  37.   
  38.     public void setMail_smtp_host(String mail_smtp_host) {  
  39.         this.mail_smtp_host = mail_smtp_host;  
  40.     }  
  41.   
  42.     public String getMail_smtp_port() {  
  43.         return mail_smtp_port;  
  44.     }  
  45.   
  46.     public void setMail_smtp_port(String mail_smtp_port) {  
  47.         this.mail_smtp_port = mail_smtp_port;  
  48.     }  
  49.   
  50.     public String getMail_user() {  
  51.         return mail_user;  
  52.     }  
  53.   
  54.     public void setMail_user(String mail_user) {  
  55.         this.mail_user = mail_user;  
  56.     }  
  57.   
  58.     public String getMail_password() {  
  59.         return mail_password;  
  60.     }  
  61.   
  62.     public void setMail_password(String mail_password) {  
  63.         this.mail_password = mail_password;  
  64.     }  
  65.   
  66.     public String getMail_termini() {  
  67.         return mail_termini;  
  68.     }  
  69.   
  70.     public void setMail_termini(String mail_termini) {  
  71.         this.mail_termini = mail_termini;  
  72.     }  
  73.   
  74.     public void sendMail(String title, String context) {  
  75.   
  76.         // 创建Properties 类用于记录邮箱的一些属性  
  77.         final Properties props = new Properties();  
  78.         // 表示SMTP发送邮件,必须进行身份验证  
  79.         props.put("mail.smtp.auth", getMail_smtp_auth());  
  80.         // 此处填写SMTP服务器  
  81.         props.put("mail.smtp.host", getMail_smtp_host());  
  82.         // 端口号,QQ邮箱给出了两个端口,但是另一个我一直使用不了,所以就给出这一个587  
  83.         props.put("mail.smtp.port", getMail_smtp_port());  
  84.         // 此处填写你的账号  
  85.         props.put("mail.user", getMail_user());  
  86.         // 此处的密码就是前面说的16位STMP口令  
  87.         props.put("mail.password", getMail_password());  
  88.   
  89.         // 构建授权信息,用于进行SMTP进行身份验证  
  90.         Authenticator authenticator = new Authenticator() {  
  91.   
  92.             protected PasswordAuthentication getPasswordAuthentication() {  
  93.                 // 用户名、密码  
  94.                 String userName = props.getProperty("mail.user");  
  95.                 String password = props.getProperty("mail.password");  
  96.                 return new PasswordAuthentication(userName, password);  
  97.             }  
  98.         };  
  99.         // 使用环境属性和授权信息,创建邮件会话  
  100.         Session mailSession = Session.getInstance(props, authenticator);  
  101.         // 创建邮件消息  
  102.         MimeMessage message = new MimeMessage(mailSession);  
  103.         // 设置发件人  
  104.         InternetAddress form;  
  105.         try {  
  106.             form = new InternetAddress(props.getProperty("mail.user"));  
  107.             message.setFrom(form);  
  108.   
  109.             // 设置收件人的邮箱  
  110.             InternetAddress to = new InternetAddress(getMail_termini());  
  111.             message.setRecipient(RecipientType.TO, to);  
  112.   
  113.             // 设置邮件标题  
  114.             message.setSubject(title);  
  115.   
  116.             // 设置邮件的内容体  
  117.             message.setContent(context, "text/html;charset=UTF-8");  
  118.   
  119.             // 最后发送邮件啦  
  120.             Transport.send(message);  
  121.         } catch (AddressException e) {  
  122.             logger.error("InternetAddress出错!");  
  123.             e.printStackTrace();  
  124.         } catch (MessagingException e) {  
  125.             logger.error("message出错!");  
  126.             e.printStackTrace();  
  127.         }  
  128.     }  
  129. }  
UDP服务器线程代码:

  1. ppackage smarthome.socket;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.DatagramPacket;  
  5. import java.net.DatagramSocket;  
  6. import java.util.TimeZone;  
  7.   
  8. import org.apache.log4j.Logger;  
  9. import smarthome.mail.SendMail;  
  10.   
  11. public class ReceiveMsg implements Runnable {  
  12.     private static final Logger logger = Logger.getLogger(ReceiveMsg.class);  
  13.     private DatagramSocket datagramSocket;  
  14.     private SendMail sendmail;  
  15.   
  16.     public ReceiveMsg(DatagramSocket datagramSocket, SendMail sendmail) {  
  17.         this.datagramSocket = datagramSocket;  
  18.         this.sendmail = sendmail;  
  19.     }  
  20.   
  21.     public void run() {  
  22.         // 存放当天的人次  
  23.         int man_time = 0;  
  24.         // 存放当天零点的毫秒值  
  25.         long zero = System.currentTimeMillis() / (1000 * 3600 * 24) * (1000 * 3600 * 24)  
  26.                 - TimeZone.getDefault().getRawOffset();  
  27.         // 一天的毫秒值为89999999  
  28.         long oneday = 90000000;  
  29.         int flag_smoke = 1;  
  30.         int flag_break = 1;  
  31.         int add_status = 1;  
  32.         while (true) {  
  33.   
  34.             byte[] buf = new byte[1024];  
  35.             DatagramPacket pc = new DatagramPacket(buf, buf.length);  
  36.             try {  
  37.                 datagramSocket.receive(pc);  
  38.                 if (add_status % 2 == 1) {  
  39.                     String str = new String(buf, 0, buf.length);  
  40.                     String string = str.replaceAll("\0""");  
  41.                     logger.info("receive data:" + string);  
  42.   
  43.                     if (string.equals("SA")) {  
  44.                         if (flag_smoke == 1) {  
  45.                             logger.info("High smoke alarm!");  
  46.                             sendmail.sendMail("来着传感器烟雾浓度过高的警报""当前烟雾浓度为:" + string + ";疑似气体泄漏检测或火灾。");  
  47.                             flag_smoke = 0;  
  48.                         }  
  49.                     } else if (string.equals("MA")) {  
  50.                         if (flag_break == 1) {  
  51.                             logger.info("Outsider invading alert!");  
  52.                             sendmail.sendMail("来着传感器检测到移动物的警报""在门窗关闭情况下,检测到了有人从门窗移动,疑似有人入侵警报。");  
  53.                             flag_break = 0;  
  54.                         }  
  55.                     } else if (string.equals("RM")) {  
  56.                         if (((System.currentTimeMillis() - zero)) > oneday) {  
  57.                             man_time = 0;  
  58.                             zero = +oneday;  
  59.                         }  
  60.                         man_time++;  
  61.                         logger.info("Current Man Time:" + man_time);  
  62.                     } else {  
  63.                         logger.info("Current smoke concentration:" + string);  
  64.                     }  
  65.                 } else {  
  66.                 }  
  67.             } catch (IOException e) {  
  68.                 logger.error("receiving data failed!");  
  69.                 e.printStackTrace();  
  70.             }finally {  
  71.                 add_status++;  
  72.             }  
  73.         }  
  74.     }  
  75.   
  76. }  
UDP客户端线程代码:

  1. package smarthome.socket;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStreamReader;  
  6. import java.net.DatagramPacket;  
  7. import java.net.DatagramSocket;  
  8. import java.net.InetAddress;  
  9.   
  10. import org.apache.log4j.Logger;  
  11.   
  12. public class SendMsg implements Runnable {  
  13.   
  14.     private static final Logger logger = Logger.getLogger(ReceiveMsg.class);  
  15.   
  16.     private InetAddress ip;  
  17.     private int port;  
  18.     private DatagramSocket datagramSocket;  
  19.   
  20.     public static Logger getLogger() {  
  21.         return logger;  
  22.     }  
  23.   
  24.     public DatagramSocket getDatagramSocket() {  
  25.         return datagramSocket;  
  26.     }  
  27.   
  28.     public InetAddress getIp() {  
  29.         return ip;  
  30.     }  
  31.   
  32.     public int getPort() {  
  33.         return port;  
  34.     }  
  35.   
  36.     public SendMsg(DatagramSocket datagramSocket, InetAddress ip, int port) {  
  37.         this.datagramSocket = datagramSocket;  
  38.         this.ip = ip;  
  39.         this.port = port;  
  40.     }  
  41.   
  42.     public void run() {  
  43.         BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));  
  44.         String line = null;  
  45.         try {  
  46.             while ((line = bufr.readLine()) != null) {  
  47.                 byte[] receiveByte = line.getBytes();  
  48.                 DatagramPacket receivePack = new DatagramPacket(receiveByte, 0, receiveByte.length, getIp(), getPort());  
  49.                 datagramSocket.send(receivePack);  
  50.                 logger.info("send data:" + line);  
  51.             }  
  52.         } catch (IOException e) {  
  53.             logger.error("sending data failed!");  
  54.             e.printStackTrace();  
  55.         }  
  56.   
  57.     }  
  58.   
  59. }  
最后祝自己顺利毕业吧!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值