2016-06-01 3 views
2

나는 Spring Integration을 사용하여 TCP 게이트웨이를 만들었다. 내 서버가 클라이언트의 요청을 처리하고 응답을 보낼 수 있습니다. 그러나 클라이언트는 클라이언트가 모든 데이터를 읽기 전에 서버가 연결을 닫는 것 SocketException얼마 동안 서버 연결을 유지하기 위해 so-linger를 사용하는 방법

java.net.SocketException: Connection reset 
    at java.net.SocketInputStream.read(SocketInputStream.java:168) 
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264) 
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306) 
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158) 
    at sun.nio.cs.StreamDecoder.read0(StreamDecoder.java:107) 
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:93) 
    at java.io.InputStreamReader.read(InputStreamReader.java:151) 

을주고있다. 따라서 so-linger을 사용하고 싶습니다.

setSoLinger은 잔여 시간 동안 서버 소켓을 열린 상태로 유지해야합니다. setSoLinger에 대한 javadoc은 지정된 지연 시간 (초)을 사용하여 SO_LINGER을 활성화/비활성화합니다.

https://docs.oracle.com/javase/6/docs/api/java/net/Socket.html#setSoLinger%28boolean,%20int%29SoLinger을 설정 Spring Integration document를 참조하십시오.

내 스프링의 context.xml :

<int-ip:tcp-connection-factory id="crLfServer" 
      type="server" 
      port="${availableServerSocket}" 
      single-use="true" 
      so-timeout="10000" 
      using-nio="false" 
      serializer="connectionSerializeDeserialize" 
      deserializer="connectionSerializeDeserialize" 
      so-linger="2000"/> 

     <bean id="connectionSerializeDeserialize" class="org.springframework.integration.ip.tcp.serializer.ByteArrayStxEtxSerializer"/> 

     <int-ip:tcp-inbound-gateway id="gatewayCrLf" 
      connection-factory="crLfServer" 
      request-channel="serverBytes2StringChannel" 
      error-channel="errorChannel" 
      reply-timeout="10000"/> <!-- reply-timeout works on inbound-gateway --> 

     <int:channel id="toSA" /> 

     <int:service-activator input-channel="toSA" 
      ref="myService" 
      method="prepare"/> 

     <int:object-to-string-transformer id="serverBytes2String" 
      input-channel="serverBytes2StringChannel" 
      output-channel="toSA"/> 

     <int:transformer id="errorHandler" 
      input-channel="errorChannel" 
      expression="payload.failedMessage.payload + ':' + payload.cause.message"/> 

나는 봄 통합 초 또는 밀리 초 단위로 시간을 머무르게됩니다 여부를 모르겠습니다. 클라이언트가 데이터를 읽을 때까지 Server 소켓이 열려 있도록 다른 플래그를 설정해야합니다.

소켓 연결 종료 이벤트가 거의 즉시 서비스 빈에서 응답을 보내는 것을보고 있습니다. 서버가 대기하지 않는 것 같습니다. 시간을 너무 오래 설정하거나 대체 방법을 제안하는 방법을 도와주세요. 고맙습니다. 여기

로그입니다 :

2016-06-01 15:43:46,276 MyService response:     ACCEPT:E211001: 

2016-06-01 15:43:46.293 DEBUG [pool-1-thread-2][org.springframework.context.support.GenericXmlApplicationContext] Publishing event in o[email protected]7a187814: TcpConnectionCloseEvent [source=org[email protected]4c4b11e9], [factory=crLfServer, connectionId=22.220.220.222:1034:5678:77483643-2156-427f-96dd-a513670a75a3] **CLOSED** 

2016-06-01 15:43:46.294 DEBUG [pool-1-thread-2][org.springframework.context.support.GenericXmlApplicationContext] Publishing event in o[email protected]7a187814: TcpConnectionExceptionEvent [source=org[email protected]4c4b11e9, cause=java.net.SocketException: Socket is closed], [factory=crLfServer, connectionId=22.220.220.222:1034:5678:77483643-2156-427f-96dd-a513670a75a3] 
+0

M-m-m. 'connectionSerializeDeserialize'가 응답 메시지를 직렬화 할 수 없다는 것이 문제가 될 수 있습니까? 그것은'TcpNetConnection'이 send시 소켓을 닫는 경우입니다. –

+0

예. 그게 내 문제 야. 내 클라이언트는 ETX를받은 후에도 데이터를 읽으려고하므로 예외가 발생합니다. 도움을 주셔서 감사합니다. – kevin

+0

그래서 게리의 대답은 정확하고'single-use = "true"' –

답변

1

Spring 통합이 값에는 변환을 수행하지 않습니다, 그래서 초입니다.

so-linger처럼 보이는 동작은 0입니다 (close()에 대해 즉각적인 RST가 전송 됨).

정말 이럴 필요가 없습니다. TCP 스택이 설정되어 있지 않으면 정상적으로 소켓을 닫아야합니다.

무슨 일이 일어나는지 파악하려면 네트워크 모니터를 실행해야합니다. 당신이 소켓을 닫습니다 클라이언트를 신뢰하는 경우

, 당신은

single-use="true"

을 제거 정도 서버가 응답을 보낸 후 소켓을 닫지 않습니다 false로 설정할 수 있습니다.

+0

예. 그게 내 문제 야. 내 클라이언트는 ETX를받은 후에도 데이터를 읽으려고하므로 예외가 발생합니다. 나는 TCP 스택이 소켓을 닫을 수 있도록 아주 가볍게 제거했다.귀하의 제안으로 인해 서버가 개선되었습니다. 당신의 도움을 주셔서 감사합니다. – kevin

관련 문제