/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.camel.test.tcp; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketTimeoutException; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Various tests used to validate the behaviour of Java Sockets. * * The tests were for experimentation and don't have any assertions in them - JUnit * provided a convenient framework to explore this behaviour. These tests shouldn't be * run with a normal build since they don't have any assertions and don't validate any * results. * * NOTE: This class may be deleted in the future */ @Ignore(value = "Tests validating Java Socket behaviours") public class JavaSocketTests { Logger log = LoggerFactory.getLogger(this.getClass()); Socket clientSocket; ServerSocket serverSocket; int messageCount = 10; @Before public void setUp() throws Exception { serverSocket = new ServerSocket(0); } @After public void tearDown() throws Exception { if (null != clientSocket) { clientSocket.close(); } if (null != serverSocket) { serverSocket.close(); } } @Test public void testSocketReadOnClosedConnection() throws Exception { final Thread acceptThread = new Thread() { Logger log = LoggerFactory.getLogger("acceptThread"); @Override public void run() { boolean running = true; try { Socket echoSocket = serverSocket.accept(); log.info("Accepted connection: {}", echoSocket.getInetAddress()); echoSocket.setSoTimeout(2000); while (echoSocket.isConnected() && !echoSocket.isClosed()) { StringBuilder responseBuilder = new StringBuilder(500); InputStream reader = echoSocket.getInputStream(); OutputStream writer = echoSocket.getOutputStream(); do { int readByte = -1; int available = -1; try { available = reader.available(); log.info("InputStream.available returned {}", available); readByte = reader.read(); log.trace("Processing byte: {}", readByte); switch (readByte) { case -1: if (echoSocket.isConnected() && !echoSocket.isClosed()) { log.info("Available returned {}", reader.available()); log.warn("Socket claims to still be open, but END_OF_STREAM received - closing echoSocket"); try { echoSocket.close(); } catch (Exception ex) { log.warn("Exception encountered closing echoSocket after END_OF_STREAM received", ex); } } running = false; break; case 10: log.info("Complete Message - Sending Response"); byte[] response = responseBuilder.toString().getBytes(); responseBuilder.setLength(0); writer.write(response, 0, response.length); writer.write('\n'); break; default: responseBuilder.append((char) readByte); } } catch (SocketTimeoutException timeoutEx) { log.info("Timeout reading data - available returned {}", available); } } while (echoSocket.isConnected() && !echoSocket.isClosed()); } } catch (IOException ioEx) { log.error("IOException in run method", ioEx); } finally { try { serverSocket.close(); } catch (IOException ioEx) { log.error("Exception encountered closing server socket", ioEx); } } log.info("Finished processing connection"); } }; acceptThread.start(); clientSocket = new Socket(); clientSocket.setSoTimeout(1000); clientSocket.connect(serverSocket.getLocalSocketAddress(), 10000); clientSocket.setTcpNoDelay(true); log.info("Begining message send loop "); byte[] message = "Hello World".getBytes(); BufferedReader reader; for (int i = 1; i <= messageCount; ++i) { reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); OutputStream writer = clientSocket.getOutputStream(); log.info("Sending payload"); writer.write(message, 0, message.length); writer.flush(); log.info("Sending terminator"); writer.write('\n'); writer.flush(); log.info("Received Response #{}: {}", i, reader.readLine()); Thread.sleep(1000); } log.info("Message send loop complete - closing connection"); // Javadoc for Socket says closing the InputStream will close the connection clientSocket.getInputStream().close(); if (!clientSocket.isClosed()) { log.warn("Closing input stream didn't close socket"); clientSocket.close(); } log.info("Sleeping ..."); Thread.sleep(5000); } }