java - 使用打洞通过 TCP 套接字在 android 中通信时出现连接拒绝错误

标签 java android sockets tcp

我正在开发一个 android 应用程序,它必须在两部手机之间进行实时通信。两部手机上都运行着一个客户端和服务器,我有一个中央服务器,每个服务器的公共(public) IP 和端口都与之交换。两部手机都在监听中央服务器以获取通知。

假设两部手机都通过中央服务器接收彼此的公共(public) ip 和端口,然后在每部手机上我启动客户端,然后启动服务器(这是因为,它以其他顺序失败,因为我正在打洞punching 我使用相同的端口进行监听和发送)。

下面是我启动服务端和客户端的方式

socket=new Socket();
try {
    socket.setReuseAddress(true);
} catch (SocketException e) {
    e.printStackTrace();
}
try {
    socket.bind(new InetSocketAddress(<Port of this phone>));
} catch (IOException e) {
e.printStackTrace();
}
ClientThread clientThread=new ClientThread(<IP of the other phone>,<Port of the other phone>,socket);
clientThread.execute();

Thread serverThread = new Thread(new ServerThread(<IP of this phone>,<Port of this phone>));
serverThread.start();

这是我服务器的代码

public class ServerThread implements Runnable {

private String serverIP;
private int serverPort;
private ServerSocket serverSocket;

public ServerThread(String serverIP,int serverPort){
    this.serverIP=serverIP;
    this.serverPort=serverPort;
}


public void run() {
    try {
            serverSocket = new ServerSocket();
            serverSocket.setReuseAddress(true);
            serverSocket.bind(new InetSocketAddress(serverPort));
             while (true) {
                // listen for incoming clients
                Socket client = serverSocket.accept();
                Log.d("serverstatus","Connected :)");
                if(connected)
                //then pass messages
                }
         }
         catch (Exception e) {
        Log.d("serverstatus","Error");
        e.printStackTrace();
         }
  }

这是我的客户代码

public class ClientThread extends AsyncTask<String,String,String>{
private String serverIP;
private int serverPort;
private Socket socket;

public ClientThread(String serverip,int serverport,Socket mySocket)
{
    serverIP=serverip;
    serverPort=serverport;
    socket=mySocket;
}

@Override
protected String doInBackground(String... arg0) {
    try {
        while(true)
        {
            socket.connect(new InetSocketAddress(serverIP, serverPort));
            if(socket.isConnected())
            {
             //pass messages
            }
        }
        }
       catch (Exception e) {
        Log.d("clientstatus","Error");
        e.printStackTrace();
        //try again
        ClientThread clientThread=new ClientThread(serverIP,serverPort,socket);
        clientThread.execute();
       }
   }
}     

预期的是,在从 phone1 到 phone2 的第一次连接尝试失败后(因为 phone2 的端口尚未打开),phone1 的端口变为打开(因为对 phone2 的请求)然后当 phone 2 尝试与 phone1 通信时,它成功了,因为 phone1 的端口现在打开了,phone2 的端口也打开了(因为 phone2 对 phone1 的请求)。

每次我尝试连接时它仍然显示连接被拒绝,然后抛出“套接字关闭”异常。

我做错了什么,谁能帮我解决这个问题。

最佳答案

我在 OSx 和 iOS 上尝试过类似的方法。我在服务器端有一个非常简单的 C 代码监听传入连接,它捕获手机的 ip 和端口号,比如 172.39.33.23:44392(基本上即使你的手机连接到 wifi 路由器,我也能够从另一台设备向此端口发送数据)。但是,您应该尝试使用 UDP 将数据发送到使用数据报 (Java) 捕获的 ip 和端口,而不是 tcp。

  public void sendUdpData()
  {

      String phone1Ip = "172.39.33.23";
      int phone1Port = 44392;

      try 
      {
          String commandString =  "Send this data";
          byte[] commnadByte = commandString.getBytes();
          DatagramPacket datagramPacket = new DatagramPacket(commnadByte, commnadByte.length,InetAddress.getByName(phone1Ip),phone1Port);
          DatagramSocket datagramSocket=  new DatagramSocket(phone1Port);
          datagramSocket.send(datagramPacket);
          datagramSocket.close();
      } 
      catch (UnknownHostException e1) 
      {

      }
      catch (SocketException e1) 
      {

      }
      catch (IOException e1) 
      {

      }
  }

关于java - 使用打洞通过 TCP 套接字在 android 中通信时出现连接拒绝错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26191346/

相关文章:

android - RecyclerView 平滑滚动

c# - Socket.*Async 方法是线程化的吗?

java - Android Studio 错误无法识别的窗口套接字

java - 在没有ORM的情况下在sql中映射一对多的方法

Java线程操作,并行编程

java - Swing - 计时器不按时间间隔触发事件

android - 如何通过 ViewModel 从 Fragment 观察 Repository LiveData

javax 验证约束在 Spring Boot 中不起作用

java - 在 RecyclerView 滚动中使用 Switch

c - 简单的套接字库需要一些检查