簡體   English   中英

無法為一個Java服務器管理多個客戶端(Android設備)

[英]Unable to manage multiple clients (android devices) for a single java server

我需要服務器來跟蹤每個客戶端的連接。 建議我使用線程。 所以我想要實現的是為每個客戶端創建一個線程,該線程應運行到客戶端連接存在為止。 但是發生的是,對於任何客戶端發送的每條消息,都在doInBackground()函數中創建了一個新的客戶端連接。 因此,我沒有為一個客戶端使用一個線程,而是為發送到服務器的任何客戶端消息使用了一個線程。 您能否提出一種方法,使我的服務器能夠區分來自不同客戶端的不同消息?

Java服務器代碼:

package com.nss.academyassistserver;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class AcademyAssistServer {
    public static ServerSocket serverSocket;
    public static Socket clientSocket;

    static final int PORT = 4444;

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try {
            serverSocket = new ServerSocket(PORT); // Server socket         
        } catch (IOException e) {
            System.out.println("Could not listen on port: "+PORT+" \n");
        }
        System.out.println("Server started. Listening to the port "+PORT);

        while (true) {
            try {
                clientSocket = serverSocket.accept();
                System.out.println("New connection accepted."); // accept the client connection
            } catch (IOException ex) {
                System.out.println("Problem in message reading");
            }
            //new thread for a client               
            new EchoThread(clientSocket).start();
        }
    }
}

class EchoThread extends Thread {

    InputStreamReader inputStreamReader;
    BufferedReader bufferedReader;
    String fromClient;
    Socket clientSocket;

    public EchoThread(Socket clientSocket) {
        this.clientSocket = clientSocket;
    }

    public void run() {
        try {
            inputStreamReader = new InputStreamReader(clientSocket.getInputStream());
            bufferedReader = new BufferedReader(inputStreamReader); // get the client message
        } catch (IOException e) {
            return;
        }

        while (!Thread.currentThread().isInterrupted()) {
             System.out.println("I am thread " + Thread.currentThread().getId()); 
            try {
                fromClient = bufferedReader.readLine();
                if ((fromClient == null) || fromClient.equalsIgnoreCase("exit")) {
                    System.out.println("You're welcome, bye!");

                    return;
                } else {
                    System.out.println(fromClient);
                    Thread.currentThread().interrupt();
                }
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }
        }
        try {
            clientSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客戶活動代碼:

    package com.nss.academyassist;

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Locale;

    //import statements for client
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.net.UnknownHostException;

    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.Window;
    import android.view.WindowManager;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.ImageButton;
    import android.widget.Toast;

    //import statements for client
    import android.os.AsyncTask;


    public class MainActivity extends Activity implements OnClickListener {

        EditText question;

        //Client sockets
        private Socket client;
        private PrintWriter printwriter;
        private String toTag;

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

            question = (EditText)findViewById(R.id.editText1);

            Button query = (Button)findViewById(R.id.button2);
            query.setOnClickListener(this);
        }

        private class SendMessage extends AsyncTask<Void, Void, Void> {

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

                try {
                    client = new Socket("Server IP Address", 4444);
                    printwriter = new PrintWriter(client.getOutputStream(), true);
                    printwriter.write(toTag); // write the message to output stream

                    printwriter.flush();
                    printwriter.close();
                    client.close(); // closing the connection

                } catch (UnknownHostException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }
        }

        public void onClick(View v)
        {
            switch(v.getId())
            {
                case R.id.button2:

                        toTag = question.getText().toString();
                        // Output the result
                        Toast.makeText(getApplicationContext(), toTag, 
                                       Toast.LENGTH_LONG).show();

                        //Invoke the execute method of AsynTask, which will run the doInBackground method of SendMessage Class
                        SendMessage sendMessageTask = new SendMessage();
                        sendMessageTask.execute();

                    break;
            }

        }
}

您可以使用IP告訴客戶端。 采用

clientSocket.getInetAddress().getHostAddress()

您還可以在android代碼中保持客戶端未關閉。 例如,您可以在onCreate打開Socket並在onDestroy中將其close

問題的原因在於您的客戶端代碼。 使用new Socket(..)客戶端每次向服務器發送標簽時都會創建一個新的連接。 因此,您可以創建一個可以重用的連接:

public class MainActivity extends Activity implements OnClickListener {

    /* .. your other variables .. */

    private Socket client;
    private PrintWriter printwriter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        /* .. no change here .. */
    }

    public void onStart()
    {
        if(this.client != null)
        {
            try {
                client = new Socket("Server IP Address", 4444);
                printwriter = new PrintWriter(client.getOutputStream(), true);
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void onClose()
    {
        this.printwriter.close();
        this.printwriter = null;
        this.client.close();
        this.client = null;
    }

    private class SendMessage extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... params) {
            try {
                printwriter.write(toTag); // write the message to output stream
                printwriter.write("\n"); // delimiter
                printwriter.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    public void onClick(View v)
    {
        switch(v.getId())
        {
            case R.id.button2:

                    toTag = question.getText().toString();
                    // Output the result
                    Toast.makeText(getApplicationContext(), toTag, 
                                   Toast.LENGTH_LONG).show();

                    //Invoke the execute method of AsynTask, which will run the doInBackground method of SendMessage Class
                    SendMessage sendMessageTask = new SendMessage();
                    sendMessageTask.execute();

                break;
        }

    }
}

除此之外,您還應該在標簽/消息中附加一些定界符,以便服務器能夠將內容與其他消息區分開。

由於您正在使用BufferedReader.readLine()分隔行

由換行符('\\ n'),回車符('\\ r')或回車符中的任意一個后跟換行符

為此,我在上面的示例中添加了一行,該行在該標記之后附加一個換行符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM