मुझे डेटा स्ट्रीमिंग के साथ कुछ समस्या है डेटा सर्वर के नियमित हिस्से को फ्लश करते समय इसे इसकी लंबाई के साथ भेजता है जो वास्तव में डेटा स्ट्रीम को दूषित करता है।

(एम्बेडेड जेटी और एम्बेडेड टोमकैट एक ही परिणाम उत्पन्न करता है।)

GitHub

मैं एक क्लाइंट के रूप में netty का उपयोग कर रहा हूं और यह संख्या को आने वाले खंड के पहले बाइट्स के रूप में लॉग करता है (नियमित रेखाएं \ n \ r से अलग होती हैं)। इसके अलावा घाट का लकड़हारा

DEBUG org.eclipse.jetty.io.WriteFlusher - write: WriteFlusher@ ... [HeapByteBuffer@ ... {<<<\r\n26\r\n>>>...},DirectByteBuffer@...{<<<event: put\ndata:{...rty':'value'}\n\n>>>...}]

कहां
"\r\n26\r\n" - संदेश की लंबाई का एक HEX प्रतिनिधित्व है
"ईवेंट: put\nडेटा:{...rty':'value'}\n\n" - वास्तव में भेजा गया संदेश

मैं लंबाई हस्तांतरण कैसे बंद कर सकता हूं?

कोड:

public class TestCorruptedWrites {

    private static Server server = null;
    private final static int port = 8089;
    private final static String endpoint = "/test";
    static String message = "event: put\ndata:{'property':'value'}\n\n";

    private static void sleep(int millis){
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @BeforeClass
    public static void initMockServer() throws Exception {
        System.out.println(message.length());
        final ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
        contextHandler.addServlet(new ServletHolder(new HttpServlet() {
            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                resp.setCharacterEncoding(StandardCharsets.UTF_8.name());
                resp.flushBuffer();

                Writer writer = resp.getWriter();
                while (true) {
                    writer.write(message);
                    writer.flush();
                    sleep(300);
                }
            }
        }), endpoint);
        contextHandler.setContextPath("/");

        server = new Server(new QueuedThreadPool(50, 10));
        ServerConnector connector = new ServerConnector(server, new HttpConnectionFactory());
        connector.setPort(port);
        server.addConnector(connector);
        server.setHandler(contextHandler);
        server.start();
    }

    @Test
    public void testClient() throws InterruptedException, IOException {
        InternalLoggerFactory.setDefaultFactory(new Slf4JLoggerFactory());

        final Bootstrap bootstrap = new Bootstrap();
        final URI uri = URI.create("http://localhost:" + port + endpoint);

        bootstrap
                .group(new NioEventLoopGroup())
                .channel(NioSocketChannel.class)
                .remoteAddress(new InetSocketAddress(uri.getHost(), uri.getPort()))
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel channel) throws Exception {
                        ChannelPipeline pipeline = channel.pipeline();
                        pipeline.addLast("logger", new LoggingHandler(LogLevel.DEBUG));
                        pipeline.addLast("line", new DelimiterBasedFrameDecoder(Integer.MAX_VALUE, Delimiters.lineDelimiter()));
                        pipeline.addLast("string", new StringDecoder());
                        pipeline.addLast("encoder", new HttpRequestEncoder());
                        pipeline.addLast("log", new SimpleChannelInboundHandler<String>(){
                            @Override
                            protected void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception {
                                System.out.println(" ---> " + msg);
                            }
                            @Override
                            public void channelActive(ChannelHandlerContext context) {
                                System.out.println("active!");
                                HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uri.toString());
                                request.headers().add(HttpHeaders.Names.ACCEPT, "text/event-stream");
                                request.headers().add(HttpHeaders.Names.HOST, uri.getHost());
                                request.headers().add(HttpHeaders.Names.ORIGIN, "http://" + uri.getHost());
                                context.channel().writeAndFlush(request);
                            }
                        });
                    }
                })
                .connect();
        Thread.sleep(500_000);
    }
}

निर्भरताएँ:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.test</groupId>
  <artifactId>test</artifactId>
  <version>1.0-SNAPSHOT</version>

  <dependencies>

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.2</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.0.9</version>
    </dependency>

    <dependency>
      <groupId>io.netty</groupId>
      <artifactId>netty-all</artifactId>
      <version>5.0.0.Alpha1</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
    </dependency>
    <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-servlet</artifactId>
      <version>9.4.2.v20170220</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>

</project>
1
Silk0vsky 21 मार्च 2017, 17:23

1 उत्तर

सबसे बढ़िया उत्तर

वह मानक HTTP/1.1 चंकिंग ट्रांसफर एन्कोडिंग है जिसे आप देख रहे हैं।

चंकिंग तब होती है जब आपके पास Content-Length हेडर के बिना कोई प्रतिक्रिया होती है, और कनेक्शन लगातार बने रहना है (प्रति HTTP / 1.1 कल्पना)।

यदि आपके पास HTTP/1.1 क्लाइंट है, और सर्वर साइड पर Content-Length हेडर सेट नहीं कर सकते हैं, तो Connection: close अनुरोध और/या प्रतिक्रिया शीर्षलेख सेट करने पर विचार करें, क्योंकि यह लगातार कनेक्शन मोड को रद्द कर देगा जो ट्रिगर करता है खंडित स्थानांतरण एन्कोडिंग।

सलाह: चंकड ट्रांसफर एन्कोडिंग का समर्थन करना स्मार्ट होगा, जैसा कि आप देख सकते हैं कि किसी भी संख्या में स्थानों (यहां तक ​​​​कि प्रॉक्सी!)

1
Joakim Erdfelt 22 मार्च 2017, 00:43