【问题标题】:socket - Android client - Java server PC gets stuck套接字 - Android 客户端 - Java 服务器 PC 卡住
【发布时间】:2016-05-12 03:16:11
【问题描述】:

嗯,这是我的第二篇文章,我正在经历一个关于套接字通信 TCP/IP 的大问题,在 android 客户端和运行在 PC 上的 java 服务器应用程序之间。

当我按下客户端应用程序中的按钮到服务器时,我尝试做的是发送一个字符串,然后根据需要多次将答案返回给我的客户端应用程序,此结果显示在 TextView我的客户。

当我尝试使用我的客户端应用程序连接到服务器时出现问题,连接成功执行,但是当我按下按钮并发送数据时,客户端应用程序卡住了,显示结果的唯一方法是停止服务器应用程序。拜托,我需要帮助!我是安卓新手。谢谢。

这是简单的服务器代码:

import java.io.*;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ServerSocks {

private static ServerSocket myServer;
private static Socket myClient;
private static String msj_ToServer;

public static void main (String args[] ){

    try {

        System.out.println("Bienvenido:\n");

        System.out.println("Por favor ingresar el nº de puerto de comunicación: ");
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String portNumber_str = in.readLine();
        int portNumber = Integer.parseInt(portNumber_str);
        myServer = new ServerSocket(portNumber);

            if(myServer.isBound() == true){

            System.out.println("Iniciando servidor en el puerto: "+portNumber); 

            } 

            else{

            System.err.println("[E R R O R] : No se pudo crear 'LISTEN SOCKET'");
            System.exit(0);

            }

            while(true){

            System.out.println("Esperando algún cliente TCP en el puerto ["+portNumber+"]...");
            myClient = myServer.accept();

            if (myClient.isConnected()) { // if2

            System.out.println("[D A T A] : El cliente ha sido aceptado IP-CLIENT\n"+""+ "IP Client address: "+myClient.getInetAddress());

            DataOutputStream outClient = new DataOutputStream(myClient.getOutputStream());

            DataInputStream inClient = new DataInputStream(myClient.getInputStream());
            msj_ToServer = inClient.readLine();
            System.out.println("Ha1 "+msj_ToServer);

            try{


            if(msj_ToServer.equalsIgnoreCase("D")) {
            System.out.println("HO "+msj_ToServer);
            outClient.writeBytes("ON");
            outClient.flush();
            break;              

            } 

            }catch(IOException e){
             e.printStackTrace();
             }

            if(msj_ToServer == "B" || msj_ToServer == "b"){

               System.out.println(msj_ToServer);
               outClient.writeUTF("OFF");
               outClient.flush();
               break;
               }

               if(msj_ToServer == "C" || msj_ToServer == "c"){
               System.out.println(msj_ToServer);
               outClient.writeUTF("xd");
               outClient.flush();
               break;
               }

               } // fin while inicio de lectura  */

               } // fin msj1

              } // fin while prueba 3
              }// fin if2


              } // fin while (true) superior

           } catch (IOException ex) {
                 Logger.getLogger(ServerSocket.class.getName()).log(Level.SEVERE, null, ex);
            ex.printStackTrace();
        }

    }// fin main 

} // fin clase ServerSocks

这是我的 Android 客户端应用程序的 Main.java 的一部分(我正在使用按钮(“状态”按钮)进行探测,该按钮正在向服务器发送“D”字符串并且服务器发回“ON”作为答案)。

public class MainActivity extends Activity implements OnClickListener {

private Button ledOnButton;
private Button ledOffButton;
static ToggleButton toggleButton; 
static EditText statusEditText;
private Button status;
static TextView prueba; 

static Socket clientSocket; 
static String data;

static String dato;

static PrintStream os;
static DataInputStream is;
static DataInputStream inputLine;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (android.os.Build.VERSION.SDK_INT > 9) {
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
    }

    ledOnButton = (Button) findViewById(R.id.ledOnButton);
    ledOnButton.setOnClickListener(this);

    ledOffButton = (Button) findViewById(R.id.ledOffButton);
    ledOffButton.setOnClickListener(this);

    toggleButton = (ToggleButton) findViewById(R.id.toggleButton);
    toggleButton.setOnClickListener(this);

    status = (Button) findViewById(R.id.statusButton);
    status.setOnClickListener(this);

    statusEditText = (EditText) findViewById(R.id.statusEditText);

    // prueba con textView

    prueba = (TextView) findViewById(R.id.textView_Prueba);

} // fin OnCreate

@Override

