Android:Socket - java.net.SocketException:sendto失败:EPIPE(管道破裂)

12
我试图使用socket与服务器建立连接。如下所示,连接管道已中断并出现了异常。

我试图使用socket与服务器建立连接。如下所示,连接管道已中断并出现了异常。

01-31 14:47:16.536: W/System.err(27255): java.net.SocketException: sendto failed: EPIPE (Broken pipe)
01-31 14:47:16.550: W/System.err(27255):    at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:496)
01-31 14:47:16.550: W/System.err(27255):    at libcore.io.IoBridge.sendto(IoBridge.java:465)
01-31 14:47:16.550: W/System.err(27255):    at java.net.PlainSocketImpl.write(PlainSocketImpl.java:507)
01-31 14:47:16.550: W/System.err(27255):    at java.net.PlainSocketImpl.access$100(PlainSocketImpl.java:46)
01-31 14:47:16.664: W/NetworkManagementSocketTagger(24437): setKernelCountSet(10021, 1) failed with errno -2
01-31 14:47:16.684: W/System.err(27255):    at java.net.PlainSocketImpl$PlainSocketOutputStream.write(PlainSocketImpl.java:269)
01-31 14:47:16.693: W/System.err(27255):    at java.io.DataOutputStream.write(DataOutputStream.java:98)
01-31 14:47:16.693: W/System.err(27255):    at java.io.OutputStream.write(OutputStream.java:82)
01-31 14:47:16.693: W/System.err(27255):    at com.x.x.y.sendRec(y.java:460)
01-31 14:47:16.693: W/System.err(27255):    at com.x.x.y.access$0(y.java:384)
01-31 14:47:16.693: W/System.err(27255):    at com.x.x.y$2.run(y.java:363)
01-31 14:47:16.693: W/System.err(27255):    at java.lang.Thread.run(Thread.java:856)
01-31 14:47:16.693: W/System.err(27255): Caused by: libcore.io.ErrnoException: sendto failed: EPIPE (Broken pipe)
01-31 14:47:16.693: W/System.err(27255):    at libcore.io.Posix.sendtoBytes(Native Method)
01-31 14:47:16.693: W/System.err(27255):    at libcore.io.Posix.sendto(Posix.java:146)
01-31 14:47:16.693: W/System.err(27255):    at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:177)
01-31 14:47:16.693: W/System.err(27255):    at libcore.io.IoBridge.sendto(IoBridge.java:463)

这里是代码,而且在这一行 outStreamRec.write(bData); 抛出异常。

    try {
        port = 86;
        byterecv = new byte[1040];
        clientRec = new Socket();
        clientRec.connect(new InetSocketAddress("192.168.1.36", port));
        System.out.println("Just connected to " + clientRec.getRemoteSocketAddress());
    } catch (IOException e2) {
        // TODO Auto-generated catch block
        e2.printStackTrace();
    }
    while (true) {
        try {
            System.out.println("Connecting to " + ServerUrl.url + " on port " + port);              
            OutputStream outToServerRec = clientRec.getOutputStream();
            DataOutputStream outStreamRec = new DataOutputStream(outToServerRec);

            outStreamRec.write(bData);

            InputStream inFromServerPlay = clientRec.getInputStream();
            DataInputStream inStreamPlay = new DataInputStream(inFromServerPlay);
            while ((lstream = inStreamPlay.read(byterecv)) != -1) {
                System.out.println("startrec bytearray -- " + byterecv.length);
                bos1.write(byterecv, 0, lstream);
            }                
            if (stopcall == true) {
                clientRec.close();
                break;
            }

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

注意:如果我立即关闭套接字连接,则一切正常。但是我想在手动关闭套接字连接之前保持连接保持活动状态。当停止按钮被点击时,我会关闭连接。

我已经搜索了网络,但没有找到解决方法。


这个在主(UI)线程上吗? - keyser
不,它不在主 UI 线程上。 - Rahul Baradia
4个回答

11

在您向对等方写入数据时,该对等方关闭了连接。这通常意味着您发送了一些它无法理解的内容。也许它是一个 HTTP 服务器?或者是您在客户端代码中尚未实现的其他协议?


2
但我能做些什么来纠正这个问题呢?这是这里的重要问题。 - Sreekanth Karumanaghat
2
@SreekanthKarumanaghat 在对等方关闭连接后不要再写入连接! 这表明您的应用程序协议存在错误。可能是对等方在不应该关闭时关闭了,或者您在不应该发送时发送了数据。 - user207421
你的意思是说,“peer关闭了连接”指的是“服务器关闭了连接”吗? - Eido95
1
@Eido95 不,我没有。我的意思是我说的话。我的意思是同行。一旦建立了TCP连接,继续考虑服务器和客户端是毫无意义的。它们彼此都是同行。如果这一端是客户端,则谈论服务器只会使答案的大小增加三倍,或者如果这一端是服务器,则谈论客户端只会使答案的大小增加三倍。这并不重要。重要的是关闭的是同行,而不是本地端。 - user207421

3

我的建议是:我们遇到了同样的问题(BROKEN EPIPE),通过查看 Fiddler(或 Charls、WireShark 或其他代理调试器/监听器等)我们注意到根本没有发送任何请求。

原因是我们添加了错误值的 "Content-Length" 头。


你可能根本不应该添加它。也许库已经为你做了这件事。HttpURLConnection肯定会这样做。 - user207421
1
我已经与编写此代码的开发人员进行了确认,他说如果他记得正确的话,问题在于当使用 setChunkedStreamingMode(x) 时没有添加头部(因为它是被禁止的,请参见 Wikipedia),但是服务器使用的 MS-WCF 绑定要求添加头部,即使启用了分块流。 - Felix
1
那么这就是MS-WCF中的一个错误。 - user207421

0

我在三星平板电脑(型号为 GT-P5113,Android 版本为 4.2.2)上遇到了这个问题,但是在其他设备(Nexus 4/5/7)上应用程序运行良好。

Libcore/io/IoBridge.java 文件中的代码如下:

public static int sendto(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetAddress inetAddress, int port) throws IOException {
    boolean isDatagram = (inetAddress != null);
    if (!isDatagram && byteCount <= 0) {
        return 0;
    }
    int result;
    try {
        result = Libcore.os.sendto(fd, bytes, byteOffset, byteCount, flags, inetAddress, port);
    } catch (ErrnoException errnoException) {
        result = maybeThrowAfterSendto(isDatagram, errnoException);
    }
    return result;
}

虽然Libcore.os.sendto()是本地调用。

也许再试一次是一个不错的解决方法。


这不是应用程序错误。这是一个应用程序协议错误。在重试之间,应用程序代码不会改变。 - user207421

0
我也遇到过这种情况,原因很傻,就是设备上的互联网连接不正常。

检查一下你的互联网连接,这可能是问题所在。


1
从技术上讲,他是正确的。那些踩了这个评论的人肯定会在某个时候犯类似的愚蠢错误。 - CiriousJoker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接