【问题标题】:Why do my server and client disconnect on server activity start?为什么我的服务器和客户端在服务器活动开始时断开连接?
【发布时间】:2020-03-14 16:10:42
【问题描述】:

这里的想法是通过本地网络建立socket 连接,发送一些数据,然后立即关闭连接。唯一应该保持运行的是serversocket。到目前为止,一切都按预期进行,除了一件事:

当启动 serversocket 的 Activity 使用后退按钮关闭然后重新打开时,从客户端发送的数据不再发送到 serversocket

DMActivity:

public class DMActivity extends AppCompatActivity {

    String ipAddress;
    boolean dmListenRunning = false;
    DMListen dmListen = new DMListen();
    Thread dmListenThread;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dm);

        if (!(dmListenRunning)) {
            dmListenThread = new Thread(dmListen);
            dmListenRunning = true;

            dmListenThread.start();
        }
    }

    @Override
    public void onBackPressed()
    {
        try {
            dmListen.KillThread(true);
            dmListenThread.interrupt();
        }

        catch (Exception e)
        {
            Log.i("LOG", e.toString());
        }

        finish();
    }
}

DM监听:

public class DMListen implements Runnable {

    ServerSocket serverSocket;
    boolean started = false;
    boolean closeSockets = false;
    boolean killed = false;

    public void run() {
        ReceivePlayerData();
    }

    public void ReceivePlayerData() {
        try {
            while (!(Thread.interrupted())) {
                if (!(started)) {
                    int port = 8080;
                    serverSocket = new ServerSocket(port);
                    started = true;
                }

                Socket clientSocket = serverSocket.accept();
                DataInputStream dataIn = new DataInputStream(clientSocket.getInputStream());
                String name;
                int init;

                name = dataIn.readUTF();
                init = dataIn.readInt();
                dataIn.close();
                clientSocket.close();
            }
        }

catch (Exception e) {
              Log.i("LOG", e.toString();
        }

        if(killed)
        {
            try {
                serverSocket.close();

                if (Thread.currentThread().isInterrupted())
                {
                    try {
                        Thread.currentThread().join();
                    }

                    catch (Exception e)
                    {
                        Log.i("LOG", e.toString());
                    }
                }
            }

            catch(IOException e)
            {
                Log.i("LOG", e.toString());
            }
        }
    }

    public void KillThread(boolean k)
    {
        boolean killed = k;
    }
}

玩家活动:

public class PlayerActivity extends AppCompatActivity {

    EditText hostIPBox;
    Button submit;
    String hostIPString;
    InetAddress hostIP;
    boolean denied = false;
    boolean started = false;
    PlayerConnect playerConnect;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_player);

        hostIPBox = (EditText) findViewById(R.id.ipaddress);
        hostIPBox.setRawInputType(Configuration.KEYBOARD_12KEY);
        hostIPBox.setSingleLine();
        submit = (Button) findViewById(R.id.submit);

        submit.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                hostIPString = hostIPBox.getText().toString();

                try {
                        if (!(hostIPString.equals(""))) {
                            hostIP = InetAddress.getByName(hostIPString);
                            if(!(started)) {
                                playerConnect = new PlayerConnect();
                                playerConnect.SetHostIP(hostIP);
                                denied = playerConnect.GetDenied();
                                started = true;
                            }

                            else {
                                playerConnect.SetHostIP(hostIP);
                                denied = playerConnect.GetDenied();
                            }


                            if (denied)
                            {
                                started = false;
                            }

                            else
                            {
                                new Thread(playerConnect).start();
                            }
                        }
                    }

                    catch (Exception e) {
                        Log.e("LOG", e.toString());
                    }
                }
        });
    }
}

PlayerConnect:

public class PlayerConnect implements Runnable {

    InetAddress hostIP;
    boolean closeSockets = false;
    boolean denied = false;

    public void run() {
            SendPlayerData(hostIP, playerName, playerInitiative);
    }

    private void SendPlayerData(InetAddress IP, String name, int init) {
        try {
            int port = 8080;
            Socket socket = new Socket();
            socket.connect(new InetSocketAddress(IP, port), 3000);
            DataOutputStream output = new DataOutputStream(socket.getOutputStream());

            if (socket.isConnected())
            {
                output.writeUTF(name);
                output.writeInt(init);
                output.close();
                socket.close();
            }

            if (closeSockets) {
                output.close();
                socket.close();
                closeSockets = false;
            }
        }

        catch (Exception e) {
            denied = true;
    Log.i("LOG", e.printStackTrace());
        }
    }

    public void SetHostIP(InetAddress host)
    {
        hostIP = host;
    }

    public boolean GetDenied()
    {
        return denied;
    }
}

【问题讨论】:

  • 而不是这个catch (Exception e) { denied = true; }打印实际的异常e.printStackTrace();
  • 我更新了它并取出了所有不是套接字或线程部分的东西,因为我知道这就是问题所在。其他一切都只是在活动中移动数据。我添加了printStackTrace(),但denied = true 用于确保用户被告知连接失败,以及允许失败的连接在他们再次按下提交时再次尝试。
  • 我认为我遇到的一个问题是事情实际上并没有失败/捕获。我怀疑我处理线程的方式可能是错误的,或者PlayerActivity 类使用PlayerConnect 类的方式是错误的。

标签: java android multithreading networking


【解决方案1】:

您应该使用 Service 来处理套接字连接。 Activity 生命周期不会有问题。

【讨论】:

  • 在我了解服务的时候,我基本上已经完成了这个项目(这是我的第一个 android 项目)。我把它弄乱了一点,但无法让它工作。服务仍然可能是我切换到的东西,这取决于我用我目前使用的方法解决这个问题的地方。我需要serversocket 在 2 个活动之间切换时继续工作,但如果用户按下后退按钮则停止(即返回您选择要做什么的“开始活动”。此处未包含代码,因为它只启动其他活动,没有任何影响)
  • 是的,我认为,Service 是您唯一的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-17
  • 2014-11-04
  • 1970-01-01
  • 1970-01-01
  • 2013-03-31
  • 1970-01-01
相关资源
最近更新 更多