Socket通信

人盡茶涼 提交于 2020-04-03 04:10:35

本次分享的是一个简单的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") + "\n");
                            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 就是为了解决,这个问题 (有什么不对或者不合理的地方,欢迎大家赐教!)

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!