2017-12-20 3 views
-2

매우 인스턴트 메시지 응용 프로그램을 만들고있어. 하나의 비동기 작업을 서버에서 메시지를 수신하고 다른 비동기 작업은 서버로 메시지를 보내고 메시지를 다시 에코합니다. 어떤 이유로 서버를 동시에 보내고들을 수 없습니다. 이것은 일어나는 순서입니다.android - 동일한 IP 및 포트에 2 개의 소켓을 실행하는 방법은 무엇입니까?

1. 사용자 A가 메시지를 입력하고 보내기를 클릭합니다. 아무 반응이 없습니다. 2. 사용자 B는 (수신 대기중인 비동기 작업을 해제하고) 메시지를 보냅니다. 그러면 사용자 B의 메시지와 함께 사용자 A의 메시지가 다시 나타납니다. 나는 왜 사용자 A가 동시에 메시지를 보내고들을 수 없는지 모르겠습니다. 여기 내 2 비동기 작업이 있습니다.

private class CommunicateWithServerAsyncTask extends AsyncTask<Void,Void,Void> 
    { 
     private String jsonReply = ""; 
     private String jsonOutputToServer = ""; 

     public CommunicateWithServerAsyncTask(String jsonMessage) 
     { 
      this.jsonOutputToServer = jsonMessage; 
     } 

     @Override 
     protected Void doInBackground(Void... params) 
     { 
      Log.d(SOCKET_TESTING_TAG,"break 1"); 
      try 
      { 
       Log.d(SOCKET_TESTING_TAG,"break 2"); 
       Socket socket = new Socket("ip",portNumber); 
       PrintWriter printWriter = new PrintWriter(socket.getOutputStream()); 
       BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
       printWriter.println(jsonOutputToServer); 
       printWriter.flush(); 
       jsonReply = bufferedReader.readLine(); 
       Log.d(SOCKET_TESTING_TAG,"break 2"); 
       if(jsonReply != null && !jsonReply.equals("")) 
       { 
        Log.d(SOCKET_TESTING_TAG,"break 3"); 
        Log.d(SOCKET_TESTING_TAG,"my message is " + jsonReply); 
       } 
       else 
       { 
        Log.d(SOCKET_TESTING_TAG,"break 4"); 
        Log.d(SOCKET_TESTING_TAG,"no message yet"); 
       } 
       printWriter.close(); 
       bufferedReader.close(); 
       socket.close(); 

      } 
      catch (IOException e) 
      { 
       Log.d(SOCKET_TESTING_TAG,"failed " + e.getMessage()); 
       e.printStackTrace(); 
      } 
      return null; 
     } 

     @Override 
     public void onPostExecute(Void var) 
     { 
      displayMessageFromServer(jsonReply,false); 
     } 
    } 

두 번째 비동기 작업

private class ListenForMessagesAsyncTask extends AsyncTask<Void,Void,Void> 
{ 
    private String jsonReply = ""; 
    //private BufferedReader bufferedReader; 

    @Override 
    protected Void doInBackground(Void... params) 
    { 
     Log.d(SOCKET_TESTING_TAG,"break A"); 
     try 
     { 
      Socket socket = new Socket("52.91.109.76",1234);; 
      BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
      while (isListeningForMessages) 
      { 
       Log.d(SOCKET_TESTING_TAG,"break D"); 
       Log.d(SOCKET_TESTING_TAG,"my buffer reader value is " + String.valueOf(bufferedReader.ready())); 
       if(bufferedReader.ready()) 
       { 
        Log.d(SOCKET_TESTING_TAG,"break E"); 
        jsonReply = (String) bufferedReader.readLine(); 
        Log.d(SOCKET_TESTING_TAG,"break F"); 
        isListeningForMessages = false;//we have a reply, close the while loop and Async Task. 
        Log.d(SOCKET_TESTING_TAG,"my listening message is " + jsonReply); 
       } 
      } 
      bufferedReader.close(); 
      socket.close(); 

     } 
     catch (IOException e) 
     { 
      Log.d(SOCKET_TESTING_TAG,"failed " + e.getMessage()); 
      e.printStackTrace(); 
     } 

     return null; 
    } 

    @Override 
    public void onPostExecute(Void var) 
    { 
     displayMessageFromServer(jsonReply,true); 
    } 

} 
+0

