android - 如何运行2个套接字到同一个IP和端口?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android - 如何运行2个套接字到同一个IP和端口?相关的知识,希望对你有一定的参考价值。

所以我正在制作一个非常小的消息应用。我有1个异步任务,用于侦听来自服务器的消息,以及另一个异步任务,它将消息发送到服务器并回送消息。由于某种原因,我无法同时发送和收听服务器。这是发生的顺序的顺序:

1.User A输入消息并单击发送。什么都没发生。 2.User B,(关闭侦听异步任务)并发送消息,然后返回userA的消息以及用户Bs。我不知道为什么我的用户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);
    }

}
答案

我想要一种非常简单的方法让用户1向服务器发送消息。服务器回应响应并将该消息发送给用户2。

要完成向服务器发送消息并获得echo响应,您可以查看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);
        }

    }

以上是关于android - 如何运行2个套接字到同一个IP和端口?的主要内容,如果未能解决你的问题,请参考以下文章

socket网络通信

AsyncTask和套接字在android java中不起作用

如何在 Android Java 中将 MAC 地址转换为 IP?

如何将数据从 Android 中的数据报套接字发送到 Node js 服务器?

Java 可以并行运行同一个套接字的多个实例吗?

Android 中的 ActionScript 套接字