4

Android アプリで大きな問題が発生しました。助けを求めたいと思います。

現在、ソケットを使用して Android Clientn-Server アプリを作成しています。私はインターネット上で多くのチュートリアルを見つけ、それらから自分のプロジェクトの基本を作成しました。ただし、すべてのチュートリアルは 1 つのメッセージ送信のみを対象としており、それだけです。もっと送る必要があるので、修正しようとしています。

これは、サーバーとクライアントを担当するコード フラグメントです。残りは現時点では重要ではありません。

サーバ:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        serverStatus = (TextView) findViewById(R.id.server_status);
        recivedMsg = (TextView)findViewById(R.id.rec_msg);

        SERVERIP = getLocalIpAddress();

        Thread fst = new Thread(new ServerThread());
        fst.start();
    }

    public class ServerThread implements Runnable {

        public void run() {
            try {
                if (SERVERIP != null) {
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            serverStatus.setText("Listening on IP: " + SERVERIP);
                        }
                    });
                    serverSocket = new ServerSocket(SERVERPORT);
                    while (true) {
                        // listen for incoming clients
                        Socket client = serverSocket.accept();
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                serverStatus.setText("Connected." + System.getProperty("line.separator"));
                            }
                        });

                        try {
                            line = null;
                            while (connected) {
                                BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
                                if((line = in.readLine())!=null)
                                {
                                    Log.d("ServerActivity", line);
                                    handler.post(new Runnable() {
                                        @Override
                                        public void run() {
                                            if(recivedMsg.equals("CLOSE"))
                                            {
                                                recivedMsg.append("CLOSE socket");
                                                connected = false;
                                            }
                                            else
                                            {
                                                recivedMsg.append("MSG: " + line + System.getProperty("line.separator"));
                                            }
                                            // do whatever you want to the front end
                                            // this is where you can be creative
                                        }
                                    });
                                }
                                else
                                {
                                    recivedMsg.append("empty" + System.getProperty("line.separator"));
                                }
                            }
                            break;
                        } catch (Exception e) {
                            handler.post(new Runnable() {
                                @Override
                                public void run() {
                                    serverStatus.setText("Oops. Connection interrupted. Please reconnect your phones.");
                                }
                            });
                            e.printStackTrace();
                        }
                    }
                } else {
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            serverStatus.setText("Couldn't detect internet connection.");
                        }
                    });
                }
            } catch (Exception e) {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        serverStatus.setText("Error");
                    }
                });
                e.printStackTrace();
            }
        }
    }

クライアント

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

        serverIp = (EditText) findViewById(R.id.server_ip);
        connectPhones = (Button) findViewById(R.id.connect_phones);

        sendField = (EditText) findViewById(R.id.send_field);
        sendMsg = (Button) findViewById(R.id.msg_send);

        connectPhones.setOnClickListener(connectListener);
        sendMsg.setOnClickListener(sendMessage);
    }

    @Override
    protected void onStop() {
         super.onStop();
         try {
                 BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
                 //send output msg
                 String outMsg = "CLOSE"; 
                 out.write(outMsg);
                 out.flush();
                 // make sure you close the socket upon exiting
                 s.close();
         } catch (IOException e) {
                 e.printStackTrace();
         }
    }

    private OnClickListener connectListener = new OnClickListener() {

        @Override
        public void onClick(View v) {
            serverIpAddress = serverIp.getText().toString();
            runTcpConnection();
            sendMessageToServer("Msg");
        }
    };

    private OnClickListener sendMessage = new OnClickListener() {

        @Override
        public void onClick(View v) {
            sendMessageToServer(sendField.getText().toString());
        }
    };

    private void runTcpConnection() {
        try {
            s = new Socket(serverIpAddress, SERVERPORT);
            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            //send output msg
            String outMsg = "TCP connecting to " + SERVERPORT + System.getProperty("line.separator"); 
            out.write(outMsg);
            out.flush();
            Log.i("TcpClient", "sent: " + outMsg);
            SystemClock.sleep(10);
            s.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    };

    public void sendMessageToServer(String str) {
        try {
                    s = new Socket(serverIpAddress, SERVERPORT);
                    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
                    //send output msg
                    String outMsg = str + System.getProperty("line.separator"); 
                    out.write(outMsg);
                    out.flush();
                    Log.i("TcpClient", "sent: " + outMsg);
                    s.close();
                } catch (UnknownHostException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    Log.d("", "hello222");
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    Log.d("", "hello4333");
                }

            }

今のところ、デバイスは正しく接続されています。さらに、最初の接続メッセージを送信しています ( のメッセージOnClickListener connectListener)。問題は、それを使用して別のメッセージを送信しようとしているときに、sendMessageToServerそれが不可能であることです。これらのメッセージは、クライアント アクティビティが破棄された後にのみ表示されます。

非常に興味深いのは、SystemClock.sleep(10);リスナーがいないとrunTcpConnection()奇妙な振る舞いをすることです。「接続済み」のみ。サーバーに表示されます。

メッセージを正常に送信できるようにするために何をしなければならないか教えてもらえますか?

編集: これは私が見つけたものです:

  • すべてが空 (null) よりも多くのメッセージを送信している接続で、2 つ目の接続エラーが表示された後に、電話を再接続してください
  • 接続中に s.close 行なしで複数のメッセージを送信している場合、sendMessageToServer1 つのメッセージのみが通過します。その後、エラーは表示されません。
  • メッセージ フォームrunTcpConnectionは常に表示されます (この関数に SystemClock.sleep(10) がない場合を除く)。

誰かが私のエラーを診断するのに役立つことを願っています。

4

1 に答える 1

2

ご覧のとおり、ユーザーがボタン送信をクリックするたびに新しいソケットを作成しますよね?
ユーザーが接続をクリックしたときに1回だけ初期化してから、send clickイベントで使用することをお勧めします(これはTCPであるため、ソケットの新しいインスタンスを作成するとサーバーに切断されます) 。したがって、 sendMessageToServerでこれらの行
削除する必要があります。:

s = new Socket(serverIpAddress, SERVERPORT);
s.close();

そしてrunTcpConnectionのこの行

s.close();

サーバーと通信したくないときはいつでもソケットを閉じる必要があります(オンストップは例です、またはアクティビティを変更するとき...)
また、BufferedWriterのインスタンスも1つだけ作成する必要があります。
この助けを願っています。

于 2012-06-10T16:00:36.153 に答える