Значение мусора при обмене данными с использованием сокета от python до Android - PullRequest
0 голосов
/ 11 июля 2020

В настоящее время у меня есть сервер (python) и клиент (android). Я пытаюсь отправить данные с android на сервер другому Android с помощью сокета. Проблема в том, что данные на сервере выглядят нормально, но при получении Android данных с сервера добавляется мусор. Если я менял размер строки, она иногда не получала данные, а после дополнительных отправок получалось странное значение мусора. Я думаю, что это какая-то проблема, связанная с буфером, но я не мог определить точную проблему.

Это вывод с сервера: outputFromServer

Это вывод из android: outputFrom Android

Это server.py. Я получаю данные от клиента и отправляю их другим клиентам.

import socket
import time
import select

host = 'myIP' # Symbolic name meaning all available interfaces
port = myPortNumber # Arbitrary non-privileged port
 

server_sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#socket.SOCK_STREAM
server_sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)#assure reconnect
server_sock.bind((host, port))
server_sock.listen(5)
print(server_sock)
sockets_list = [server_sock]#socket list... multiple clients 

clients = {}#socket is the key, user Data will be value 

print("Waiting")

def receive_message(client_socket):
    try:
        data = client_socket.recv(1024)
        print("receive Message : " +data.decode('utf-8'))
        #return data.decode('utf-8')
        return {"data" : data}

    except:
        return False



while True:
    read_sockets, _, exception_sockets = select.select(sockets_list, [], sockets_list)#read, write ,air on 

    for notified_socket in read_sockets:
        if notified_socket == server_sock: #someone just connected 
            client_socket, client_address = server_sock.accept()
            print(client_socket)
            print(client_address)

            user = receive_message(client_socket)
            if user is False:
                print("USER FALSE")
                continue

            sockets_list.append(client_socket)

            clients[client_socket] = user 
            print("ACCEPTED connection")
        

        else: 
            message = receive_message(notified_socket)
            print("IN ELSE : " + message['data'].decode('utf-8'))
            if message is False :
                sockets_list.remove(notified_socket)
                del clients[notified_socket]
                continue

            user = clients[notified_socket]

            #share this message with everyBody

            for client_socket in clients:
                print("for loop")
                if client_socket != notified_socket:
                    message_to_send = message['data']
                    client_socket.send(len(message_to_send).to_bytes(2, byteorder='big'))
                    client_socket.send(message_to_send)


    for notified_socket in exception_sockets:
        sockets_list.remove(notified_socket)
        del clients[notified_socket]

Вот мой Android (java) код для клиента

package com.example.testing;

import android.util.Log;
import android.view.View;
import android.widget.Button;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

public class ConnectTcp {

    private String TAG = "tcp";
    private DataOutputStream dos;
    private DataInputStream dis;
    private Socket socket;
    private Thread socketThread;

    public ConnectTcp() {

    }//connectTcp

    void sendMessage(final String message){
         socketThread = new Thread() {
             public void run(){
                try {
                    if (Thread.interrupted()) { throw new InterruptedException();}
                    while(!Thread.currentThread().isInterrupted()) {
                        // ...
                        try {
                            socket = new Socket(remoteIP, port);
                            Log.e(TAG, "success");
                        }catch (IOException ioe) {
                            Log.e(TAG,"ERROR");
                        
                        try {

                            dos = new DataOutputStream(socket.getOutputStream());   // output
                            dis = new DataInputStream(socket.getInputStream());     // inpu
                            dos.writeUTF("CONNECT TO SERVER : "+ message);

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

                        while(true) {
                          
                            try {
                               
                                while (true) {
                                
                                    line = (String) dis.readUTF();
                                    Log.w("------서버에서 받아온 값", "" + line);

                                    
                                }
                            } catch (Exception e) {

                            }
                        }
                    }
                } catch (InterruptedException consumed){
                /* Allow thread to exit */
                }



            }//run
        };//Thread

        socketThread.start();
    }

    void sendAdditionalMessage(final String data) throws IOException {
        Thread sendMessageThread = new Thread() {
            @Override
            public void run() {
                super.run();
                try {
                    dos = new DataOutputStream(socket.getOutputStream());
                    dos.writeUTF(data);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        };

        sendMessageThread.start();
    }


    void closeSocket() throws IOException {
        socket.shutdownInput();
        socket.shutdownOutput();
        socket.close();
        socketThread.interrupt();
    }


}//class

Это MainActivity. java

package com.example.testing;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Handler;

import okhttp3.FormBody;
import okhttp3.RequestBody;

public class MainActivity extends AppCompatActivity {

    String getData;
    TextView textView;
    Button bt_connect;
    Button bt_disConnect;
    TextView tv_hanium;
    int data = 10;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bt_connect = findViewById(R.id.bt_connect);
        bt_disConnect = findViewById(R.id.bt_cancel);
        Button bt_goToLogin = findViewById(R.id.bt_goToLogin);
        final Button bt_send = findViewById(R.id.bt_send);

        final ConnectTcp connectTcp = new ConnectTcp();

        bt_connect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            
                connectTcp.sendMessage("hello world");//connect to server

            }
        });

        bt_disConnect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    connectTcp.closeSocket();//close socket
                } catch (IOException e) {
                    Log.d("tcp", "fail to close ");
                    e.printStackTrace();
                }
            }
        });//데이터 전송 중단
        bt_send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    connectTcp.sendAdditionalMessage("150");// send data
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

       
        bt_goToLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent goToLogin = new Intent(MainActivity.this, LoginActivity.class);
                MainActivity.this.startActivity(goToLogin);
            }
        });


    }



}

1 Ответ

0 голосов
/ 11 июля 2020

Метод Java DataOutput.writeUTF отправляет длину записываемой строки. Если вы не хотите изменять сторону Java, вам необходимо изменить функцию receive_message Python, чтобы читать поле длины. Вот начало:

def receive_message(client_socket):
    try:
        data = client_socket.recv(2)
        # TODO: ensure 2 bytes were returned
        expected_length = int.from_bytes(data, byteorder="big")

        data = client_socket.recv(expected_length)
        if len(data) < expected_length:
            # TODO: add a loop to read more data from the socket
            pass

        # TODO: write your own "modified utf-8" decoder - see
        # https://docs.oracle.com/javase/8/docs/api/java/io/DataInput.html
        print("receive Message : " + data.decode('utf-8'))

Java DataOutput и DataInput на самом деле не предназначены для общего ввода / вывода и, как вы обнаружили, затрудняют интеграцию с другими языками программирования. На вашем месте я бы рассмотрел возможность перехода на другой протокол, например, основанный на чтении и написании строк текста.

...