Cómo enviar datos a través de socket en java

Estoy haciendo una aplicación android simple para enviar cadena al servidor (creado en python). Me estoy conectando al servidor usando socket en hilo separado como Mostrar en código. Quiero enviar la cadena en el botón de clic. Este es el código java:

public class MainActivity extends AppCompatActivity {

private Socket socket;
Button btn;

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

    new Thread(new ClientThread()).start();

    btn = (Button) findViewById(R.id.button);
    if (socket != null){
        try {
            OutputStream output = socket.getOutputStream();
            PrintWriter writer = new PrintWriter(output, true);
            writer.println("1");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class ClientThread implements Runnable{
    @Override
    public void run() {
        try {
            socket = new Socket("192.168.0.12", 80);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Y este es mi servidor python

import socket

host = socket.gethostbyname(socket.gethostname())
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, 80))

print("ip = ", host)

s.listen(1)
print("Listening")

while True:
    conn, addr = s.accept()
    print(addr, " connected to us")
    conn.sendall(bytes("Hello", "utf-8"))
    while True:
        try:
            data = bytes.decode(conn.recv(1024), "utf-8")
            print(data)
        except:
            break
    
    

y esto es la salida del servidor

ip =  192.168.0.12
Listening
('192.168.0.6', 45903)  connected to us

Por favor, déme su sugerencia de enviar datos al servidor

Pregunta hecha hace 3 años, 5 meses, 0 días - Por phpphoenix


4 Respuestas:

  •     Socket s = new Socket("address",port);
        OutputStream os = s.getOutputStream();
        //do write
        os.close();
        s.shutdownOutput();
    

    Cuando quieras usar el socket la próxima vez,Regrésala y conéctate.

    s.shutdownOutput() 
    

    Este método escribe datos al servidor cuando lo invocó;

    Respondida el Dec 17, 2020 a las 07:51 - por codechampion

    Votos positivos: 0 | Votos negativos: 0

  • Después de tanta investigación encontré solución para mi problema. Aquí estoy compartiendo mi código

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn = (Button) findViewById(R.id.button);
        btn2 = (Button) findViewById(R.id.button2);
    
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new UPThread()).start();
            }
        });
    
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new DOWNThread()).start();
            }
        });
    
    }
    private PrintWriter output;
    private BufferedReader input;
    class UPThread implements Runnable{
        @Override
        public void run() {
            try {
                socket = new Socket("192.168.43.235", 80);
                output = new PrintWriter(socket.getOutputStream());
                output.write("UP");
                output.flush();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    class DOWNThread implements Runnable{
        @Override
        public void run() {
            try{
                socket = new Socket("192.168.43.235", 80);
                output = new PrintWriter(socket.getOutputStream());
                output.write("DOWN");
                output.flush();
                socket.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
    

    Ejecuto el hilo en el botón haga clic para que sea fácil enviar instrucciones sencillas a mi proyecto IOT

    Respondida el Dec 17, 2020 a las 07:58 - por devninjax

    Votos positivos: 0 | Votos negativos: 0

  • El problema en tu código es que estás intentando enviar datos al servidor directamente en el onCreate de tu actividad, lo cual no es la forma adecuada de enviar datos a través de un socket en Android.

    Lo que debes hacer es mover el envío de datos al servidor al momento en que se haga clic en el botón. Para hacer esto, primero necesitas crear un listener para el botón y en ese listener realizar la comunicación con el servidor.

    Aquí te dejo un ejemplo de cómo podrías modificar tu código para lograr esto:

    java
    public class MainActivity extends AppCompatActivity {
    
        private Socket socket;
        private PrintWriter writer;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            new Thread(new ClientThread()).start();
    
            Button btn = findViewById(R.id.button);
            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (socket != null && writer != null) {
                        writer.println("1");
                    }
                }
            });
        }
    
        class ClientThread implements Runnable{
    
            @Override
            public void run() {
                try {
                    socket = new Socket("192.168.0.12", 80);
                    OutputStream output = socket.getOutputStream();
                    writer = new PrintWriter(output, true);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    Con este cambio, el envío de datos se realizará al hacer clic en el botón. Además, he declarado el PrintWriter como un atributo de la clase para que pueda ser utilizado en cualquier parte de la actividad.

    Ten en cuenta que es importante manejar excepciones adecuadamente en caso de que la conexión falle o ocurra algún otro problema. También, recuerda cerrar los sockets y liberar recursos apropiadamente cuando ya no los necesites.

    Respondida el Dec 18, 2020 a las 07:51 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Solución 1: Utilizar un Handler

    Puedes utilizar un Handler para publicar mensajes desde el hilo del socket al hilo principal, lo que te permitirá actualizar la interfaz de usuario. Aquí tienes el código actualizado:

    java
    public class MainActivity extends Activity {
    
        private Socket socket;
        private Button btn;
        private Handler handler;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            handler = new Handler(Looper.getMainLooper());
    
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        socket = new Socket("192.168.0.12", 80);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
    
            btn = (Button) findViewById(R.id.button);
            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (socket != null){
                        try {
                            OutputStream output = socket.getOutputStream();
                            PrintWriter writer = new PrintWriter(output, true);
                            writer.println("1");
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
        }
    
        @Override
        protected void onResume() {
            super.onResume();
    
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        InputStream input = socket.getInputStream();
                        BufferedReader reader = new BufferedReader(new InputStreamReader(input));
    
                        String line;
                        while ((line = reader.readLine()) != null) {
                            // Recibe mensajes del servidor y los muestra en el hilo principal usando el Handler
                            Message msg = new Message();
                            msg.obj = line;
                            handler.sendMessage(msg);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    
        @Override
        public void handleMessage(Message msg) {
            // Actualiza la interfaz de usuario con el mensaje recibido del servidor
            String message = (String) msg.obj;
            // Actualiza la interfaz de usuario en consecuencia
        }
    }
    

    Solución 2: Utilizar un AsyncTask

    También puedes utilizar un AsyncTask para realizar la comunicación con el servidor en segundo plano y luego actualizar la interfaz de usuario en el hilo principal. Aquí tienes el código actualizado:

    java
    public class MainActivity extends Activity {
    
        private Socket socket;
        private Button btn;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            btn = (Button) findViewById(R.id.button);
            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    new MyAsyncTask().execute();
                }
            });
        }
    
        private class MyAsyncTask extends AsyncTask {
    
            @Override
            protected String doInBackground(Void... voids) {
                try {
                    socket = new Socket("192.168.0.12", 80);
                    OutputStream output = socket.getOutputStream();
                    PrintWriter writer = new PrintWriter(output, true);
                    writer.println("1");
    
                    InputStream input = socket.getInputStream();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(input));
                    return reader.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                    return null;
                }
            }
    
            @Override
            protected void onPostExecute(String result) {
                // Actualiza la interfaz de usuario con el resultado recibido del servidor
            }
        }
    }
    

    Respondida el Dec 18, 2020 a las 08:01 - por Gemini

    Votos positivos: 0 | Votos negativos: 0