zoukankan      html  css  js  c++  java
  • Socket通信

    本次分享的是一个简单的Web项目里使用的Socket通信案例

    1、建立监听类:

    package com.trust.fricem.TCPC.service;
    
    import org.springframework.web.context.WebApplicationContext;
    import org.springframework.web.context.support.WebApplicationContextUtils;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    /**
     * @Author:Singularity
     * @Date:2019/6/1 14:23
     * @Description: Socket 服务监听
     */
    public class SocketServiceLoader implements ServletContextListener {
    
        //socket server 线程
        private SocketThread socketThread;
    
        /**
         * 当Servlet 容器启动Web 应用时调用该方法。在调用完该方法之后,容器再对Filter 初始化,
         * 并且对那些在Web 应用启动时就需要被初始化的Servlet 进行初始化。
         */
        @Override
        public void contextInitialized(final ServletContextEvent sce) {
            System.out.println("容器启动-------");
            if (null == socketThread) {
                //新建线程类
                WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
                socketThread = new SocketThread(null, wac);
                //启动线程
                socketThread.start();
            }
        }
    
        /**
         * 当Servlet 容器终止Web 应用时调用该方法。在调用该方法之前,容器会先销毁所有的Servlet 和Filter 过滤器。
         */
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
            System.out.println("容器终止-------");
            if (null != socketThread && !socketThread.isInterrupted()) {
                socketThread.closeSocketServer();
                socketThread.interrupt();
            }
        }
    }

    2、创建线程类,同时创建 ServerSocket 服务端并监听客户端的连接

    package com.trust.fricem.TCPC.service;
    
    import com.trust.fricem.TCPC.controller.SocketDataDealController;
    import org.springframework.web.context.WebApplicationContext;
    
    import java.io.*;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * @Author:Singularity
     * @Date:2019/6/1 14:32
     * @Description: Socket 服务端
     */
    public class SocketThread extends Thread {
        private ExecutorService threadPool = Executors.newFixedThreadPool(100);
        private ServerSocket serverSocket = null;
        private WebApplicationContext webApplicationContext = null;
        Socket socket;
        BufferedReader reader;
        BufferedWriter writer;
    
        public SocketThread(ServerSocket serverScoket, WebApplicationContext wac) {
            try {
                if (null == serverSocket) {
                    this.serverSocket = new ServerSocket(8088);
                    webApplicationContext = wac;
                    System.out.println("socket start");
                    System.out.println("Spring 容器 webApplicationContext 获取");
                }
            } catch (Exception e) {
                System.out.println("SocketThread创建socket服务出错");
                e.printStackTrace();
            }
    
        }
    
        public void run() {
            while (!this.isInterrupted()) {
                try {
                    //1、创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口 1024-65535的某个端口
                    while (true) {// 巧用死循环
                        //2、调用accept()方法开始监听,等待客户端的连接
                        socket = serverSocket.accept();
    
                        InetAddress address = socket.getInetAddress();//获取远程客户端的IP信息
                        System.out.println("InetAddress:" + address);
                        System.out.println("IP地址:" + address.getHostAddress());
                        System.out.println("主机名:" + address.getHostName());
    
                        reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));//读取客户端消息
                        writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));//向客户端写消息
                        try {
                            //3、获取输入流,并读取客户端信息
                            String info = null;
                            SocketDataDealController sdd = new SocketDataDealController(webApplicationContext);
                            while (!(info = reader.readLine()).equals("bye")) {
                                System.out.println("收到来自客户端的发送的消息是:" + new String(info.getBytes(), "UTF-8"));
                                String returnInfo = sdd.dealSocketData(info);
                                System.out.println("给客户端的发送的消息是:" + returnInfo);
                                writer.write(new String(returnInfo.getBytes(), "UTF-8") + "
    ");
                                writer.flush();
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        } finally {
                            try {
                                if (reader != null) {
                                    reader.close();
                                }
                                if (writer != null) {
                                    writer.close();
                                }
                                if (socket != null) {
                                    System.out.println("Socket通道关闭");
                                    socket.close();
                                }
                            } catch (Exception e2) {
                                e2.printStackTrace();
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        public void closeSocketServer() {
            try {
                if (null != serverSocket && !serverSocket.isClosed()) {
                    System.out.println("ServerSocket 终止");
                    serverSocket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    3、处理客户端数据类,其中包含调用 Service 层方法的用法

    package com.trust.fricem.QRCode.controller;
    
    import com.trust.fricem.QRCode.entity.ProdQRCodeEntity;
    import com.trust.fricem.QRCode.entity.ReturnMessage;
    import com.trust.fricem.QRCode.entity.UniversalcodeEntity;
    import com.trust.fricem.QRCode.service.ProdQRCodeService;
    import com.trust.fricem.QRCode.service.UniversaleCodeService;
    import com.trust.fricem.common.Constant;
    import com.trust.fricem.common.util.ASCIIUtils;
    import com.trust.fricem.common.util.CRC8;
    import com.trust.fricem.equipment.entity.EquipmenttypeEntity;
    import com.trust.fricem.equipment.service.EquipmenttypeDisService;
    import com.trust.fricem.product.entity.ProducttypeEntity;
    import com.trust.fricem.product.service.ProductTypeService;
    import org.springframework.web.context.WebApplicationContext;
    
    /**
     * GPRS 通信接口
     * @author Singularity
     * @Time 2019.2.25
     */
    public class SCMInterface {
    
        private WebApplicationContext context = null;
        private ProdQRCodeService prodQRCodeService;
        private EquipmenttypeDisService equipmenttypeDisService;
        private ProductTypeService productTypeService;
        private UniversaleCodeService universaleCodeService;
    
        public SCMInterface(WebApplicationContext webApplicationContext) {
            context = webApplicationContext;
            // 利用 webApplicationContext 创建 service 
            prodQRCodeService = context.getBean(ProdQRCodeService.class);
            equipmenttypeDisService = context.getBean(EquipmenttypeDisService.class);
            productTypeService = context.getBean(ProductTypeService.class);
            universaleCodeService = context.getBean(UniversaleCodeService.class);
    
        }
    
    
        /**
         * 接口1
         */
        public String receiveMessage(String param) {
            ReturnMessage object = null;
            String returnStr = null;
            if (null != object) {
                if (null != object.getCodeStr()) {
                    String str = object.getCodeStr();
                    if (null != str && "" != str) {
                        //二维码类型标识
                        String codeType = str.substring(0, 2);
                        if (Constant.PROQrCode_BS.equals(codeType)) {//----普通二维码
                            returnStr = prodQRCodeService.updateQrCodeInfo(object);//修改二维码加工状态
                        }
                        if (Constant.PROQrCode_WS.equals(codeType)) {//----万能二维码
                            returnStr = universaleCodeService.saveUniversaleCode(object);//添加万能码使用记录数据
                            //returnStr = CRC8.returnType(Constant.PROQrCode_SUCCESS, Constant.PROQrCode_EQUIPNO);
                        }
                    }
                }
            }
            return returnStr;
        }
    }

    4、再 Web.xml 中添加监听

    <!-- spring监听器 -->
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        <!-- 防止spring内存溢出监听器,比如quartz -->
        <listener>
            <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
        </listener>
    
        <!-- Socket 监听器 (注意,监听要放在 Spring 之后,不然创建的 ServletContextEvent 是空的)-->
        <listener>
            <listener-class>com.trust.fricem.TCPC.service.SocketServiceLoader</listener-class>
        </listener>

    注意:由于使用的是 Servlet 的监听方法,servlet 容器是在 Spring 容器之前加载的,而本次我用的是 SSM 框架,其中的 service 层和 dao 层等使用 Spring 容器管理的,所以上方的黄色标注的地方调用的方法会报错, 其中的 webApplicationContext 就是为了解决,这个问题 (有什么不对或者不合理的地方,欢迎大家赐教!)

  • 相关阅读:
    在MathType如何让括号随内容自动调整大小的技巧
    对于MathType中公式与文字错位的问题怎么解决
    怎样批量修改MathType公式格式
    你与论文达人只差一个MathType的距离
    公式达人必杀技,你会几招?
    如何用MathType快速输入公式
    openfire数据库mysql配置
    thinkphp 操作mssql2008
    phpstudy+php5.2+mssql2008
    thinkphp openfire 添加用户 骨架
  • 原文地址:https://www.cnblogs.com/Singulariity-gs/p/11038239.html
Copyright © 2011-2022 走看看