简体   繁体   中英

Android Server Socket not listening immediately

I have checked every related post to this but none seems to answer my problem. Anyhow, I'm making a simple chat server-client app using sockets. In the code below, what happens is, server can send data to client always but when client sends to server, it doesn't appear in server's UI unless you send data to client. For example:

Server to Client Situation:

Server sends "A"
Server displays "A" in Server UI
Client recieves "A"
Client displays "A" in Client UI

Server sends "B"
Server displays "B" in Server UI
Client recieves "B"
Client displays "B" in Client UI

Server sends "C"
Server displays "C" in Server UI
Client recieves "C"
Client displays "C" in Client UI

Client to Server Situation:

Client sends "A"
Client displays "A" in Client UI
Server receives nothing
Server displays nothing in Server UI

Server sends "B"
Server displays "B" in Server UI
Sever receives "A" //from earlier
Server displays "A" in Server UI
Client receives "B"
Client displays "B" in Server UI

Client sends "Q"
Client displays "Q" in Client UI
Client sends "W"
Client displays "W" in Client UI
Client sends "E"
Client displays "E" in Client UI
Server receives none of "Q","W", or "E"
Server sends "P"
Server displays "P" in Server UI
Server displays "E" in Server UI
Client receives "P"
Client displays "P" in Client UI

What do you think is causing this? All I want is when Client sends data no matter how many times, Server receives without having to click anything like my current situation. Client receives Server's data fine. Thanks for any answer

Client.java

//imports...

public class RawClient extends Activity {

int portNo = 8080;

//globals..

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

    editTextAddress = (EditText) findViewById(R.id.address);
    buttonConnect = (Button) findViewById(R.id.connect);
    textResponse = (TextView) findViewById(R.id.response);
    buttonConnect.setOnClickListener(buttonConnectOnClickListener);

}


View.OnClickListener buttonConnectOnClickListener =
        new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                MyClientTask myClientTask = new MyClientTask(
                        editTextAddress.getText().toString(),
                        portNo);
                myClientTask.execute();
            }
        };

public class MyClientTask extends AsyncTask<Void, Void, Void> {

    String dstAddress;
    int dstPort;
    String response = "";

    MyClientTask(String addr, int port) {
        dstAddress = addr;
        dstPort = port;
    }

    @Override
    protected Void doInBackground(Void... arg0) {

        Socket socket = null;

        try {
            socket = new Socket(dstAddress, dstPort);

            ByteArrayOutputStream byteArrayOutputStream =
                    new ByteArrayOutputStream(1024);
            byte[] buffer = new byte[1024];

            int bytesRead;
            InputStream inputStream = socket.getInputStream();

/*
 * notice:
 * inputStream.read() will block if no data return
 */
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, bytesRead);
                response += byteArrayOutputStream.toString("UTF-8");
            }

        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            response = "UnknownHostException: " + e.toString();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            response = "IOException: " + e.toString();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
        textResponse.setText("Connected");
        textResponse.setTextColor(Color.parseColor("#2eb82e"));
        buttonConnect.setEnabled(false);

        //reinstantiated thread to recieve messages from server/send message to server
        sendData = new ClientPassData(
                editTextAddress.getText().toString(),
                portNo);
        sendData.execute();
    }

}

//class called to send data..
public class ClientPassData extends AsyncTask<Void, Void, Void> {
    String dstAddress;
    int dstPort;
    String getResponse = "";

    ClientPassData(String addr, int port) {
        dstAddress = addr;
        dstPort = port;
    }

    @Override
    protected Void doInBackground(Void... arg0) {

        Socket socket = null;

        try {
            socket = new Socket(dstAddress, dstPort);

            //send data to client    
            PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket
                    .getOutputStream())), true);
            out.println("" + my_answer);
            out.flush();

            ByteArrayOutputStream byteArrayOutputStream =
                    new ByteArrayOutputStream(1024);
            byte[] buffer = new byte[1024];

            int bytesRead;
            InputStream inputStream = socket.getInputStream();
/*
 * notice:
 * inputStream.read() will block if no data return
 */
            //recieve data from server
            if (inputStream == null) {

            }
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, bytesRead);
                getResponse += byteArrayOutputStream.toString("UTF-8");

            }

        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            getResponse = "UnknownHostException: " + e.toString();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            getResponse = "IOException: " + e.toString();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
          super.onPostExecute(result);
          //do anything with recieved message
          //reinstantiate itself to continue listening to server
        sendData = new ClientPassData(
                editTextAddress.getText().toString(),
                portNo);
        sendData.execute();
        // }

    }

}