내가 당신의 [이전 질문]에 내 대답은 당신에게 (https://stackoverflow.com/q/47899231/207421) 내의 readLine ('그 https://stackoverflow.com/q/47899231/207421)'null을 반환한다고해서 '아직 메시지가 없습니다.'라는 의미가 아닙니다. – EJP

+0

비동기 작업은 두 장치의 서로 다른 클라이언트 응용 프로그램에서 사용됩니다. 너 왜 그렇게 말 안했어? – greenapps

+0

다른 클라이언트가받는 메시지는 서버가 보내는 대상과받는 사람에 따라 다릅니다. 당신은 당신의 서버에 대해 아무 것도 말하지 않았습니다. 또한 서버 코드를 게시하지 않았습니다. 그렇다면 어떻게해야 하는지를 어떻게 알 수 있을까요? – greenapps

답변

-1

나는 서버에 메시지를 보내려면 사용자 1에 대한 매우 간단한 방법을 원했다. 서버는 응답을 에코하고 그 메시지를 사용자 2에게 보냅니다.

서버로 메시지를 보내고 에코 응답을 얻으려면 CommunicateWithServerAsyncTask를 살펴보십시오. 여기서는 소켓 객체를 사용하여 서버에 연결하고 Typewriter 클래스를 사용하여 서버에 메시지를 보낼 수 있습니다. 다음으로, 버퍼 판독기 클래스를 사용하여 서버의 모든 메시지 응답을 수신합니다.

사용자 2가 서버에서 사용자 1의 메시지를 수신하려면 서버에서 응답을 계속 수신해야하므로 CommunicateWithServerAsyncTask를 구현 한 것입니다. 첫 번째 AsyncTask와 같은 개념이지만 while 루프에서는 socket 및 bufferreader 객체가 필요합니다.

호프가 소켓 연결의 기본 사항을 파악하는 데 도움이되기를 바랍니다. 이 답변에서 저는 이미 당신이 어딘가에서 돌아가는 서비스를 제공하고 있고 클라이언트 측에서 도움이 필요하다고 가정합니다.

public class MainActivity extends AppCompatActivity 
{ 
    private Button b_send; 
    private EditText et_message; 
    private TextView tv_response, userB_TV; 
    private boolean isSendButtonPressed; 
    private final String SOCKET_TESTING_TAG = "SOCKET_TESTING_TAG"; 
    private static boolean isListeningForMessages = true; 
    private Socket socket; 
    private BufferedReader bufferedReader; 
    private ListenForMessagesAsyncTask listenForMessagesAsyncTask; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     bindActivity(); 

    } 
    private void bindActivity() 
    { 
     b_send = (Button) findViewById(R.id.b_send); 
     et_message = (EditText) findViewById(R.id.et_message); 
     tv_response = (TextView) findViewById(R.id.tv_response); 
     userB_TV = (TextView) findViewById(R.id.tv_history); 
     tv_response.setMovementMethod(new ScrollingMovementMethod()); 
     b_send.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) 
      { 
       if(!et_message.getText().toString().isEmpty() && !isSendButtonPressed)//I do a couple checks to make sure the user doesn't send an empty string and that they don't keep tapping the button 
       { 
        isSendButtonPressed = true; 
        listenForMessagesAsyncTask.cancel(true); 
        try 
        { 
         socket.close(); 
         bufferedReader.close(); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } 
        CommunicateWithServerAsyncTask communicateWithServerAsyncTask = new CommunicateWithServerAsyncTask(convertMessageToJson(et_message.getText().toString())); 
        communicateWithServerAsyncTask.execute();//Note: you could do new CommunicateWithServerAsyncTask.execute(""); However, im just used to initiating async tasks this way. 

       } 
      } 
     }); 
     listenForMessagesAsyncTask = new ListenForMessagesAsyncTask(); 
     listenForMessagesAsyncTask.execute(); 
    } 

    private class CommunicateWithServerAsyncTask extends AsyncTask<Void,Void,Void> 
    { 
     private String jsonReply = ""; 
     private String jsonOutputToServer = ""; 

     public CommunicateWithServerAsyncTask(String jsonMessage) 
     { 
      this.jsonOutputToServer = jsonMessage; 
     } 

     @Override 
     protected Void doInBackground(Void... params) 
     { 
      try 
      { 
       Socket socket = new Socket("ip",portNumber); 
       PrintWriter printWriter = new PrintWriter(socket.getOutputStream()); 
       BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
       printWriter.println(jsonOutputToServer); 
       printWriter.flush(); 
       jsonReply = bufferedReader.readLine(); 
       if(jsonReply != null && !jsonReply.equals("")) 
       { 
        Log.d(SOCKET_TESTING_TAG,"my message is " + jsonReply); 
       } 
       else 
       { 
        Log.d(SOCKET_TESTING_TAG,"no message yet"); 
       } 
       printWriter.close(); 
       bufferedReader.close(); 
       socket.close(); 

      } 
      catch (IOException e) 
      { 
       Log.d(SOCKET_TESTING_TAG,"failed " + e.getMessage()); 
       e.printStackTrace(); 
      } 
      return null; 
     } 

     @Override 
     public void onPostExecute(Void var) 
     { 
      displayMessageFromServer(jsonReply,false); 
     } 
    } 

    private class ListenForMessagesAsyncTask extends AsyncTask<Void,Void,Void> 
    { 
     private String jsonReply = ""; 
     //private BufferedReader bufferedReader; 

     @Override 
     protected Void doInBackground(Void... params) 
     { 
      try 
      { 
       socket = new Socket("ip",portNumber);; 
       bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
       while (isListeningForMessages) 
       { 
        //Log.d(SOCKET_TESTING_TAG,"break D"); 
        if(bufferedReader.ready()) 
        { 
         Log.d(SOCKET_TESTING_TAG,"break E"); 
         jsonReply = (String) bufferedReader.readLine(); 
         Log.d(SOCKET_TESTING_TAG,"break F"); 
         isListeningForMessages = false;//we have a reply, close the while loop and Async Task. 
         Log.d(SOCKET_TESTING_TAG,"my listening message is " + jsonReply); 
        } 
       } 
       bufferedReader.close(); 
       socket.close(); 

      } 
      catch (IOException e) 
      { 
       Log.d(SOCKET_TESTING_TAG,"failed " + e.getMessage()); 
       e.printStackTrace(); 
      } 

      return null; 
     } 

     @Override 
     public void onPostExecute(Void var) 
     { 
      displayMessageFromServer(jsonReply,true); 
     } 

    } 
+0

다른 내용과 왜 더 나은지 언급하지 않는 한이 방법은 다른 사람에게별로 유용하지 않습니다. – EJP

+0

@EJP 좋습니다. 많은 세부 사항을 추가하겠습니다. – TheQ

관련 문제