2017-01-30 61 views
1

我是Android新手,對套接字編程有點新鮮。我有兩個設備,運行Android 5.1,與WiFi直接連接(不確定是否相關)。我有一個服務,服務器在套接字上偵聽請求,然後將回復返回給客戶端。Android WiFi直連客戶端套接字超時

同樣,客戶端代碼發送請求並偵聽來自服務器的回覆。服務器正在發送響應,但客戶端永遠不會收到消息並且套接字超時。

服務器測試代碼:

while (true) { 
    try { 
     Log.i(TAG, "test waiting for a request"); 
     mServer = new ServerSocket(PORT); 
     Socket socket = mServer.accept(); //Block to receive message // 
     BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
     Log.i(TAG, "Message received! " + in.readLine()); 

     String msg = "This is my reply."; 
     OutputStream outputStream = socket.getOutputStream(); 
     PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); 
     out.println(msg); 
     out.flush(); 
     out.close(); 

    } catch (SocketException e) { 
     Log.e(TAG, "Socket Accept Interrupted", e); 
    } catch (IOException e) { 
     Log.e(TAG, "Socket Failure", e); 
    } finally { 
     if (mServer != null && mServer.isBound()) { 
      try { 
       mServer.close(); 
      } catch (IOException ioException) { 
       Log.e(TAG, "Failed to close socket trying to recover from SocketException", ioException); 
      } 
     } 
    } 
} 

客戶端測試代碼:

Socket socket = null; 
    SocketAddress addr = new InetSocketAddress(host, PORT); 
    int socketTOms = 5000; 
    try { 
     socket = new Socket(host, PORT); 
     socket.setKeepAlive(false); 
     String syncReq = "Request to server."; 

     //Send Request// 
     OutputStream outputStream = socket.getOutputStream(); 
     outputStream.write(syncReq.getBytes()); 
     socket.setSoTimeout(socketTOms); 

     //Rcv reply// 
     BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
     Log.i(TAG, "Message received! " + in.readLine()); 

    } catch (SocketTimeoutException e) { 
     Log.e(TAG, "Timeout while reading from socket: timeout=" + socketTOms); 
    } catch (Exception e) { 
     Log.e(TAG, "Exception", e); 
    } finally { 
     if (socket != null && socket.isConnected()) { 
      try { 
       socket.close(); 
      } catch (IOException e) { 
       Log.e(TAG, "Exception while closing socket", e); 
      } 
     } 
    } 

我通過Android Studio中運行兩個不同的設備服務器和客戶端,可以在日誌中看到服務器收到請求併發送回復,但客戶端始終爲throwsSocketTimeoutException。我看到其他地方socket.setKeepAlive(false)將解決這個問題,但它似乎沒有任何效果。

似乎很簡單,但我看不到我在這裏失蹤。

回答

0

想通了這一點.... 在我使用outputStream.write(...)發送請求到服務器的客戶端:

String syncReq = "Request to server."; 
    OutputStream outputStream = socket.getOutputStream(); 
    outputStream.write(syncReq.getBytes()); 

但隨着BufferedReader.readLine()閱讀它在服務器上:

Socket socket = mServer.accept(); //Block to receive message // 
    BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
    Log.i(TAG, "Message received! " + in.readLine()); 

我的問題是,outputStream.write(...)不會在字符串末尾附加'\ n',但服務器上的in.readLine()預期它。因此服務器在等待'\ n'時被阻塞;這又導致客戶端套接字超時。

0

可能在無限循環之前嘗試下面這行代碼mServer = new ServerSocket(PORT);

您是否嘗試在服務器端應用程序中創建線程。這會使進程並行運行,以便在服務器等待請求時應用程序不會掛起。首先嚐試這個代碼爲本地主機。要找到Inetaddress,只需使用InetAddress.getLocalHost()。然後運行這個。爲了與不同設備進行通信,提供了稱爲(NSD)(網絡服務Discovary)的服務。

但是,如果你想以這種方式運行,我已經爲你寫了一個代碼。

服務器端代碼

TextView textView; 
    Button button; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     textView=(TextView)findViewById(R.id.textView); 
     button=(Button)findViewById(R.id.button); 

button.setOnClickListener(
     new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       connect(); 
      } 
     } 
); 



    } 


    public void connect() 
    { 

     MyServer myServer= new MyServer(); 
     myServer.setEventListener(this); 
     myServer.startListening(); 

    } 





    @Override 
    public void Display(String message) { 

     textView.setText("Client - "+ message); 
    } 
} 

客戶端代碼

TextView textView; 
    Button button; 
    Thread mThread; 
    Socket clientSocket; 
Button sendBtn; 
    public String userText1; 
    ObjectOutputStream output; 
    EditText editText; 
    Object userText; 


    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     textView=(TextView)findViewById(R.id.textView); 
     button=(Button)findViewById(R.id.button); 
     sendBtn=(Button)findViewById(R.id.sendBtn); 
     editText=(EditText)findViewById(R.id.editText); 
     sendBtn.setOnClickListener(
       new View.OnClickListener() { 
        @Override 
        public void onClick(View v) { 
         userText=editText.getText().toString(); 


         start(); 
        } 
       } 
     ); 




    public void start() 
    { 
     mThread= new Thread(new Runnable() { 
      @Override 
      public void run() { 

       try { 
        clientSocket = new Socket("127.0.0.1", 2001); 
        Log.v("binaya", "client socket created"); 
        output = new ObjectOutputStream(clientSocket.getOutputStream()); 
        output.writeObject(userText); 
        Message serverObj = Message.obtain(); 
        ObjectInputStream input = new ObjectInputStream(clientSocket.getInputStream()); 


        String strMsg = input.readObject().toString(); 
        serverObj.obj = strMsg; 

        mHandler.sendMessage(serverObj); 

       } catch (IOException e) { 
        e.printStackTrace(); 
       } catch (ClassNotFoundException e) { 
        e.printStackTrace(); 
       } 


      } 
     }); 
    mThread.start(); 
    } 


    Handler mHandler= new Handler() 
    { 
     @Override 
     public void handleMessage(Message msg) { 
      msgDisplay(msg.obj.toString()); 
     } 
    }; 

    private void msgDisplay(String msg) { 
    textView.setText("Server - " + msg); 

    } 

我們已經用處理,因爲我們不能在這種情況下,從內部運行的觸摸用戶界面。 感謝

+0

謝謝SháilèndraWregmi –