【问题标题】:Spring TCP Socket client not receiving data from MainframeSpring TCP Socket客户端未从大型机接收数据
【发布时间】:2017-08-30 12:38:01
【问题描述】:

我正在尝试使用this example 向使用HEX 数据进行通信的大型机机器发送和接收数据。所以我的配置中有以下内容:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:int="http://www.springframework.org/schema/integration"
       xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
        http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd">

    <context:property-placeholder />

    <!-- Client side -->

    <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="<ip>"
                                   serializer="CustomSerializerDeserializer"
                                   deserializer="CustomSerializerDeserializer"
                                   port="${availableServerSocket}"
                                   single-use="false"
                                   so-timeout="1800000"
                                   using-nio="false" />

    <bean id="CustomSerializerDeserializer" class="org.springframework.integration.samples.tcpclientserver.CustomSerializerDeserializer" />


    <int:channel id="input" />

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

    <!-- Server side -->

    <int-ip:tcp-connection-factory id="crLfServer"
                                   type="server"
                                   port="${availableServerSocket}"/>

    <int-ip:tcp-inbound-gateway id="gatewayCrLf"
                                connection-factory="crLfServer"
                                request-channel="serverBytes2StringChannel"
                                error-channel="errorChannel"/>

    <int:channel id="toSA" />

    <int:service-activator input-channel="toSA"
                           ref="echoService"
                           method="test"/>

    <bean id="echoService"
          class="org.springframework.integration.samples.tcpclientserver.EchoService" />

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

</beans>

而在我的序列化器/反序列化器中,我有以下内容:

public void serialize(String input, OutputStream outputStream) throws IOException {
    outputStream.write(buildmsg(input));
    outputStream.flush();
}

public String deserialize(InputStream inputStream) throws IOException {
    String data = "";
    logger.info("inside deserialize");
    DataInputStream dis = new DataInputStream(inputStream);
    int len = dis.readInt();
    if (len > 0) {
        logger.info("len: " + decimaltohex(len));
        logger.info("data: " + data);
        byte[] b = new byte[dis.available()];
        dis.readFully(b);
        data += decimaltohex(len);
        data += byteArrayToHex(b);
    }
    logger.info("full data:" + data);
    return data;
}

public byte[] buildmsg(String body) throws UnsupportedEncodingException {
    String header = "00000000";
    String totMsg = header + body;
    header = massageheader(decimaltohex(totMsg.length() / 2));
    totMsg = header + body;
    logger.info("sending data : " + totMsg);
    return hexStringToByteArray(totMsg);
}

public String decimaltohex(int data) {
    return Integer.toHexString(data);
}

public static String massageheader(String data) {
    String str = String.format("%8s", data).replace(' ', '0').toUpperCase();
    return str;
}

public static byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                + Character.digit(s.charAt(i + 1), 16));
    }
    return data;
}

public static String byteArrayToHex(byte[] a) {
    StringBuilder sb = new StringBuilder(a.length * 2);
    for (byte b : a) {
        sb.append(String.format("%02x", b));
    }
    return sb.toString();
}

输入本身是一个十六进制字符串(假设是这样)。所以消息正在发送,响应也被正确接收,但输出没有被传递回 Echo 服务。为什么这没有发生?我的配置有什么问题吗?

【问题讨论】:

    标签: java spring sockets tcp


    【解决方案1】:

    这不是DEBUG日志,只是INFO;你的 log4j 配置一定是错误的。

    反序列化

    这只是接收线程等待数据;它卡在您的 for 循环中,等待大型机关闭连接 - 我建议您在循环中添加一些调试。

    编辑

    您的 POM 中缺少 Commons-logging...

    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    

    或切换到 log4j2

    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.7</version>
    </dependency>
    

    并创建一个 log4j2 配置文件。

    Spring Framework 5 现在使用自己的 commons-logging 实现,不支持 log4j 1.x。

    【讨论】:

    • 我添加了一个更正 - 这只是阅读器线程坐在您的反序列化器中等待数据。
    • 你说得对,这是我的逻辑错误。感谢您指出了这一点。我现在已经修复它并且字节正在转换为字符串。我可以看到它们打印在我的日志中,但由于某种原因没有传递给 echoservice 类。你能帮我解释为什么吗?
    • 你需要查看一个DEBUG日志;如果你还是想不通;将日志发布到某个地方。
    • 我已经解决了这个问题,但我想知道套接字连接是否在每次发送消息时打开和关闭,或者连接是否仍然存在?发生的情况是,即使我连续发送 2 条消息,套接字描述符也不同。这会导致大型机端出现问题。
    • 如果你的配置还是和上面一样,你有single-use="true",表示每次请求一个新的socket;与"false" 相同的连接将持续到大型机关闭它。
    【解决方案2】:

    如果主机在响应结束时没有关闭连接(可能不会),则读取循环将永远不会退出。循环需要以某种方式了解响应的预期或实际长度。

    序列化器肯定也需要做一些 EBCDIC 转换?

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-29
    • 1970-01-01
    • 1970-01-01
    • 2012-03-05
    • 1970-01-01
    • 2016-12-06
    • 2013-01-31
    • 2016-03-31
    相关资源
    最近更新 更多