简体   繁体   English

Java,收到奇怪的套接字异常:“管道损坏”和“操作超时”

[英]Java, Getting a weird Socket Exception: “Broken pipe” and “Operation timed out”

I have a client server application that has 16 threads (8 client, 8 server) and each has a TCP connection in a 1-1 matching (so 8 TCP streams). 我有一个客户端服务器应用程序,该应用程序具有16个线程(8个客户端,8个服务器),每个线程都有1-1匹配的TCP连接(因此有8个TCP流)。

I have the server sending X amount of random bytes then close. 我让服务器发送X数量的随机字节,然后关闭。 Meanwhile the client just reads X amount of data then closes. 同时,客户端仅读取X数量的数据,然后关闭。 X is predetermined. X是预定的。 I am also using dummynet for bandwidth throttling but I am leaving the pipe with plenty of bandwidth (100Mbps). 我也使用虚拟网络来限制带宽,但是我给管道留有足够的带宽(100Mbps)。 Sometimes it works fine, other times I get these exceptions. 有时工作正常,其他时候我得到了这些例外。 I am transferring 1GB spread evenly over all 8 connections in around 3.5 minutes. 我将在3.5分钟左右的时间内将所有8个连接平均分配1GB。

The client is throwing this exception: 客户端抛出此异常:

java.net.SocketException: Operation timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at miccbull.parralleltcp.client.StreamWorker.run(StreamWorker.java:43)

The server is throwing this exception: 服务器抛出此异常:

java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:124)
at miccbull.parralleltcp.server.TransmissionWorker.run(TransmissionWorker.java:51)

Server Code: 服务器代码:

public void run() {

    OutputStream os = null;

    try {
        socket = sSocket.accept();
        os = socket.getOutputStream();
    } catch (IOException e2) {
        e2.printStackTrace();
    }

    //send the data
    for(int i = 0; i < Server.TRANSMISSIONS; i++){
        System.out.println(sSocket.getLocalPort() + " sending set " + (i+1) + " of " + Server.TRANSMISSIONS);

        try {
            os.write(new byte[Server.FILE_SIZE/Server.numStreams/Server.TRANSMISSIONS]);
            os.flush();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Closing server (at write bytes) with socket id: " + sSocket.getLocalPort());
        } 
    }

    System.out.println("Worker " + sSocket.getLocalPort() + " done");

    //close the socket
    try {
        socket.close();
        sSocket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

Client Code: 客户代码:

    public void run(){

    byte[] bytes = new byte[1024];  //number of bytes to read per client stream
    InputStream is = null;

    //connect to server
    try {
        connectionSocket = new Socket("localhost", id);
        is = connectionSocket.getInputStream();
    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }


    //read file from server
    int value = 0;
    int bytesRead = 0;
    try {

        while(bytesRead < (Client.FILE_SIZE/Client.NUM_STREAMS)){
            value = is.read(bytes, 0, 1024);
            if(value == -1){
                System.out.println("******************************** Read is -1 for client " + id);
            }
            else if(value == 0){
                System.out.println("******************************** Read is 0 for client " + id);
            }
            bytesRead += value;
        }
    } catch (IOException e) {
        System.out.println("**** Exception in read in client " + id + " and value value was: " + value);
        if(bytesRead == (Client.FILE_SIZE/Client.NUM_STREAMS)){
            System.out.println("************ NOT ACTUALLY BAD" + id);
        }
        e.printStackTrace();
    }

    //Finished download
    Client.workerDone();
    System.out.println("Worker " + id + " done received " + bytesRead);

What causes these exceptions? 是什么导致这些异常?

您的客户端永远不会停止读取,因为您不测试返回的<0的read()。

Here's what I see in your code: 这是我在您的代码中看到的:

  1. I have verified that every call to both socket.getOutputStream() and socket.getInputStream() returns a different stream associated with the socket. 我已经验证了对socket.getOutputStream()socket.getInputStream()每次调用都会返回与套接字相关联的不同流。 You should call them each once per socket and put the result in a local variable. 您应该为每个套接字分别调用一次,并将结果放入局部变量中。

     OutputStream outputStream = socket.getOutputStream(); // send the data for (int i = 0; i < 10; i++) { .... outputStream.write(...); 
  2. There are a number of places where you should return from your run() method but I suspect you knew that. 在很多地方都应该从run()方法返回,但是我怀疑您知道这一点。

  3. You are not checking the return value from read() to see if it returns -1 on EOF. 您没有检查read()的返回值以查看它是否在EOF上返回-1。 You should not just make the assumption you are getting the correct number of bytes. 您不应该只是假设您获得了正确的字节数。

  4. I assume you are writing blocks of null characters for a reason. 我假设您出于某种原因在编写空字符块。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM