【问题标题】:Java Socket : java.net.SocketTimeoutException: Read timed outJava Socket:java.net.SocketTimeoutException:读取超时
【发布时间】:2016-05-19 11:48:39
【问题描述】:

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

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

这是服务类:

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') {

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

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

【问题讨论】:

    标签: java sockets timeout


    【解决方案1】:

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

    您的回复不以\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() 的每次调用都会从网络返回一个新字节。您应该在每个 while 循环中调用一次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();
    

    【讨论】:

    • 感谢您的回答。你说得对。但问题依然存在。您是否发现其他任何可能是我的问题的根源?
    • 我添加了一个名为“客户端读取响应错误”的段落,其中包含另一个错误
    • 是的,我同意这样更好。然而仍然不能解决问题。我注意到我首先得到了超时,然后才在控制台中打印“这个虚拟文本被发送到打印服务器”。
    • 从客户端写完字节后能不能调用clientSocket.shutdownOutput();
    • 同样的结果。您不认为问题出在我尝试从服务器发送消息的方式上吗?我不确定我是否正确使用了这个 PrintWriter.write 方法。
    猜你喜欢
    • 2011-04-04
    • 2014-03-07
    • 2023-03-11
    • 2012-09-06
    • 2012-10-24
    • 2011-10-03
    • 2021-12-11
    • 1970-01-01
    • 2020-01-19
    相关资源
    最近更新 更多