2017-01-30 75 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 –