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.
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 have a wireless device communicating over port 22 connected to my network. Once the device starts up, it immediately starts sending log data. Once this device is sent a command, it stops logging and responds accordingly. This all works, I have tested it using a telnet client.
My problem is that I can't seem to send it a command properly in my app. I am reading the log data as planned, but when I send it a command, in this case the command "r", it continues outputting log data instead what it should be showing me for that particular command. This has to mean that I am not properly sending the command. This is my code for the task that sends it the command and logs the output in the android logcat:
public class ReceiveVarTask extends AsyncTask<Void, Void, Void>{
String dstAddress;
int Port;
ReceiveVarTask(String addr, int port) {
dstAddress = addr;
Port = port;
}
protected Void doInBackground(Void... vars){
Socket socket = null;
String command = "r";
try {
Log.i(TAG, "Connecting to port 22");
socket = new Socket(dstAddress, Port);
Log.i(TAG, "Connected to port 22");
PrintWriter writer = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
InputStream inputStream = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
writer.println(command);
String line = reader.readLine();
Log.i(TAG, line);
while(line!=null && !isCancelled()){
line = reader.readLine();
Log.i(TAG, line);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
protected void onPostExecute(Void arg) {
taskRunning = false;
}
}
What am I doing wrong? Why is it not registering the command?
UPDATE:
I have used several telnet clients for testing, and the server is reading the 'r' command as expected on some. It works using a windows telnet client, and it works using the vSSH app by Velestar. Interestingly enough, when testing this with the android telnet client by ClockworkMod, the server is not registering the command either.
Could it be something to do with encoding?
Do I need any additional permissions to work with sockets? I have android.permission.INTERNET declared in the manifest.
UPDATE 2:
The developer of of the hardware just told me that the hardware is expecting the command to be ASCII encoded and CR terminated. So I will try changing PrintWrite initialization to:
PrintWriter writer = new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream(), "ASCII")), true);
and the print command to:
writer.print(command+"\r");
Changing the the encoding type to "US-ASCII" and adding a carriage return instead of a new line did the trick. I'm able to read and write data as expected.
From my understanding of your problem description, you have a telnet server, and when a telnet client connects to that server, the server start sending the client log data. The client may send an "r" to the server to stop the log stream.
I suggest you first confirm using another telnet client that sending an "r" does stop the server from generating more log data.
You could use Wireshark to check if the "r" command is indeed sent.
I try to write an app that sends text from Windows computer to Android cellphone.
The text I send can be in English or Hebrew (for example). The connection is via Socket. The code I use on the Windows side (Visual studio 2012):
String buffer = // Some text
// Encode the data string into a byte array.
byte[] msg = Encoding.ASCII.GetBytes(buffer + "\n");
// Send the data through the socket.
int bytesSent = socketSender.Send(msg);
And on the Android side:
//After I establish the Socket
String text = "";
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader in = new BufferedReader(isr);
while ((inputText = in.readLine()) != null)
{
text = inputText;
}
All this works perfectly when sending English text.
When I try to send Hebrew text I replace to this line:
byte[] msg = Encoding.Unicode.GetBytes(buffer + "\n");
But on the Android side I can't "read" it.
I tried to use CharsetEncoder but didn't work (or I did it the wrong way).
Any ideas?
Ok, so the answer is:
on the Windows side:
byte[] msg = Encoding.UTF8.GetBytes(buffer + "\n");
And on the Android side:
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
I'm trying to Execute an interactive binary file on my android tablet.
I can execute the server binary just fine and its working perfectly.
But I need to interact with it on a CLI at a specified port where I need to send it a command and receive the response, process the response and send another command as reply.
eg:
$nc 192.168.1.1 8111
>Connected to CLI
$Request Server Status
>Server Sending File to Client X
$Stop Server
>Server Stopped
Where $command represents commands I sent and >command is the reply from server.
So to test this I tried the below function :-
private String TryExecuteCommand(String command) {
try {
proc = Runtime.getRuntime().exec("nc 127.0.0.1 8888");
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
int read;
char[] buffer1 = new char[4096];
StringBuffer output = new StringBuffer();
DataOutputStream writer = new DataOutputStream(proc.getOutputStream());
writer.writeBytes("continuous responses" + "\n");
Thread.sleep(2000);
writer.writeBytes("quit" + "\n");
while ((read = reader.read(buffer1)) > 0)
output.append(buffer1, 0, read);
proc.waitFor();
reader.close();
if (dataLines.length > 0)
return dataLines.toString();
else
return "";
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "Error occured";
}
With this code I'm able to get the output after the "quit" command is issued. But if i try to read the response before quit is issued I get the EPIPE broken error.
Any help is appreciated :)
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.