【发布时间】:2019-05-03 12:42:00
【问题描述】:
我正在尝试使用 Python 3 从我的 Raspberry Pi 将照片发送到我的 Android 设备。我通过 TCP 执行此操作,Pi 作为客户端,Android 设备作为我的服务器。我的目标是将照片文件从 Pi 发送到我的 Android 设备。然后,我的 Android 设备将解码该照片数据,然后将其设置为我的应用程序中 ImageView 的可绘制对象。请注意,我发送的是 640x480 的 200kB 图像。
我尝试了一种设置,让 Pi 通过 TCP 将文本发送到我的 Android 设备,我已经成功了。
接下来我尝试将照片从 Python3 客户端发送到 Python3 服务器。在这种情况下,我仍然使用 Pi 作为我的客户端,我使用我的 MacOS 笔记本电脑作为服务器。这是我最终使用的代码。
服务器 - MAC 操作系统
import socket # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 11111 # Reserve a port for your service.
s.bind((host, port)) # Bind to the port
f = open('torecv.jpg','wb')
s.listen(5) # Now wait for client connection.
while True:
c, addr = s.accept() # Establish connection with client.
print('Got connection from', addr)
print("Receiving...")
l = c.recv(1024)
while (l):
print("Receiving...")
f.write(l)
l = c.recv(1024)
f.close()
print("Done Receiving")
c.send(b'Thank you for connecting')
c.shutdown(socket.SHUT_RDWR)
c.close() # Close the connection
客户端 - Pi
import socket # Import socket module
import os
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
host = '192.168.254.194' # Get local machine name
port = 6001 # Reserve a port for your service.
CWD_PATH = os.getcwd()
PATH_TO_IMG_DIR = os.path.join(CWD_PATH, 'img_folder', 'test.jpg')
s.connect((host, port))
#s.send(b'Hello Server!')
f = open(PATH_TO_IMG_DIR,'rb')
print('Sending...')
l = f.read(1024)
while (l):
print('Sending...')
s.send(l)
l = f.read(1024)
f.close()
print("Done Sending")
s.shutdown(socket.SHUT_WR)
print(s.recv(1024))
s.close # Close the socket when done
使用此代码,我能够将照片从我的 Pi 传输到我的 MacOS 笔记本电脑。
现在,我使用the code here as reference 将我的照片从我的 Pi 传输到我的 Android 设备。现在,这是我的代码:
服务器 - 安卓
class ServerThread implements Runnable {
public void run() {
Socket socket;
try {
Log.e(TAG, "starting the serverthread at port 6001");
serverSocket = new ServerSocket(6001);
} catch (IOException e) {
Log.e(TAG, "exception in creating server socket: ", e);
e.printStackTrace();
}
while (!Thread.currentThread().isInterrupted()) {
try {
socket = serverSocket.accept();
CommunicationThread commThread = new CommunicationThread(socket);
new Thread(commThread).start();
} catch (IOException e) {
}
}
}
}
class CommunicationThread implements Runnable{
private Socket clientSocket;
private DataInputStream input;//private BufferedReader input;
public CommunicationThread(Socket clientSocket) {
this.clientSocket = clientSocket;
try {
Log.e(TAG, "getting data from the input stream!");
//this.input = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
InputStream in = this.clientSocket.getInputStream();
this.input = new DataInputStream(in);
} catch (IOException e) {
Log.e(TAG, "error in creating data input stream: ", e);
e.printStackTrace();
}
}
public void run() {
Log.e(TAG, "running the code!");
while (!Thread.currentThread().isInterrupted()) {
try {
Log.e(TAG, "parsing the input data stream!");
byte[] data;//String read = input.readLine();
int len= this.input.readInt();
if (len > 0) {
data = new byte[len];
this.input.readFully(data,0,data.length);
}
/*
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] data;
int length = 0;
while ((length = this.input.read(data))!=-1) {
out.write(data,0,length);
}
data=out.toByteArray();
*/
Log.e(TAG, "Updating the UI through a thread!!");
// updateConversationHandler.post(new updateUIThread(data));
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e(TAG, "error in reading sent data! ", e);
e.printStackTrace();
}
}
}
}
为了使用这些类,我将以下内容声明为全局变量:
Thread serverThread = null;
Handler updateConversationHandler;
在我的onCreate() 中,我有以下内容:
updateConversationHandler = new Handler();
this.serverThread = new Thread(new ServerThread());
this.serverThread.start();
应用程序将启动,并且套接字将打开。但是,当我尝试从我的 Pi 发送照片时,我在这段代码中遇到了一个错误:
public void run() {
Log.e(TAG, "running the code!");
while (!Thread.currentThread().isInterrupted()) {
try {
Log.e(TAG, "parsing the input data stream!");
byte[] data;//String read = input.readLine();
int len= this.input.readInt();
if (len > 0) {
data = new byte[len];
this.input.readFully(data,0,data.length);
}
/*
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] data;
int length = 0;
while ((length = this.input.read(data))!=-1) {
out.write(data,0,length);
}
data=out.toByteArray();
*/
Log.e(TAG, "Updating the UI through a thread!!");
// updateConversationHandler.post(new updateUIThread(data));
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e(TAG, "error in reading sent data! ", e);
e.printStackTrace();
}
}
}
class updateUIThread implements Runnable {
private byte[] byteArray;//private String msg;
public updateUIThread(byte[] array){ //public updateUIThread(String str) {
this.byteArray=array; //this.msg = str;
}
@Override
public void run() {
Log.e(TAG, "running the photo update!");
Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray , 0, byteArray .length);
ivBed.setImageBitmap(bitmap);//text.setText(text.getText().toString()+"Client Says: "+ msg + "\n");
}
}
原来是这样一行:
data = new byte[len];
在if(len>0) 条件之外。但是发生的事情是,出于某种原因,Pi 发送了一个负值,当然我们不希望 len 变量有一个负值。当然,当我尝试创建具有负长度的字节数组data 时遇到了错误。然后我将该行置于 if 条件中。
但是,在我这样做之后,我在同一行中遇到了 OOM Error data = new byte[len];
Process: agict.work.freelance.patientsensor, PID: 15224
java.lang.OutOfMemoryError: Failed to allocate a 1677608328 byte allocation with 6291456 free bytes and 254MB until OOM, max allowed footprint 7797480, growth limit 268435456
我有一种预感,在第二个错误中,我试图用一个实际上已经是图像数据的值初始化字节数组,因此出现 OOM 错误。
但是,如果我只取第一个值并将其分配为 len,我有可能得到一个负数,并且代码会遇到第一个错误。
是否有可能我必须进行一些调整才能将照片数据从 Python3 传输到 Android?我感觉正在发生某种格式不匹配的情况。
同样,我的目标是通过 TCP 从 Python3 将照片文件发送到我的 Android 设备。 Python3 将获得一个文件,Android 设备将对它获得的输入进行解码,解码后,将该数据用作 ImageView 的可绘制对象。
【问题讨论】:
标签: android python-3.x sockets tcp file-transfer