public void cl_send(View view) {
    if(cl_input.getText().toString().length() <= 0){
        Toast t = Toast.makeText(getApplicationContext(), "Cannot Send Empty String", Toast.LENGTH_SHORT );
        t.show();
    } else {
        sendData = new ClientPassData(
                editTextAddress.getText().toString(),
                portNo);
        //set data to send to server here
        //send!
        sendData.execute();
    }
}
}

Server.java

//imports..

public class RawServer extends Activity {

//globals..

TextView info, infoip, serverEnemScore, txtServMyScore;
String message = "";
ServerSocket serverSocket;

String lastAnswer = "";

Socket globalSocket;
Thread socketServerThread;

int round = 1;
int play = 0; //counter to know how many iterations of the game had happened.
int servMyScore = 0; //variable that holds my score...
int servEnemyScore = 0;
String passValue = "", ser_myAnswer = "";

SocketServerReplyThread servePass;

String lineChat = null; //String that will hold message of Client from InputStream

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

    initiailize();

    infoip = (TextView) findViewById(R.id.infoip);

    infoip.setText(getIpAddress());

    socketServerThread = new Thread(new SocketServerThread());
    socketServerThread.start(); //starts listening to connecting clients
}

private String getIpAddress() {
    String ip = "";
    try {
        Enumeration<NetworkInterface> enumNetworkInterfaces = NetworkInterface
                .getNetworkInterfaces();
        while (enumNetworkInterfaces.hasMoreElements()) {
            NetworkInterface networkInterface = enumNetworkInterfaces
                    .nextElement();
            Enumeration<InetAddress> enumInetAddress = networkInterface
                    .getInetAddresses();
            while (enumInetAddress.hasMoreElements()) {
                InetAddress inetAddress = enumInetAddress.nextElement();

                if (inetAddress.isSiteLocalAddress()) {
                    ip += "SiteLocalAddress: "
                            + inetAddress.getHostAddress() + "\n";
                }
            }
        }
    } catch (SocketException e) {
        e.printStackTrace();
        ip += "Something Wrong! " + e.toString() + "\n";
    }

    return ip;
} //end of getIpAddress

public void send(View v){
    servePass = new SocketServerReplyThread(globalSocket, score);
    ser_myAnswer = input.getText().toString();
    rowMessages.add(new RowMessage(me, ser_myAnswer)); //add to arraylist
    adapter.notifyDataSetChanged(); //updates the adapter na naay nadungag na data sa arraylist
    scrollMyListViewToBottom();
    input.setText("");
    servePass.run();
}

private class SocketServerThread extends Thread {

    static final int SocketServerPORT = 8080;
    int count = 0;
    boolean flag = false;

    @Override
    public void run() {
        try {
            serverSocket = new ServerSocket(SocketServerPORT);

            while (true) {
                Socket socket = serverSocket.accept();
                globalSocket = socket;

                final SocketServerReplyThread socketServerReplyThread = new SocketServerReplyThread(
                        socket, count);


                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                lineChat = in.readLine();

                RawServer.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if(!lineChat.equals(lastAnswer) && lineChat.length() > 0){
                            lastAnswer = lineChat;
                            //display answer from client here
                        }
                    }
                });

            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}


private class SocketServerReplyThread extends Thread {

    private Socket hostThreadSocket;
    int cnt;

    SocketServerReplyThread(Socket socket, int c) {
        hostThreadSocket = socket;
        cnt = c;
    }

    @Override
    public void run() {
        OutputStream outputStream;
        String msgReply;

        try {
        //send data to client
            outputStream = hostThreadSocket.getOutputStream();
            PrintStream printStream = new PrintStream(outputStream);
            printStream.print(msgReply);
            printStream.close();

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            message += "Something wrong! " + e.toString() + "\n";
        }

    }

}

}

Even if you're code is ok, you can have this kind of problems. For example, server can be overloaded, network can be satured. You have to had some protection.

For example, you can increment each message sent by a client. When server receives message 3 before message 2, it waits five or six seconds. If during this time it receives message , you can write 2 and after 3. If you didn't received it, you can write message 3. If you never receive the second message, you.

So, you have to implement a logic system of your choice to prevent network problems.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM