Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring集成TCP服务器多个连接超过5个_Spring_Spring Boot_Tcp_Spring Integration_Serversocket - Fatal编程技术网

Spring集成TCP服务器多个连接超过5个

Spring集成TCP服务器多个连接超过5个,spring,spring-boot,tcp,spring-integration,serversocket,Spring,Spring Boot,Tcp,Spring Integration,Serversocket,我现在正在使用以下版本的Spring Boot和Spring集成 spring.boot.version 2.3.4.RELEASE spring-integration 5.3.2.RELEASE 我的要求是创建一个TCP客户机-服务器通信,我正在使用spring集成来实现这一点。spike适用于客户端和服务器之间的单个通信,也适用于5个并发客户端连接 当我将并发客户机连接从5增加到任意数量时,它不起作用,但TCP服务器只接受5个连接 我在前面的一条评论(针对类似的需求)中使用了Gary

我现在正在使用以下版本的Spring Boot和Spring集成

spring.boot.version 2.3.4.RELEASE
spring-integration  5.3.2.RELEASE
我的要求是创建一个TCP客户机-服务器通信,我正在使用spring集成来实现这一点。spike适用于客户端和服务器之间的单个通信,也适用于5个并发客户端连接

当我将并发客户机连接从5增加到任意数量时,它不起作用,但TCP服务器只接受5个连接

我在前面的一条评论(针对类似的需求)中使用了Gary Russell提到的“ThreadAffinityClientConnectionFactory”,但仍然不起作用

下面是我目前掌握的代码

@Slf4j
@Configuration
@EnableIntegration
@IntegrationComponentScan
public class SocketConfig {

    @Value("${socket.host}")
    private String clientSocketHost;

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

    @Bean
    public TcpOutboundGateway tcpOutGate(AbstractClientConnectionFactory connectionFactory) {
        TcpOutboundGateway gate = new TcpOutboundGateway();
        //connectionFactory.setTaskExecutor(taskExecutor());
        gate.setConnectionFactory(clientCF());
        return gate;
    }

    @Bean
    public TcpInboundGateway tcpInGate(AbstractServerConnectionFactory connectionFactory)  {
        TcpInboundGateway inGate = new TcpInboundGateway();
        inGate.setConnectionFactory(connectionFactory);
        inGate.setRequestChannel(fromTcp());
        return inGate;
    }

    @Bean
    public MessageChannel fromTcp() {
        return new DirectChannel();
    }

    // Outgoing requests
    @Bean
    public ThreadAffinityClientConnectionFactory clientCF() {
        TcpNetClientConnectionFactory tcpNetClientConnectionFactory = new TcpNetClientConnectionFactory(clientSocketHost, serverCF().getPort());
        tcpNetClientConnectionFactory.setSingleUse(true);
        ThreadAffinityClientConnectionFactory threadAffinityClientConnectionFactory = new ThreadAffinityClientConnectionFactory(
            tcpNetClientConnectionFactory);
        // Tested with the below too.
        // threadAffinityClientConnectionFactory.setTaskExecutor(taskExecutor());
        return threadAffinityClientConnectionFactory;
    }


    // Incoming requests
    @Bean
    public AbstractServerConnectionFactory serverCF() {
        log.info("Server Connection Factory");
        TcpNetServerConnectionFactory tcpNetServerConnectionFactory = new TcpNetServerConnectionFactory(clientSocketPort);
        tcpNetServerConnectionFactory.setSerializer(new CustomSerializer());
        tcpNetServerConnectionFactory.setDeserializer(new CustomDeserializer());
        tcpNetServerConnectionFactory.setSingleUse(true);
        return tcpNetServerConnectionFactory;
    }


    @Bean
    public TaskExecutor taskExecutor () {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(50);
        executor.setMaxPoolSize(100);
        executor.setQueueCapacity(50);
        executor.setAllowCoreThreadTimeOut(true);
        executor.setKeepAliveSeconds(120);
        return executor;
    }

}
是否有人有过多个并发Tcp客户端连接超过5个的问题

谢谢

客户端代码:
@组件
@Slf4j
@所需参数构造函数
公共类ScheduledTaskService{
//超时(毫秒)
专用静态最终int插座\时间\超时=18000;
专用静态最终整数缓冲区大小=32000;
专用静态最终整数ETX=0x03;
私有静态最终字符串头=“ABCDEF”;
私有静态最终字符串数据=“固定数据”
私有最终AtomicInteger AtomicInteger=新的AtomicInteger();
@异步的
@计划(固定延迟=100000)
public void sendDataMessage()引发IOException、InterruptedException{
int numberOfRequests=10;
Callable executeMultipleSuccessfulRequestTask=()->socketSendNReceive();
最终集合callables=newarraylist();
IntStream.rangeClosed(1,numberOfRequests).forEach(i->{
添加(executeMultipleSuccessfulRequestTask);
});
ExecutorService ExecutorService=Executors.newFixedThreadPool(numberOfRequests);
List taskFutureList=executorService.invokeAll(可调用项);
列表字符串=taskFutureList.stream().map(未来->{
试一试{
返回future.get(20000,时间单位为毫秒);
}捕捉(中断异常e){
e、 printStackTrace();
}捕获(执行例外){
e、 printStackTrace();
}捕获(超时异常e){
e、 printStackTrace();
}
返回“”;
}).collect(Collectors.toList());
forEach(string->log.info(“从服务器收到的消息:{}”,string));
}
公共字符串socketSendNReceive()引发IOException{
int requestCounter=atomicInteger.incrementAndGet();
String host=“localhost”;
int端口=8000;
套接字=新套接字();
InetSocketAddress地址=新的InetSocketAddress(主机、端口);
socket.connect(地址、套接字超时);
套接字。设置超时(套接字超时);
//将消息发送到服务器
OutputStream os=socket.getOutputStream();
BufferedOutputStream bos=新的BufferedOutputStream(os);
write(HEADER.getBytes());
写入(data.getBytes());
bos.write(ETX);
bos.flush();
//info(“发送到服务器的消息:{}”,envio);
//从服务器获取返回消息
InputStream=socket.getInputStream();
字符串响应=接收器(is);
日志信息(“收到的响应”);
返回响应;
}
私有字符串接收器(InputStream in)引发IOException{
final StringBuffer StringBuffer=新StringBuffer();
int readLength;
字节[]缓冲区;
缓冲区=新字节[缓冲区大小];
做{
if(Objects.nonNull(in)){
log.info(“输入流不为空”);
}
readLength=in.read(缓冲区);
log.info(“readLength:{}”,readLength);
如果(读取长度>0){
追加(新字符串(缓冲区),0,readLength);
log.info(“字符串*******”);
}
}while(缓冲区[readLength-1]!=ETX);
缓冲区=空;
stringBuffer.deleteCharAt(resposta.length()-1);
返回stringBuffer.toString();
}
}

由于同时打开所有连接,因此需要增加服务器连接工厂上的
backlog
属性

它默认为5

/**
*连接待办事项中的套接字数。违约5;
*如果您期望高连接率,请增加。
*@param backlog要设置的backlog。
*/
公共void setBacklog(int backlog){

框架中没有任何东西会将连接限制为5个;如果您能提供一个展示这种行为的完整小示例,我可以看看有什么问题。嗨,Gary,感谢您的快速响应。我现在已在问题中添加了客户端代码,它将把10条并发消息推送到服务器套接字上。什么时候客户端代码尝试同时推送10条消息,然后从服务器套接字只接受5条消息,并且只得到5条响应。相同的客户端代码在另一个标准java服务器套接字上进行测试(不使用spring集成)但是对于10个并发的客户端连接请求来说效果很好。Ref link我知道你没有关闭套接字,但这不重要。我看不出为什么你会被限制为5个连接。同样,我需要一个完整的示例项目发布在某个地方,这样我就可以看到发生了什么。这需要一些专有的JAR-你能把它剥离到t吗他是最小的,没有Lombok?哇。工作起来很有魅力。您之前提到过,当前代码没有关闭连接。我们应该在哪里关闭连接?我假设在设置tcpNetServerConnectionFactory.setSingleUse(true)时,以及tcpNetClientConnectionFactory.setSingleUse(true)时;连接将自动关闭。如果
@Component
@Slf4j
@RequiredArgsConstructor
public class ScheduledTaskService {

    // Timeout in milliseconds
    private static final int SOCKET_TIME_OUT = 18000;
    private static final int BUFFER_SIZE = 32000;
    private static final int ETX = 0x03;
    private static final String HEADER = "ABCDEF             ";
    private static final String data = "FIXED DARATA"
    private final AtomicInteger atomicInteger = new AtomicInteger();

    @Async
    @Scheduled(fixedDelay = 100000)
    public void sendDataMessage() throws IOException, InterruptedException {
        int numberOfRequests = 10;

        Callable<String> executeMultipleSuccessfulRequestTask = () -> socketSendNReceive();

        final Collection<Callable<String>> callables = new ArrayList<>();
        IntStream.rangeClosed(1, numberOfRequests).forEach(i-> {
            callables.add(executeMultipleSuccessfulRequestTask);
        });
        ExecutorService executorService = Executors.newFixedThreadPool(numberOfRequests);

        List<Future<String>> taskFutureList = executorService.invokeAll(callables);
        List<String> strings = taskFutureList.stream().map(future -> {
            try {
                return future.get(20000, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }
            return "";
        }).collect(Collectors.toList());

        strings.forEach(string -> log.info("Message received from the server: {} ", string));

    }

    public String socketSendNReceive() throws IOException{
        int requestCounter = atomicInteger.incrementAndGet();

        String host = "localhost";
        int port = 8000;

        Socket socket = new Socket();
        InetSocketAddress address = new InetSocketAddress(host, port);
        socket.connect(address, SOCKET_TIME_OUT);
        socket.setSoTimeout(SOCKET_TIME_OUT);

        //Send the message to the server
        OutputStream os = socket.getOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(os);

        bos.write(HEADER.getBytes());
        bos.write(data.getBytes());
        bos.write(ETX);
        bos.flush();
//        log.info("Message sent to the server : {} ",  envio);

        //Get the return message from the server
        InputStream is = socket.getInputStream();
        String response =  receber(is);
        log.info("Received response");
        return response;
    }

    private String receber(InputStream in) throws IOException {
        final StringBuffer stringBuffer = new StringBuffer();
        int readLength;
        byte[] buffer;
        buffer = new byte[BUFFER_SIZE];
        do {
            if(Objects.nonNull(in)) {
                log.info("Input Stream not null");
            }
            readLength = in.read(buffer);
            log.info("readLength : {}  ", readLength);
            if(readLength > 0){
                stringBuffer.append(new String(buffer),0,readLength);
                log.info("String ******");
            }
        } while (buffer[readLength-1] != ETX);
        buffer = null;
        stringBuffer.deleteCharAt(resposta.length()-1);
        return stringBuffer.toString();
    }
}