I'm receiving an image through a socket in an android aplication, I did debugging and when I'm going to save the image in Drawable d, the program waits for something happens.
I think it has to have relation with clientSocket.getInputStream(); or with the socket.
I have a multithreading server in C++ and when I stop the server, the android aplication continues and I can see the image I sent before. But, I think it's not a server problem, because the socket in the server send the data and shows the message printf("Bytes enviados %d\n", bytesEnviados); which is at the end of the server code.
Here you have the code:
public Drawable mandaMensajeVideo(String mensaje, String ip, int puerto ) throws IOException{
Socket clientSocket = new Socket(ip, puerto);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
outToServer.writeBytes(mensaje);
outToServer.flush();
InputStream inputStream = clientSocket.getInputStream();
Drawable d = Drawable.createFromStream(inputStream, null);
clientSocket.close();
outToServer.close();
return d;
}
Thanks!
Sounds like the end of the inputStream is never reached, as you never properly close the communication.
Related
Working on a project where an Android client communicates with a .Net server via sockets.
It can pass text messages without issue.
It now needs to be expanded to pass an jpeg image.
The server side code:
Dim fs As FileStream = New FileStream(imagePath, FileMode.Open)
Dim br As BinaryReader = New BinaryReader(fs)
sendBytes = br.ReadBytes(fs.Length)
logger.Debug("sending " & sendBytes.Length & " bytes")
clientStream.Write(sendBytes, 0, sendBytes.Length)
clientStream.Flush()
clientStream.Close()
The Android client code:
message send / receive
socket = new Socket(dstAddress, dstPort);
DataOutputStream writer = new DataOutputStream(socket.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
byte[] outputBytes = requestString.getBytes();
writer.write(outputBytes);
Log.d(method, "Message sent: " + requestString);
while ((responseString = reader.readLine()) != null) {
response += responseString + "\n";
}
reader.close();
writer.close();
socket.close();
then trying to reconstruct the image from the response:
byte[] imageBytes = reponse.getBytes();
Log.d(method, "imageBytes.length: " + imageBytes.length);
ByteArrayInputStream is = new ByteArrayInputStream(imageBytes);
ImageView imageV = new ImageView(activity);
imageV.setImageBitmap(BitmapFactory.decodeStream(is));
LogCat error message is: SkImageDecoder::Factory returned null
PLUS the server log says it sent 14548 bytes,
BUT the client log says it received 25294 bytes.
An encoding issue?
I tried adding encoding to the server BinaryReader, no luck.
I also tried on the client side:
imageV.setImageBitmap(BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length));
I have spent hours looking through dozens of posts, I also tried other changes I can't even remember.
but, always "Factory returned null"
What am I doing wrong?
Edit----
Tried changing to
byte[] imageBytes = Base64.decode(response, Base64.DEFAULT)
That generated: IllegalArgumentException: bad base-64
You cannot use readLine() to read the bytes of an image.
Declare a buffer and in a loop read() bytes in the buffer and save them.
You cannot use intermediate Strings either.
If the server only sends an image you could even use
imageV.setImageBitmap(BitmapFactory.decodeStream(socket.getInputStream()));)
variable of position in inputstream may be set to 1024 after the first decode. So add inputstream.reset() before the second decode. Hope that works.
I did a script to exchange data between a client and a server with socket on specific port.
In order, I am expecting:
Server is listening
Client opens a socket
Server akwnoledges by sending a int -> never received !
I just noticed that my client receives the int, when I quit the server brutally
Here is my (simple) code.
Client:
Socket socket = new Socket(SERVER_ADDR, PORT);
DataOutputStream dOut = new DataOutputStream(socket.getOutputStream());
DataInputStream dIn = new DataInputStream(socket.getInputStream());
Log.v("[DEBUG]", "waiting aknowledgement");
status = dIn.readInt(); //<-- BLOCKS HERE
Log.v("[DEBUG]", "ack"); //<-- RECEIVED WHEN SERVER IS EXITED
Server:
try {
DataInputStream stdIn = new DataInputStream(client.getInputStream());
DataOutputStream stdOut = new DataOutputStream(client.getOutputStream());
while (incoming) {
stdOut.writeInt(1);
stdOut.flush();
System.out.println("Waiting...");
var_from_client = stdIn.readInt(); //<-- BLOCKS HERE (BECAUSE CLIENT IS BLOCKED)
// ...
}
} catch (Exception e) {}
How to explain this error?
'Socket not flushing data' has exactly nothing to do with it. This is a deadlock, caused by a bug in your application.
Your server sends an int.
Your client receives the int.
Your server blocks trying to read another int.
Your client doesn't send an int.
The server can never send another int because it is blocked waiting for the non-existent reply int.
Your client blocks while trying to receive another int because the server is blocked from sending it.
Solution: send the int from the client.
Notes:
Flushing the output stream of a socket does nothing, and neither does flushing a DataOutputStream wrapped directly around it.
NEVER ignore exceptions.
I'm trying to send some commands to Android (client) from VB.NET (server) using sockets. I can connect the client to the server, but I don't know how to receive the commands sent by the server.
Here's a part of my Android code:
public void connect(View v){ //called on button click
SERVER_IP = ip.getText().toString(); //it gets the server's ip from an editText
SERVER_PORT = Integer.parseInt(port.getText().toString()); //and the port too
Toast.makeText(this, "Trying to connect to\n" + SERVER_IP + ":" + SERVER_PORT + "...", Toast.LENGTH_SHORT).show();
new Thread(new Runnable() {
public void run() {
InetAddress serverAddr;
try {
serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVER_PORT); //It establishes the connection with the server
if(socket != null && socket.isConnected()){ //not sure if it is correct
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//Here comes the problem, I don't know what to add...
}
} catch (Exception e) {
}
}
}).start();
}
And here's a part of my VB.NET send code:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
send(TextBox1.text)
End Sub
Private Sub Send(ByVal command)
Dim temp() As Byte = UTF8.GetBytes(command) 'Is UTF8 right to use for that?
stream.Write(temp, 0, temp.Length)
stream.Flush()
End Sub
Question1: is it right to us UTF8 instead of for example ASCII encoding?
Question2: what would I change in the Android code if it wanted to use a timer that sends a command every second?
Thanks.
To read input from a BufferedReader you need to do something similiar to this:
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while((line = input.readLine()) != null){
// do something with the input here
}
A nice tutorial on sockets is available from oracle in the docs: http://docs.oracle.com/javase/tutorial/networking/sockets/readingWriting.html
The default charset on Android is UTF-8 http://developer.android.com/reference/java/nio/charset/Charset.html, so no worries there but you can always send a byte stream from the server onto the client and decode it however you want.
To receive a byte stream you need to do this:
BufferedInputStream input = new BufferedInputStream(socket.getInputStream());
byte[] buffer = new byte[byteCount];
while(input.read(buffer, 0, byteCount) != -1 ){
// do something with the bytes
// for example decode it to string
String decoded = new String(buffer, Charset.forName("UTF-8"));
// keep in mind this string might not be a complete command it's just a decoded byteCount number of bytes
}
As you see it's much easier if you send strings instead of bytes.
If you want to receive input from the server periodically, one of the solutions would be to create a loop which opens a socket, receives input, process it, closes the socket, and then repeats, our you could just keep the loop running endlessly until some command like "STOP" is received.
I am currently trying to open a socket in android, but my code keeps sticking at one sentence.
private ServerSocket serverSocket;
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public void run(){
Log.i("DebugMessage", "ServerThread received pulse. Trying to open socket now!");
try{
serverSocket = new ServerSocket(25555);
Log.i("DebugMessage", "serverSocket is open, waiting for the clientSocket.");
clientSocket = serverSocket.accept();
Log.i("DebugMessage", "serverSocket and clientSocket are both open! Waiting for in-/output!");
in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
out = new PrintWriter(clientSocket.getOutputStream(), true);
String input = in.readLine();
out.println("received: " + input);
in.close();
out.close();
} catch(Exception e) {
Log.i("DebugMessage", "Failed to open socket!");
e.printStackTrace();
}
}
At clientSocket = serverSocket.accept(); it keeps sticking.
Now I have seen this question a few other times, but the answers given were totally different.
Here is being said that it is about his code, and here is being said that the problem is with the emulator. Now my question is, is my problem with the emulator or my code, and if it is with my code, how is it possible to fix it?
By the way, I have added these lines to AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" >
</uses-permission>
The answer of FD_ is correct but i want to clarify it a bit. accept() calls wait(). So the thread will wait for a connection.
You may want to call such code from a other thread.
ServerSocket.accept() waits until a device connects to the socket's port (25555 in your case) on your device's ip address. It will only proceed and return a Socket when there is a new connection.
You'll find more information in the docs.
I've got Android device acting as a client, the PC is a Bluetooth Server, using Bluecove library
Code snippet from the client:
btSocket = serverBt.createRfcommSocketToServiceRecord(myUuid);
btAdapter.cancelDiscovery();
btSocket.connect();
InputStream in = btSocket.getInputStream();
OutputStream out = btSocket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(out);
InputStreamReader isr = new InputStreamReader(in);
osw.write(55);
osw.flush();
out.flush();
//osw.close();
logTheEvent("Stuff got written, now waiting for the response.");
int dummy = isr.read();
logTheEvent("Servers response: "+ new Integer(dummy).toString());
And the server:
StreamConnectionNotifier streamConnNotifier = (StreamConnectionNotifier)Connector.open( connectionString, Connector.READ_WRITE );
StreamConnection incomingConnection=streamConnNotifier.acceptAndOpen();
InputStream in = incomingConnection.openInputStream();
OutputStream out = incomingConnection.openOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(out);
InputStreamReader isr = new InputStreamReader(in);
int fromClient = isr.read();
System.out.println("Got from client " + new Integer(fromClient).toString());
osw.write(999);
When the osw.close(); at the client is uncommented, the message gets transferred to the server, however, client is then unable to receive the response, IOException with message "socket already closed" is thrown.
However, when osw.close(); is commented, both client and server freeze:
A. Client hangs on reading server's response of course
B. Server hangs on streamConnNotifier.acceptAndOpen();
What should be done to enable two-way communication?
Is my code, or PC Bluetoototh stack, or bluecove to blame?
Bluetooth uses buffered output. That means there is a small memory location that contains all of the data you write to the stream. When this memory location gets full, it writes the buffer data to the socket in a packet. When you prematurely close the socket, that buffer gets wiped, and the data is gone.
In order to force the stream to write, try calling flush()
Something else you could do is set the buffer size to be very small, so data always gets written. The performance won't be very good if you do this, though.
Unfortunately, I don't have all of the code I wrote, but there's a base project here