0
votes

I want use spring integration to replace socket client.My socket client code is like this:

public static void main(String[] args) {

    try {
        Socket socket = new Socket("localhost", 7779);
        OutputStream os = socket.getOutputStream();
        PrintWriter pw = new PrintWriter(os);
        String str = "hello server!";
        pw.write(str);
        pw.flush();
        socket.shutdownOutput();
        InputStream is = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String info = br.readLine();
        while (info != null) {
            System.out.println("i am client. server says that " + info);
            info = br.readLine();
            pw.close();
        }
        br.close();
        is.close();
        pw.close();
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

socket client will get server's reply msg. and I use spring integration to do the same job. spring integration's xml code is like this:

    <int:gateway id="gw"
             service-interface="org.springframework.integration.samples.tcpclientserver.SimpleGateway"
             default-request-channel="input"/>

<int-ip:tcp-connection-factory id="client"
                               type="client"
                               host="localhost"
                               port="7779"
                               single-use="true"
                               so-timeout="10000"/>

<int:channel id="input"/>

<int-ip:tcp-outbound-gateway id="outGateway"
                             request-channel="input"
                             reply-channel="clientBytes2StringChannel"
                             connection-factory="client"
                             request-timeout="10000"
                             reply-timeout="10000"/>

<int:object-to-string-transformer id="clientBytes2String"
                                  input-channel="clientBytes2StringChannel"/>

it's a part of spring integration's tcp-client-server example https://github.com/spring-projects/spring-integration-samples/tree/master/basic/tcp-client-server

java code is like this:

    final Scanner scanner = new Scanner(System.in);
    final GenericXmlApplicationContext context = Main.setupContext();
    final SimpleGateway gateway = context.getBean(SimpleGateway.class);
    final AbstractServerConnectionFactory crLfServer = context.getBean(AbstractServerConnectionFactory.class);

    TestingUtilities.waitListening(crLfServer, 10000L);

    while (true) {

        final String input = scanner.nextLine();

        if ("q".equals(input.trim())) {
            break;
        }
        else {
            final String result = gateway.send(input);
            System.out.println(result);
        }
    }

    System.out.println("Exiting application...bye.");
    System.exit(0);

}

public static GenericXmlApplicationContext setupContext() {
    final GenericXmlApplicationContext context = new GenericXmlApplicationContext();

    if (System.getProperty(AVAILABLE_SERVER_SOCKET) == null) {
        System.out.print("Detect open server socket...");
        int availableServerSocket = SocketUtils.findAvailableTcpPort(5678);

        final Map<String, Object> sockets = new HashMap<>();
        sockets.put(AVAILABLE_SERVER_SOCKET, availableServerSocket);

        final MapPropertySource propertySource = new MapPropertySource("sockets", sockets);

        context.getEnvironment().getPropertySources().addLast(propertySource);
    }

    System.out.println("using port " + context.getEnvironment().getProperty(AVAILABLE_SERVER_SOCKET));

    context.load("classpath:META-INF/spring/integration/tcpClientServerDemo-context.xml");
    context.registerShutdownHook();
    context.refresh();

    return context;
}

and I can't get sever reply, because server doesn't get a eof signal and it still blocked in readLine(); the exception I get : org.springframework.integration.MessageTimeoutException: Timed out waiting for response.

Here is server code:

try {
        ServerSocket serverSocket = new ServerSocket(7779);
        Socket socket = serverSocket.accept();
        InputStream is = socket.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String info = br.readLine();
        System.out.println("from client : "+info);
        while (info != null) {
            System.out.println("i am server. message from client is " + info);
            info = br.readLine(); //server blocked here
        }
        socket.shutdownInput();
        OutputStream os = socket.getOutputStream();
        String replyMsg="welcom from server 7779 ACK\r\n";
        os.write(replyMsg.getBytes());
        os.close();
        br.close();
        isr.close();
        is.close();
        socket.close();
        serverSocket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

so how can I send a eof singal to server so my application will get the server's reply?

1
You need to show the server side code.Gary Russell
I add the server side code.jsdsh
The client connection factory will configure a ByteArrayCrLfSerializer by default, which adds \r\n to the data, so the readLine() should exit just fine and you are properly adding \r\n on the reply so that should be received ok too. Try turning on DEBUG logging to see if it helps; also look at a network trace, such as with WireShark.Gary Russell
As you see I have add \r\n for the end of the string,but can't work. I think the problem is how spring integration handle " socket.shutdownOutput() ". I think spring integration closed socket when client side shutdownOutput(). I but don't know how to simulate shutdownOutput in Spring integrationjsdsh

1 Answers

0
votes

Spring Integration currently doesn't support those shutDown*() methods.

Please open a GitHub Issue and we'll take a look.