Как исправить ошибку тайм-аута залпа, когда setRetryPolicy не решает ее? - PullRequest
0 голосов
/ 28 июня 2019

Я пытаюсь заставить мое приложение для Android иметь возможность записи в базу данных MySQL, которая работает на локальном хосте на моем компьютере, но я все еще получаю ошибку тайм-аута залпа.

Почти все решения этой проблемы при переполнении стека говорят об использовании stringRequest.setRetryPolicy. Я попробовал это, как вы можете видеть далее в коде, но, к сожалению, это не решило проблему. Мой телефон - Xiaomi Mi A1 под управлением Android версии 9. Я использую WAMP v3.1.7 с PHP 7.2, MySQL 5.7 и Apache 2.4.

//URL for adding user
public static final String URL_REGISTER = "http://192.168.0.18:3000/pom/add_user.php";

//URL for reading users table
public static final String URL_DB = "http://192.168.0.18/pom/get_all_users.php";

URL_REGISTER - это URL, который я пытаюсь использовать для этого запроса. Функция ниже - та, которая делает запрос. Это в отдельном классе.

  private void registerUser(final String fname, final String sname, final String phoneno, final String email, final String password){

    //tag used to cancel request
    String tag_string_req = "req_register";

    StringRequest strReq = new StringRequest(Request.Method.POST, AppConfig.URL_REGISTER,
            new Response.Listener<String>(){

                @Override
                public void onResponse(String response) {

                    try{

                        JSONObject jObj = new JSONObject(response);
                        boolean error = jObj.getBoolean("Error");
                        if(error){
                            String errorMsg = jObj.getString("error_msg");
                            Toast.makeText(getApplicationContext(), "Error occurred: " + errorMsg,
                                    Toast.LENGTH_LONG).show();
                        }

                        //Navigate to page that displays DB entries
                        Intent intent = new Intent(Registration.this, DBView.class);
                        startActivity(intent);

                    }catch(JSONException e) {
                        e.printStackTrace();
                    }
                }
            },
            new Response.ErrorListener(){

                @Override
                public void onErrorResponse(VolleyError error) {
                    if(error instanceof AuthFailureError){
                        Log.e(TAG, "Authorisation Failure Error: " + error.getMessage());
                        Toast.makeText(getApplicationContext(), "Registration Error: Authorisation Failure Error", Toast.LENGTH_LONG).show();
                    }else if(error instanceof NetworkError){
                        Log.e(TAG, "NetworkError: " + error.getMessage());
                        Toast.makeText(getApplicationContext(), "Registration Error: Network Error", Toast.LENGTH_LONG).show();
                    }else if(error instanceof ParseError){
                        Log.e(TAG, "Parse Error: " + error.getMessage());
                        Toast.makeText(getApplicationContext(), "Registration Error: Parse Error", Toast.LENGTH_LONG).show();
                    }else if(error instanceof ServerError){
                        Log.e(TAG, "Server Error: " + error.getMessage());
                        Toast.makeText(getApplicationContext(), "Registration Error: Server Error", Toast.LENGTH_LONG).show();
                    }else if(error instanceof TimeoutError){
                        Log.e(TAG, "Timeout Error: " + error.getMessage());
                        Toast.makeText(getApplicationContext(), "Registration Error: Timeout Error", Toast.LENGTH_LONG).show();
                    }else if(error instanceof NoConnectionError){
                        Log.e(TAG, " No Connection Error: " + error.getMessage());
                        Toast.makeText(getApplicationContext(), "Registration Error: No Connection Error", Toast.LENGTH_LONG).show();
                    }

                }
            }){
        @Override
        protected Map<String, String> getParams(){
            //posting params to register url
            Map<String, String> params = new HashMap<String, String>();
            params.put("First_name", fname);
            params.put("Surname", sname);
            params.put("PhoneNo", phoneno);
            params.put("Email", email);
            params.put("Password", password);

            return params;
        }
    };

    strReq.setRetryPolicy(new DefaultRetryPolicy(50000,DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
    //Add to requestQueue
    Log.d(TAG, strReq.toString());
    AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
}

addToRequestQueue:

  public RequestQueue getRequestQueue(){
    if(mRequestQueue == null){
        mRequestQueue = Volley.newRequestQueue(getApplicationContext());
    }
    return mRequestQueue;
}

  public <T> void addToRequestQueue(Request<T> req, String tag){
    req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
    getRequestQueue().add(req);
}

add_user:

<?php

/ * * Следующий код создаст новую строку продукта * Все детали продукта считываются из HTTP Post Request * /

 //create array for json response
 $response = array();

 //check for required fields
 //&& isset($_POST['sname'] && isset($_POST['phoneno']) && isset($_POST['email']) && isset($_POST['password'])
if(isset($_POST['fname'])){
  $fname = $_POST['fname'];
  $sname = $_POST['sname'];
  $phoneno = $_POST['phoneno'];
  $email = $_POST['email'];
  $password = $_POST['password'];



//include db connect
require_once __DIR__ . "/db_connect.php";

//connect to db
$db = new DB_CONNECT();

//mysql inserting a new row
$result = mysqli_query("INSERT INTO users(First_name, Surname, PhoneNo, Email, Password) VALUES('$fname', '$sname', '$phoneno','$email', '$password')");

//check if row is inserted
if($result){
    $response['success'] = 1;
    $response['message'] = "Successfully inserted";

    //echoing JSON response
    echo json_encode($response);
}else{
    //failed to insert row
    $response['success'] = 0;
    $response['message'] = "An error occured.";

    //echo JSON response
    echo json_encode($response);
}
}else{
    $response['success'] = 0;
    $response['message'] = "required field(s) missing.";

    //echo JSON response
    echo json_encode($response);
}?>

db_connect

 class DB_CONNECT {

 //constructor
 function __construct(){
     //connecting to database
     $this -> connect();
 }

 //destructor
 function __destruct(){
     //closing db connection
     $this -> close();
 }

 /*
  * Function to connect to database
  */

  function connect(){
      //import database connection variables
      require_once __DIR__ . '/db_config.php';

      //connecting to mysql database
      $con = mysqli_connect(DB_SERVER, DB_USER, DB_PASSWORD) or die(mysqli_connect_error()) or die(mysqli_error());

      //selecting database
      $db = mysqli_select_db(DB_DATABASE) or die(mysqli_error());

      //returning connection cursor
      return $con;
  }

  function close(){
      //closing db connection
      mysqli_close();
  }
}?>

DB_CONFIG

define('DB_USER', "root"); //db user
define('DB_PASSWORD', ""); //db password
define('DB_DATABASE', "pom"); //database name
define('DB_SERVER', "localhost");
?>

Выше приведен весь код, который должен вызываться при попытке подключиться к БД. Он должен добавить новую запись в таблицу users в моей базе данных MySQL, а в приложении он должен перевести меня на другой экран, но в таблице нет записей, и приложение вместо этого выдает ошибку тайм-аута. Локальный IP-адрес моего компьютера - 192.168.0.18, а для моего телефона - 192.168.0.55. Я пробовал порт 80, порт не указан, и сейчас я пытаюсь 3000, но все они дают ошибку времени ожидания. Последнее, что может быть полезно, - это то, что запрос даже не отображается в журнале apache. Я ожидаю увидеть что-то вроде этого

 192.168.0.55 - - [27/Jun/2019:11:30:01 +0100] "POST /pom/add_user.php HTTP/1.1" 200 52

но в самый последний раз, когда я его запускал, в журнале доступа или журнале ошибок нет записей.

Обновление:

Я решил проверить Wireshark, чтобы проверить, проходят ли пакеты. Я получил этот захват:

211 18.541329   192.168.0.55    192.168.0.18    TCP 74  38066 → 80 [SYN] Seq=0 Win=65535 Len=0 MSS=1460 SACK_PERM=1 TSval=15216282 TSecr=0 WS=256
214 19.556572   192.168.0.55    192.168.0.18    TCP 74  [TCP Retransmission] 38066 → 80 [SYN] Seq=0 Win=65535 Len=0 MSS=1460 SACK_PERM=1 TSval=15216383 TSecr=0 WS=256234   
234 21.556683   192.168.0.55    192.168.0.18    TCP 74  [TCP Retransmission] 38066 → 80 [SYN] Seq=0 Win=65535 Len=0 MSS=1460 SACK_PERM=1 TSval=15216583 TSecr=0 WS=256
287 25.554442   192.168.0.55    192.168.0.18    TCP 74  [TCP Retransmission] 38066 → 80 [SYN] Seq=0 Win=65535 Len=0 MSS=1460 SACK_PERM=1 TSval=15216984 TSecr=0 WS=256
396 33.572515   192.168.0.55    192.168.0.18    TCP 74  [TCP Retransmission] 38066 → 80 [SYN] Seq=0 Win=65535 Len=0 MSS=1460 SACK_PERM=1 TSval=15217786 TSecr=0 WS=256

Кажется, что это не удается рукопожатие. Значит ли это, что у меня не правильно настроен мой apache? Или это проблема брандмауэра. Я добавил исключения, чтобы разрешить трафик с 192.168.0.55 до 192.168.0.18 на моем компьютере и межсетевом экране маршрутизатора.

Обновление 2: Теперь это работает. Рукопожатие там, а также HTTP-запрос и 200 ОК. Для тех, кто страдает той же проблемой, это проблема с брандмауэром. Для меня есть 3 брандмауэра:

  • Защитник Windows
  • Commodo антивирус
  • Брандмауэр маршрутизатора

Я установил правила для всех из них, чтобы пропускать трафик. К сожалению, окна были окнами, но по какой-то причине они все еще блокировали. Когда я отключил Windows Defender все вместе, пакеты прошли. Несмотря на то, что у меня есть входящее правило для защитника, оно все равно не понравилось, так что это может быть что-то, о чем стоит помнить.

...