Java Socket:java.net.SocketTimeoutException:读取超时

时间:2016-02-09 13:10:52

标签: java sockets timeout

嗨,我希望你们做得很好。

我目前正在尝试测试一个创建与打印服务器的套接字连接的服务类。

这是服务类:

public class PrintServiceImpl implements PrintService {
private static final Logger LOGGER = LoggerFactory.getLogger(PrintServiceImpl.class);

static final int TIMEOUT_MILLISECOND = 20000;

@Override
public boolean sendLabelToPrintServer(String hostname, int port, String labelData) {

    Socket clientSocket = null;
    DataOutputStream outToServer = null;
    Boolean successful;

    try {
        // open the connection to the printing server
        clientSocket = new Socket();
        clientSocket.connect(new InetSocketAddress(hostname, port), TIMEOUT_MILLISECOND);
        clientSocket.setSoTimeout(TIMEOUT_MILLISECOND);

        outToServer = new DataOutputStream(clientSocket.getOutputStream());

        // send data to print
        outToServer.writeBytes(labelData);

        BufferedReader input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(),
                StandardCharsets.UTF_8));

        // Read HTTP Request CHARACTER BY CHARACTER instead of line by line
        while ((char) input.read() != 0 && (char) input.read() != '\r') {
            LOGGER.debug("Getting print server answer.");
        }

        successful = true;
        LOGGER.debug("Label printed.");
    } catch (Exception e) {
        LOGGER.error("Printing failed.", e);
        successful = false;
    } finally {
        try {
            // close connection
            if (outToServer != null) {
                outToServer.close();
            }
            if (clientSocket != null) {
                clientSocket.close();
            }
        } catch (IOException e) {
            LOGGER.error("Exception while closing DataOutputStream/ClientSocket.", e);
        }
    }
    return successful;
}

这是我的考试班。如您所见,@ Before方法在新线程上实例化SocketServer。

public class PrintServiceImplTest {

private static final Logger LOGGER = LoggerFactory.getLogger(PrintServiceImplTest.class);

PrintServiceImpl whfPrintService = new PrintServiceImpl();

private static final String LOCALHOST = "localhost";
private static final int SERVER_PORT = 3000;
private static final String LABEL_TEXT = "This dummy text is sent to the print server";
private static final String RESPONSE = "Test Label printed correctly";
private ServerSocket server;
private Socket incommingSocket = null;

@Before
public void before() {
    Thread myThread = new Thread() {
        @Override
        public void run() {
            try {
                server = new ServerSocket(SERVER_PORT);
                incommingSocket = server.accept();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    };
    myThread.start();
}

@After
public void after() {
    try {
        incommingSocket.close();
        server.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Test
public void returnsTrueIfConnectionSuccessful() {

    BufferedReader reader = null;
    PrintWriter out = null;
    BufferedReader in = null;
    String line;

    whfPrintService.sendLabelToPrintServer(LOCALHOST, SERVER_PORT, LABEL_TEXT);

    try {

        in = new BufferedReader(new InputStreamReader(incommingSocket.getInputStream()));
        out = new PrintWriter(incommingSocket.getOutputStream());

        reader = new BufferedReader(new InputStreamReader(incommingSocket.getInputStream()));

        while ((line = reader.readLine()) != null) {
            System.out.println("line : " + line);
        }

        out.write(RESPONSE);
        out.flush();

        out.close();
        in.close();
        reader.close();

    } catch (IOException e) {
        e.printStackTrace();
    }
}

当我运行测试时,我得到一个SocketTimoutException。它发生在客户端从服务器读取响应时。这一行:

while ((char) input.read() != 0 && (char) input.read() != '\r') {

所以这意味着客户端没有收到回复。我的猜测是服务器没有发送正确的响应。

我错过了什么?提前谢谢你。

1 个答案:

答案 0 :(得分:0)

服务器不正确 - >客户端响应

您的回复不会以\0\r结尾。

private static final String RESPONSE = "Test Label printed correctly";

通过使用这些字符中的任何一个来结束响应,客户端将从循环中退出。

private static final String RESPONSE = "Test Label printed correctly\0";

客户端错误地读取响应

客户端使用以下代码读取响应:

while ((char) input.read() != 0 && (char) input.read() != '\r') {

每次调用input.read()都会从网络返回一个新字节。你应该每次循环调用input.read()一次,并在之后进行比较。

char c;
while (c = (char) input.read()) != -1) {
    if(c == 0 || c == '\r') {
        break;
    }
}

客户端到服务器消息没有正确的结尾

从客户端发送到服务器的消息没有结束,服务器会一直读取,直到套接字输入关闭,但客户端永远不会关闭套接字。

  // send data to print
   outToServer.writeBytes(labelData);

写完这些字节后,请拨打socket.shutdownOutput()向另一方发出文件结束信号。

  // send data to print
   outToServer.writeBytes(labelData);
  clientSocket.shutdownOutput();