2014-08-30 3 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

+0

예, 서버가 "새 메시지"를받지 못했습니다 – keduadoi

답변

1

서버 구현이 올바르지 않습니다. 연결을 수락 한 후 서버는 새 스레드를 생성하고 accept에 의해 반환 된 소켓을 전달해야합니다. 그런 다음이 스레드는 필요에 따라 클라이언트와 통신해야합니다. 현재 구현은 연결을 허용하고 클라이언트에서 첫 번째 메시지를 읽은 다음 'accept'로 루프를 반환합니다.

+0

이것은 정확하게 제 문제입니다. 정말 고마워요. – keduadoi

0

이것은 단지 추측입니다. 그러나 귀하의 서비스가 귀하의 활동과 동일한 프로세스를 실행하고 있다고 의심됩니다. 그렇지 않은 경우 문제가되지 않을 수도 있습니다. 이 코드는 온 클릭 리스너를 통해 호출 그래서

: 당신은 UI 스레드에서 차단 네트워크 호출을 시도하기 때문에

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를 슬로우합니다.