2014-08-30 86 views
0

我試圖創建控制客戶端和服務器之間的套接字連接,保留客戶的活動之間套接字連接服務套接字連接。這個客戶端的過程是當用戶點擊一個連接按鈕時,一個套接字將被創建,並且客戶端會移動到下一個活動,在這個活動中,我創建了一個按鈕來使用新創建的套接字向服務器發送數據。但是當點擊這個按鈕時,服務器似乎沒有收到客戶端的任何數據。 這是我的服務保留在活動的Android

//ConnectionService.java 
public class ConnectionService extends Service { 
... 
public class LocalBinder extends Binder { 
    public ConnectionService getService(){ 
     return ConnectionService.this; 
    } 
} 
private final IBinder myBinder = new LocalBinder(); 

@Override 
public IBinder onBind(Intent intent) { 
    return myBinder; 
} 

@Override 
public void onCreate(){ 
    super.onCreate(); 
    Log.i("Socket connection","I am on onCreate()"); 
} 

public void isBoundable(){ 
    Toast.makeText(this, "Boundable", Toast.LENGTH_LONG).show(); 
} 

public void getSocketInfo(){ 
    Log.i("Socket info",socket.toString()); 
} 

public void sendMessage(String message){ 
    if(dos!=null){ 
     Log.i("Data_Transfer","Sending message"); 
     try { 
      dos.writeUTF(message); 
      dos.flush(); 
     }catch (IOException e){ 
      e.printStackTrace(); 
     } 
     Log.i("Data_Transfer","Message sent"); 
    } 
} 


@Override 
public int onStartCommand(Intent intent, int flags, int startId){ 
    super.onStartCommand(intent,flags,startId); 
    //Log.i("Socket connection","I am in onStartCommand"); 
    Runnable connection = new SocketConnection(); 
    new Thread(connection).start(); 
    return START_STICKY; 
} 

class SocketConnection implements Runnable{ 

    @Override 
    public void run(){ 
     //create socket connection 
     try { 
      //Log.i("Socket connection", "C: connecting"); 
      serverAddress = InetAddress.getByName(SERVER_IP); 
      socket = new Socket(serverAddress, SERVER_PORT); 
      //Log.i("Socket connection", "C: connected"); 

      dos = new DataOutputStream(socket.getOutputStream()); 

      Log.i("TCP client","C: sent"); 
      dos.writeUTF("Message from client"); 
      dos.flush(); 

      dis = new DataInputStream(socket.getInputStream()); 
      String msg = ""; 
      msg=dis.readUTF(); 
      Log.d("response",msg); 

     } catch (IOException e){ 
      Log.e("TCP client","Cannot connect to server"); 
     } 
    } 
} 

活動創建的服務:

private ConnectionService boundService; 
private Boolean isBound; 

private ServiceConnection connection = new ServiceConnection(){ 

    @Override 
    public void onServiceConnected(ComponentName name, IBinder service){ 
     Log.i("Connect","Creating service"); 
     boundService = ((ConnectionService.LocalBinder)service).getService(); 
     if(boundService!=null){ 
      Log.i("Connect","service bounded"); 
      boundService.isBoundable(); 
      responseFromServerView.setText("Connected"); 
     } 
    } 

    @Override 
    public void onServiceDisconnected(ComponentName name){ 

     boundService = null; 

    } 

}; 

private void doBindService(){ 
    bindService(new Intent(ShareImages.this,ConnectionService.class),connection, Context.BIND_AUTO_CREATE); 
    isBound = true; 
} 

private void doUnbindService(){ 
    if(isBound){ 
     unbindService(connection); 
     isBound = false; 
    } 
} 

@Override 
protected void onDestroy(){ 
    super.onDestroy(); 
    doUnbindService(); 
} 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.share_images); 

    responseFromServerView = (TextView)findViewById(R.id.responseFromServer); 
    responseFromServerView.setText("Connecting"); 
    sendDataBtn = (Button)findViewById(R.id.sendDataBtn); 
    sendDataBtn.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View view) { 
      if(boundService!=null){ 
       boundService.getSocketInfo(); 
       boundService.sendMessage("New message"); 
       Log.i("Connect","Sent"); 
      } 
      Toast.makeText(ShareImages.this, "Sent to server", Toast.LENGTH_SHORT).show(); 
     } 
    }); 

    startService(new Intent(ShareImages.this, ConnectionService.class)); 
    doBindService(); 

} 

服務器代碼:

private class SocketServerThread implements Runnable { 

    static final int SocketServerPORT = 8080; 
    int count = 0; 

    @Override 
    public void run() { 
     Socket socket = null; 
     DataInputStream dataInputStream = null; 
     DataOutputStream dataOutputStream = null; 

     try { 
      serverSocket = new ServerSocket(SocketServerPORT); 
      MainActivity.this.runOnUiThread(new Runnable() { 

       @Override 
       public void run() { 
        info.setText("I'm waiting here: " 
          + serverSocket.getLocalPort()); 
       } 
      }); 

      while (true) { 
       socket = serverSocket.accept(); 
       dataOutputStream = new DataOutputStream(
         socket.getOutputStream()); 
       dataInputStream = new DataInputStream(socket.getInputStream()); 

       String messageFromClient = ""; 

       //If no message sent from client, this code will block the program 
       messageFromClient = dataInputStream.readUTF(); 

       count++; 
       message += "#" + count + " from " + socket.getInetAddress() 
         + ":" + socket.getPort() + "\n" 
         + "Msg from client: " + messageFromClient + "\n"; 

       MainActivity.this.runOnUiThread(new Runnable() { 

        @Override 
        public void run() { 
         msg.setText(message); 
        } 
       }); 

       String msgReply = "Hello from Android, you are #" + count; 
       dataOutputStream.writeUTF(msgReply); 
       System.out.println(messageFromClient); 

      } 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
      final String errMsg = e.toString(); 
      MainActivity.this.runOnUiThread(new Runnable() { 

       @Override 
       public void run() { 
        msg.setText(errMsg); 
       } 
      }); 

     } 

當 「連接到服務器」 被按下時,客戶端發送從消息「消息客戶端「服務器,它的工作原理,服務器可以收到此消息。但是在連接之後,在新活動中,按另一個按鈕向服務器發送「新消息」字符串不起作用,即使boundService仍然存在,服務器也不會收到消息。任何人都請幫我解決這個問題。 P/S:是否使服務器處理多個客戶端以及需要始終保持套接字連接的客戶端的正確方式?

+0

你檢查'logcat'? – eleven 2014-08-30 18:42:36

+0

是的,服務器沒有收到「新消息」 – keduadoi 2014-08-30 18:59:27

回答

1

您的服務器的實現是不正確的。接受連接後,你的服務器應該產生一個新的線程,並將accept返回的套接字傳遞給它。此線程應根據需要與客戶端進行通信。 您當前的實現接受連接,從客戶端讀取第一條消息,然後循環返回到「接受」。

+0

這正是我的問題,非常感謝。 – keduadoi 2014-09-01 02:50:56

0

這只是一個猜測。但我懷疑你的服務正在運行與你的Activity相同的進程(如果不是,那可能無關緊要)。

所以,當這個代碼通過的onClick監聽器調用:

public void sendMessage(String message){ 
    if(dos!=null){ 
     Log.i("Data_Transfer","Sending message"); 
     try { 
      dos.writeUTF(message); 
      dos.flush(); 
     }catch (IOException e){ 
      e.printStackTrace(); 
     } 
     Log.i("Data_Transfer","Message sent"); 
    } 
} 

dos.write調用拋出IOException,因爲你正在試圖做的UI線程阻塞網絡調用。