Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
436 views
in Technique[技术] by (71.8m points)

springboot中如何开启两个长连接线程的端口呢?

以前搞一个端口是没问题的,代码片断如下:
`

package com.smart.env.service.impl;

import com.smart.env.utils.ParseDust;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

@Component
public class DustDeviceServerSocket {

    @Value("${socket.dustPort}")
    private Integer port;

    @Autowired
    private MsgProducer msgProducer;

    public static void main(String[] args) {
        new DustDeviceServerSocket().startAction();
    }

    public void startAction(){
        java.net.ServerSocket serverSocket=null;
        try {
            serverSocket=new java.net.ServerSocket(port);  //端口号
            System.out.println("环境监测Socket服务已启动,占用端口: " + serverSocket.getLocalPort() );
            //通过死循环开启长连接,开启线程去处理消息
            while(true){
                Socket socket=serverSocket.accept();
                new Thread(new MyRuns(socket)).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (serverSocket!=null) {
                    serverSocket.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }

    class MyRuns implements Runnable{

        Socket socket;
        BufferedReader reader;
        BufferedWriter writer;

        public MyRuns(Socket socket) {
            super();
            this.socket = socket;
        }

        @Override
        public void run() {
            try {
                reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));//读取客户端消息
                writer=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));//向客户端写消息
                String lineString="";
                String str="";
                while((lineString=reader.readLine())!=null){
                    System.out.println("接收数据:"+lineString);
                    str = ParseDust.Shift(lineString);
                    writer.write("server response:"+str+"
");
                    if(str!=null&&!"".equals(str)){
                        System.out.println(str);
                        msgProducer.sendMsg(str);
                    }
                    writer.flush();
                }
                System.out.println(str);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (reader!=null) {
                        reader.close();
                    }
                    if (writer!=null) {
                        writer.close();
                    }
                    if (socket!=null) {
                        socket.close();
                    }
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
        }

    }

}

主入口里的代码:

ApplicationContext applicationContext = SpringApplication.run(EnvApplication.class, args);
        applicationContext.getBean(DustDeviceServerSocket.class).startAction();
        SpringApplication.run(EnvApplication.class, args);

现在又加一个端口,我把上面的文件复制一份出来改为新端口,发现第一个可以跑,第二个却跑不起来了。

主入口代码:

ApplicationContext applicationContext = SpringApplication.run(EnvApplication.class, args);
        applicationContext.getBean(DustDeviceServerSocket.class).startAction();
        applicationContext.getBean(CraneDeviceServerSocket.class).startAction();
        SpringApplication.run(EnvApplication.class, args);

在网上找资料
找到以下代码片断:


package com.smart.env.service.impl;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;


@Component
public class ApplicationContextProvider implements ApplicationContextAware {

    private static ApplicationContext context;

    private ApplicationContextProvider(){}

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    public  static <T> T getBean(String name,Class<T> aClass){
        return context.getBean(name,aClass);
    }

}

moniotr代码:


package com.smart.env.service.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.management.monitor.Monitor;

@Component("mTask")
@Scope("prototype")
public class MoniotrTask extends Thread  {

    final static Logger logger= LoggerFactory.getLogger(MoniotrTask.class);
    //参数封装
    private Monitor monitor;

    @Autowired
    private  DustDeviceServerSocket dustDeviceServerSocket;

    public void setMonitor(Monitor monitor) {
        this.monitor = monitor;
    }

    public void startAction1(){
        dustDeviceServerSocket.startAction();
    }

    public void startAction2(){
        System.out.println("222222");
    }

    @Override
    public void run() {
        logger.info("线程:"+Thread.currentThread().getName()+"运行中.....");
    }


}

主入口代码:

        MoniotrTask  m1=   ApplicationContextProvider.getBean("mTask",MoniotrTask .class);
        m1.startAction1();
        System.out.println("123");
        MoniotrTask  m2=   ApplicationContextProvider.getBean("mTask",MoniotrTask .class);
        m2.startAction2();

第二个端口还是跑不起来

我分析了原因:主要在于
while(true){

            Socket socket=serverSocket.accept();
            new Thread(new MyRuns(socket)).start();
        }

这几段代码,进入死循环后面的都不跑了,但是翻了网上资料,如果搞长链接,必须要死循环。
请各位路过的大神,指点下,应该如何解决这个问题,谢谢了!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

每次初始化一个服务端socket就新开一个线程,要不当线程初始化第一个时候socket服务端已经阻塞到那里,不会往下面执行初始化第二个服务端了。


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...