public void onClick(View arg0) {

    AsyncAction object = new AsyncAction();
    final String salida_dato;


switch (arg0.getId()) {

    case R.id.toggleButton:


        if (toggleButton.isChecked()) {

            object.conexion_socket();


        }

        if (!toggleButton.isChecked()) {

            object.desconexion_socket();

        }


        break;

    case R.id.ledOnButton:


        if ((MainActivity.toggleButton.isChecked())) {

            object.ledOnButton();
        }

        break;

    case R.id.ledOffButton:

        if ((toggleButton.isChecked())) {

            object.ledOffButton();
        }

        break;

    case R.id.statusButton:

这里我尝试向服务器发送一个“D”字符串

        if ((toggleButton.isChecked())) {


            if (clientSocket != null && os != null && is != null) {

                try {

                    final String responseLine;
                    //    String data = "D";
                    //os.write(data.getBytes());
                 os.println("D");


                    while ((responseLine = is.readLine()) != null) {
                        System.out.println(responseLine);


                        runOnUiThread(new Runnable() {
                            public void run() {
                                MainActivity.prueba.setText(responseLine);
                                os.flush();

                            }
                        });

                        break;


                    }

                    os.close();
                    is.close();
                    clientSocket.close();

                } //fin try

                catch (UnknownHostException e) {
                    System.err.println("Trying to connect to unknown host: " + e);
                } catch (IOException e) {
                    System.err.println("IOException:  " + e);
                }

这里的连接是在后台使用 asynchTasks 运行的(我想是的)

    @Override
    protected String doInBackground(Void... args) {

        conexion_socket();

        ...


    }//fin doInBackground

这是我用来创建套接字连接的连接方法

public void conexion_socket(){

        try {

            MainActivity.clientSocket = new Socket("192.168.2.80", 30000);

            try {

                MainActivity.os = new PrintStream(MainActivity.clientSocket.getOutputStream());
                MainActivity.is = new DataInputStream(MainActivity.clientSocket.getInputStream());
                MainActivity.inputLine = new DataInputStream(new BufferedInputStream(System.in));

            } // fin try

            catch (IOException e){

                System.err.println("algo anda al con los i/o ...");

            } // fin catch




        } catch (IOException e) {
            e.printStackTrace();
        }
        if (MainActivity.clientSocket.isConnected()) {
            MainActivity.statusEditText.setText("OK connection");
        }
    }

如果有人能提供一种方法来进行这种交流,我将不胜感激!

【问题讨论】:

    标签: java android sockets communication


    【解决方案1】:
    if(myServer.isBound() == true){
    

    此时这不可能是错误的。删除 test 和 else 块。您使用端口号构造了ServerSocket => 它已绑定。

            else{
            System.err.println("[E R R O R] : No se pudo crear 'LISTEN SOCKET'");
            System.exit(0);
            }
    

    无法访问。删除。

            while(true){
            System.out.println("Esperando algún cliente TCP en el puerto ["+portNumber+"]...");
            myClient = myServer.accept();
            if (myClient.isConnected()) { // if2
    

    再一次,这不可能是假的。您接受了套接字 => 它已连接。不要编写无用的测试。

            System.out.println("[D A T A] : El cliente ha sido aceptado IP-CLIENT\n"+""+ "IP Client address: "+myClient.getInetAddress());
            DataOutputStream outClient = new DataOutputStream(myClient.getOutputStream());
            DataInputStream inClient = new DataInputStream(myClient.getInputStream());
            msj_ToServer = inClient.readLine();
            System.out.println("Ha1 "+msj_ToServer);
            try{
    
            if(msj_ToServer.equalsIgnoreCase("D")) {
            System.out.println("HO "+msj_ToServer);
            outClient.writeBytes("ON");
    

    这里你写的是字节,但没有行终止符。客户端对应的代码使用readLine(),所以会永远阻塞。向该字符串添加行终止符。

            outClient.flush();
    

    冗余。消除。 DataOutputStream 没有缓冲,Socket.getOutputStream() 也没有,因此刷新它们中的任何一个都不起作用。

            }catch(IOException e){
             e.printStackTrace();
             }
    
            if(msj_ToServer == "B" || msj_ToServer == "b"){
    
               System.out.println(msj_ToServer);
               outClient.writeUTF("OFF");
    

    下定决心。你写的是字节、行还是writeUTF()使用的特殊格式?客户端中对应的代码使用readLine()。我建议您标准化编写行以供readLine()writeUTF()/readUTF() 阅读。你不能混合它们。

               outClient.flush();
    

    见上文。删除。

               if(msj_ToServer == "C" || msj_ToServer == "c"){
               System.out.println(msj_ToServer);
               outClient.writeUTF("xd");
    

    见上文。

               outClient.flush();
    

    见上文。

            MainActivity.clientSocket = new Socket("192.168.2.80", 30000);
    
            try {
    
                MainActivity.os = new PrintStream(MainActivity.clientSocket.getOutputStream());
                MainActivity.is = new DataInputStream(MainActivity.clientSocket.getInputStream());
                MainActivity.inputLine = new DataInputStream(new BufferedInputStream(System.in));
    
            } // fin try
            catch (IOException e){
                System.err.println("algo anda al con los i/o ...");
            } // fin catch
    

    没有理由将这些代码行放在 try 块中。你已经在里面了。

        if (MainActivity.clientSocket.isConnected()) {
    

    在这一点上,这个测试再一次不可能是假的。如果套接字已构建,则它已连接。

    但是,由于您的异常处理结构不正确,它可能为 null。紧随其后的块应该在前面的封闭 try 块内。

    一般来说,你应该去掉所有内部的try/catch 块。取决于先前try 块中代码成功的代码应该在该try 块内。

    【讨论】:

    • 非常感谢!!我会听从你的建议和建议,我会让你知道我的结果!!我期待着我是否最终得到沟通:) 谢谢sss
    猜你喜欢
    • 2018-01-06
    • 1970-01-01
    • 1970-01-01
    • 2012-06-05
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 2017-02-25
    • 2012-06-24
    相关资源
    最近更新 更多