Java Android套接字已连接,但无法写入

Java Android套接字已连接,但无法写入,java,android,sockets,networking,Java,Android,Sockets,Networking,我试图在我的应用程序中建立一些网络,但我遇到了一些问题。似乎我无法写入OutputStream对象。虽然我的服务器收到了连接,但它没有收到任何数据。我尝试过使用Writer、DataOutputStream等。似乎没有一个起作用。 我的应用程序使用异步任务,通过套接字对象和消息调用此对象。套接字对象已用于使用setStreams方法初始化后设置流。 有人能试着找出问题吗?我会非常感激的 public class NetworkingUtils { private OutputStream out

我试图在我的应用程序中建立一些网络,但我遇到了一些问题。似乎我无法写入OutputStream对象。虽然我的服务器收到了连接,但它没有收到任何数据。我尝试过使用Writer、DataOutputStream等。似乎没有一个起作用。 我的应用程序使用异步任务,通过套接字对象和消息调用此对象。套接字对象已用于使用setStreams方法初始化后设置流。 有人能试着找出问题吗?我会非常感激的

public class NetworkingUtils {
private OutputStream out = null;
private InputStream in = null;

//set streams
public void setStreams(Socket sock){
    if (sock.isConnected()) {
        try {
            this.out = (OutputStream) sock.getOutputStream();
            this.in = (InputStream) sock.getInputStream();
        } catch (Throwable e) {
            Log.d("SOCKET", "FAILED TO SET STREAMS");
            e.printStackTrace();
        }
    }
}

//send \n terminated messages to pre defined socket
public void sendMessage(Socket sock, String message) throws Throwable {
    if (sock.isConnected()) {
        try {
            this.out.write(message.getBytes());
            Log.d("SOCKET","WRITING COMPLETE. " + message);
        } catch (Throwable e) {
            throw e;
        }
    }
}

public String recvMessage(Socket sock) throws Throwable {
    //receives \n terminated message from pre defined socket
    String answer = null;
    if (sock.isConnected()){
        try{
            answer = this.convertStreamToString(this.in);
            Log.d("SOCKET","READING COMPLETE");
        }
        catch (Throwable e){
            Log.d("socket",e.getLocalizedMessage());
            throw e;
        }
    }
    else{
        Log.d("socket","is not connected!!!");
    }
    if (answer.length() == 0){
        //empty string answer from server
        throw new IOException();
    }
    else {
        return answer;
    }

}

private String convertStreamToString(java.io.InputStream is) {
    java.util.Scanner s = null;
    try{
     s = new java.util.Scanner(is).useDelimiter("\r\n");}
    catch (Throwable e){
        e.printStackTrace();
    }
    return s.hasNext() ? s.next() : "";
}

}

我只能看到一个可能导致此问题的客户端。。。我对此表示怀疑。也就是说:试试这个,以防万一会有不同,但我认为不会

  this.out.write(message.getBytes());
  Log.d("SOCKET","WRITING COMPLETE. " + message);
潜在的问题是,如果out是一个缓冲流,那么写操作可能只会导致将字节写入缓冲区。可能需要调用this.out.flush以推送到服务器

但我怀疑它是否有用,因为据我所知,套接字输出流在Java中没有缓冲。我认为真正的问题更有可能出现在服务器端

如果您无法确定问题发生在哪一方,我建议您尝试在服务器端使用网络监视/数据包嗅探工具来检查数据是否到达服务器主机

当我引起你的注意时,你的异常代码非常非常糟糕

不要将方法声明为throws Throwable或throws Exception。基本上就是说这个方法可能会抛出任何异常,我不会告诉你是哪一个。当您这样做时,调用方代码必须处理任何异常,这基本上不可能智能地完成

您应该做的是将该方法声明为抛出代码可以抛出的已检查异常。例如,在您的情况下,IOException可能就足够了

捕获异常,记录它,然后重新显示它不是一个好主意。为什么?因为在堆栈的后面,可能还有其他方法会看到异常。他们不知道是否已经记录了异常。因此,他们应该记录它,可能会导致相同问题的重复日志事件,或者不可能导致异常被取消跟踪

不要在没有消息的情况下抛出异常:

      throw new IOException();
它是懒惰的。您应该始终包含一条简单的消息,至少可以grep'd或google搜索

此外,不需要对Socket.isConnected进行测试。根据javadoc:

返回:如果套接字成功连接到服务器,则返回true

注意:关闭套接字不会清除其连接状态,这意味着 对于关闭的套接字,此方法将返回true。请参阅isClosed if 它在关闭之前已成功连接

因此,反复测试连接是徒劳的。如果它返回true一次,那么从那时起它将始终返回true


即使是setStreams中的初始断开连接测试也值得怀疑。我只需调用getInputStream而不进行测试,如果套接字处于错误状态,则依赖套接字API引发IOException。

我只能看到一个客户端可能导致此问题。。。我对此表示怀疑。也就是说:试试这个,以防万一会有不同,但我认为不会

  this.out.write(message.getBytes());
  Log.d("SOCKET","WRITING COMPLETE. " + message);
潜在的问题是,如果out是一个缓冲流,那么写操作可能只会导致将字节写入缓冲区。可能需要调用this.out.flush以推送到服务器

但我怀疑它是否有用,因为据我所知,套接字输出流在Java中没有缓冲。我认为真正的问题更有可能出现在服务器端

如果您无法确定问题发生在哪一方,我建议您尝试在服务器端使用网络监视/数据包嗅探工具来检查数据是否到达服务器主机

当我引起你的注意时,你的异常代码非常非常糟糕

不要将方法声明为throws Throwable或throws Exception。基本上就是说这个方法可能会抛出任何异常,我不会告诉你是哪一个。当您这样做时,调用方代码必须处理任何异常,这基本上不可能智能地完成

您应该做的是将该方法声明为抛出代码可以抛出的已检查异常。例如,在您的情况下,IOException可能就足够了

捕获异常,记录它,然后重新显示它不是一个好主意。为什么?因为在堆栈的后面,可能还有其他方法会看到异常。他们不知道是否已经记录了异常。因此,他们应该记录它,可能会导致相同问题的重复日志事件,或者不可能导致异常被取消跟踪

不要在没有消息的情况下抛出异常:

      throw new IOException();
它是懒惰的。您应该始终包括一个 简单的信息,至少可以grep'd或google搜索

此外,不需要对Socket.isConnected进行测试。根据javadoc:

返回:如果套接字成功连接到服务器,则返回true

注意:关闭套接字不会清除其连接状态,这意味着 对于关闭的套接字,此方法将返回true。请参阅isClosed if 它在关闭之前已成功连接

因此,反复测试连接是徒劳的。如果它返回true一次,那么从那时起它将始终返回true


即使是setStreams中的初始断开连接测试也值得怀疑。我只需调用getInputStream而不进行测试,如果套接字处于错误状态,则依赖套接字API引发IOException。

您实际上是在使用模糊的扫描仪读取行,但不是在写行。因此,扫描器将阻塞,直到行终止符或EOS到达


发送时需要附加一个行终止符。

使用这种模糊的扫描仪可以有效地读取行,但不能写入行。因此,扫描器将阻塞,直到行终止符或EOS到达


发送时需要附加一个行终止符。

断开连接的测试毫无意义。如果插座没有连接,你就不会有插座。它不会告诉您连接的当前状态。断开连接的测试是没有意义的。如果插座没有连接,你就不会有插座。它不会告诉您连接的当前状态。+1-是的,这是合理的。特别是如果该代码或类似代码在两侧使用。它在两侧以下线终止。+1-是,这是合理的。特别是如果此代码或类似代码在两侧都使用。它在两侧都以EOL终止。与“断开连接”混淆的是,人们使用它来测试连接状态,而它仅指示套接字的状态。当对等机断开连接时,它不会改变值。我根据您的建议修复了代码,并使用wireshark检查了网络流量。在端口上,我的应用程序和服务器工作没有数据包被捕获。我也试过这个。out.flush,没用。有什么明显的东西我遗漏了吗?@Talkopel-在这一点上,我开始怀疑奇怪的网络骗局。也许你应该写一个SSCCE并将其发布到Github或其他地方,以便人们可以查看、运行它等。谢谢@Stephen,这为我修复了它。与isConnected混淆的是,人们使用它来测试连接状态,而它只指示套接字的状态。当对等机断开连接时,它不会改变值。我根据您的建议修复了代码,并使用wireshark检查了网络流量。在端口上,我的应用程序和服务器工作没有数据包被捕获。我也试过这个。out.flush,没用。有什么明显的东西我遗漏了吗?@Talkopel-在这一点上,我开始怀疑奇怪的网络骗局。也许你应该写一个SSCCE并将其发布在Github或其他地方,以便人们可以查看、运行它等等。谢谢@Stephen,这为我修复了它。