I am a beginner in android. I am trying to work on Sockets. But my InputStream is not reading the data as expected. It is getting out of the method after j = inputStream.read(arrayOfByte, 0, i); Please help me.
public void readinputstreamforid(final String ip, final int port){
AsyncTask asyncTask = new AsyncTask() {
#Override
protected Object doInBackground(Object[] objects) {
try {
socket=new Socket(ip,port);
} catch (IOException e) {
e.printStackTrace();
}
final byte[] arrayOfByte = new byte[10000];
InputStream inputStream = null;
try {
inputStream = socket.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
while (socket.isConnected()) {
int j = 0;
int i = arrayOfByte.length;
try {
j = inputStream.read(arrayOfByte, 0, i);
if (j == -1)
throw new IOException("not working");
if (j == 0)
continue;
} catch (IOException e) {
e.printStackTrace();
}
final String strData = new String(arrayOfByte, 0, j).replace("\r", "").replace("\n", "");
Log.d("hello","recieved: "+strData);
}
try {
IOUtils.write("!##\n",socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
};
asyncTask.execute();
}
If an error happens, you are logging it, but then you continue with the code, where more errors can then happen. When an error happens, STOP looping and exit the function. InputStream.read() returns -1 when the end of the stream is reached. For a socket, that means when the connection is closed. That is not really an error condition, so you don't need to throw an exception. Just break the loop. You can wrap the InputStream inside of a BufferedReader so you can use its readLine() method instead of reading bytes manually.
Also, you are trying to write to the socket's OutputStream after the socket has already disconnected. That will never work.
Try something more like this:
public void readinputstreamforid(final String ip, final int port){
AsyncTask asyncTask = new AsyncTask() {
#Override
protected Object doInBackground(Object[] objects) {
try {
socket = new Socket(ip, port);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
OutputDataStream out = socket.getOutputStream();
do {
String data = in.readLine();
if (data == null)
break;
Log.d("hello", data);
IOUtils.write("!##\n", out, StandardCharsets.UTF_8);
}
while (true);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
};
asyncTask.execute();
}
Related
It's my first time working with sockets, in order to get a better understanding of what's going on I decided to build a client server chat application which can support several users.
At first, I used DataInputStream / DataOutputStream to communicate and everything works well. But I would like to switch to an ObjectStream and that's where the problem occurs. Once I replace all the DataInputStream / DataOutputStream by ObjectInputStream / ObjectOutputStream, I'm no longer able to print the retrieved data.
This is the code that I used before, which works (DataStream) :
SERVER:
try {
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeUTF("HI FROM SERVER");
while (!socket.isClosed()) {
try {
if (in.available() > 0) {
String input = in.readUTF();
for (ClientThread thatClient : server.getClients()){
DataOutputStream outputParticularClient = new DataOutputStream(thatClient.getSocket().getOutputStream());
outputParticularClient.writeUTF(input + " GOT FROM SERVER");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
CLIENT:
try {
socket = new Socket("localhost", portNumber);
DataInputStream in = new DataInputStream(socket.getInputStream());
new Thread(()->{
while(!socket.isClosed()){
try {
if (in.available() > 0){
String input = in.readUTF();
System.out.println(getUserName() + " > " + input);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
And this is how I tried to perform the same idea with ObjectStream :
SERVER:
try {
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
while (!socket.isClosed()) {
try {
if (in.available() > 0) {
Message input;
try {
input = (Message)in.readObject();
if (input.equals(null)){
System.err.println("SERVER RETRIEVED NULL OBJECT");
}
for (ClientThread thatClient : server.getClients()){
ObjectOutputStream outputParticularClient = new ObjectOutputStream(thatClient.getSocket().getOutputStream());
outputParticularClient.writeObject(input);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
CLIENT:
try {
socket = new Socket(getHost(), portNumber);
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
new Thread(()->{
while(!socket.isClosed()){
try {
if (in.available() > 0){
Message input = null;
try {
input = (Message)in.readObject();
if (input.equals(null)){
System.err.println("CLIENT RETRIEVED NULL OBJECT");
}
System.out.println("CLIENT " + input.toString());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
I feel like it has something to do with this if statement if (in.available() > 0) but I cannot say precisely what's going on.
available() doesn't do what you may think it does and it is almost never useful in production code (and that's particularly true for ObjectInputStream). The reason you don't receive any data is in fact that in.available() always returns 0 as you already suspected.
As noted in the comments, the StreamCorruptedException is caused by writing to an existing ObjectInputStream that has already been written to using another instance of ObjectOutputStream. Cf. the answer StreamCorruptedException: invalid type code: AC for further explanation.
Here is some quick & dirty example code that has a server echoing the messages from two clients. It's not clean but it may give you an idea how to approach your problem:
public class SO56493162 {
private static final class Message implements Serializable {
private static final long serialVersionUID = 1L;
private static int cnt = 0;
private final int id;
public Message(int id) {
++cnt;
this.id = id;
}
public String toString() {
return "Msg from " + id + " : " + cnt;
}
}
private static final class Client implements Runnable {
private InetSocketAddress addr = null;
private int id = -1;
Client(InetSocketAddress addr, int id) {
this.addr = addr;
this.id = id;
}
public void run() {
int timeout = 3000;
Socket s = null;
try {
s = new Socket();
s.connect(addr, timeout);
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
System.out.println("Client " + id + " connected");
while (true) {
Thread.sleep(new Random().nextInt(2000));
Message hello = new Message(id);
oos.writeObject(hello);
oos.flush();
Message reply = (Message) ois.readObject();
System.out.println("Reply: " + reply.toString());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
s.close();
} catch (Exception ignore) {
}
}
}
}
private static final class Server implements Runnable {
private ServerSocket sock = null;
Server(ServerSocket sock) throws IOException {
this.sock = sock;
}
public void run() {
System.out.println("starting server");
try {
while (true) {
final Socket client = sock.accept();
System.out.println("connection accepted");
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
while (!client.isClosed()) {
try {
Message input = (Message) ois.readObject();
oos.writeObject(input);
oos.flush();
} catch (EOFException eof) {
System.err.println("EOF!");
client.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.setDaemon(true);
t.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String args[]) throws IOException, InterruptedException {
final int port = 9876;
Thread ts = new Thread(new Runnable() {
#Override
public void run() {
try {
new Server(new ServerSocket(port)).run();
} catch (Exception e) {
e.printStackTrace();
}
}
});
ts.setDaemon(true);
ts.start();
InetSocketAddress addr = new InetSocketAddress("localhost", port);
for (int i = 0; i < 2; ++i) {
Client cl = new Client(addr, i);
Thread tc = new Thread(cl);
tc.setDaemon(true);
tc.start();
}
Thread.sleep(10000);
System.err.println("done");
}
}
I EDITED CODE
I'm making file transfer program with java
I have to send 21 files.
my code stops at Client's while loop in run()
(It doesn't print "file receive complete") <- see run() in Client
Server's CODE
class SendFileThread extends Thread {
private ServerSocket fileTransferServerSocket;
private Socket fileTransferSocket;
private BufferedReader requestReader;
private PrintWriter requestAnswerer;
private BufferedOutputStream fileWriter;
private int fileTransferPort = 12345;
public SendFileThread() {
try {
fileTransferServerSocket = new ServerSocket(fileTransferPort);
fileTransferSocket = fileTransferServerSocket.accept();
requestReader = new BufferedReader(new InputStreamReader(fileTransferSocket.getInputStream()));
fileWriter = new BufferedOutputStream(fileTransferSocket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
public void CloseTransferStream() {
try {
requestAnswerer.close();
requestReader.close();
fileWriter.close();
fileTransferSocket.close();
fileTransferServerSocket.close();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
}
public void SendFile(String filename) {
try {
File file = new File(CLIENT_PATH + "/" + filename);
BufferedInputStream fileReader = new BufferedInputStream(new FileInputStream(file));
int packet;
while((packet = fileReader.read()) != -1)
fileWriter.write(packet);
fileWriter.flush();
fileReader.close();
}
catch (IOException ioe) {
System.out.println(ioe.getMessage());
}
//System.out.print(filename + " send complete (" + count + " times)");
}
public void ListenForRequester() {
try {
String input;
while((input = requestReader.readLine()) != null) {
if(input.equals("request file")) {
SendFile(requestReader.readLine());
}
else if(input.equals("end transfer"))
break;
else {
System.out.println("Something wrong");
}
}
}
catch(IOException ioe) {
ioe.getStackTrace();
}
}
public void run() {
ListenForRequester();
CloseTransferStream();
}
}
Client's CODE
class ReceiveFileThread extends Thread {
private Socket fileTransferSocket;
private int fileTransferPort = 12345;
private BufferedInputStream fileReader;
private PrintWriter fileRequester;
public ReceiveFileThread() {
try {
fileTransferSocket = new Socket(serverIP, fileTransferPort);
fileRequester = new PrintWriter(fileTransferSocket.getOutputStream(), true);
fileReader = new BufferedInputStream(fileTransferSocket.getInputStream());
}
catch (UnknownHostException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
public void CloseTransferStream() {
try {
fileRequester.close();
fileReader.close();
fileTransferSocket.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
public synchronized void RequestFile(String filename) {
fileRequester.println("request file");
fileRequester.println(filename);
}
public synchronized void SendEndMsg() {
fileRequester.println("end transfer");
}
public void run() {
for(int i = 0;i < fileList.size();i++) {
String filename = (String)fileList.get(i);
RequestFile(filename);
try {
BufferedOutputStream fileWriter = new BufferedOutputStream(new FileOutputStream(new File(PROGRAM_PATH + "/" + filename)));
int packet = 0;
while((packet = fileReader.read()) > -1)
fileWriter.write(packet);
System.out.println("file receive complete");
fileWriter.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
SendEndMsg();
CloseTransferStream();
}
}
It became 5 days that this error bothers me :(
Could anyone save me from this error?
Closing the socket's output stream will close the socket, In order to send multiple files you will have to make a couple of changes.
Server:
Before you start to send a file, send that file's length.
Client:
After you receive the file's length start to read that many bytes from the input stream and save them to a file, when you're done read the next file's length.
Well, I want to write a simple java client-server-programme, which exchanges byte arrays over tcp-sockets.
/* Server */
public class Server {
private ServerSocket Server = null;
private Socket Client = null;
public static void main(String[] args) {
Server A = new Server();
A.runServer();
A.listenServer();
}
public void runServer() {
try {
Server = new ServerSocket(1234);
}
catch (Exception e) {
System.out.println("Server fault: "+ e.getMessage());
System.exit(-1);
}
}
public void listenServer() {
try {
while (true) {
System.out.println("Waiting...");
Client = Server.accept();
System.out.println("Got something new");
readMessage(Client);
}
}
catch (Exception e) {
System.out.println("Server fault: "+ e.getMessage());
}
}
public byte [] readMessage (Socket socket) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1];
int len = -1;
while((len = socket.getInputStream().read(buf))!=-1){
baos.write(buf, 0, len);
}
for (int i=0; i<baos.toByteArray().length; i++) {
System.out.println(baos.toByteArray()[i]);
}
return baos.toByteArray();
}
catch (Exception e) {
System.out.println("Server fault: "+ e.getMessage());
}
return null;
}
public void writeMessage (Socket socket, String Message) {
try {
PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
printWriter.print(Message);
printWriter.flush();
}
catch (Exception e) {
System.out.println("Server fault: "+ e.getMessage());
}
}
}
/* Client */
public class Client {
public static void main(String[] args) {
Client B = new Client();
B.runClient();
}
public void runClient () {
Socket socket = null;
try {
socket = new Socket("127.0.0.1", 1234);
}
catch (Exception e) {
System.out.println("Client fault: "+e.getMessage());
}
byte [] Tmp = new byte[10];
for (int i=0; i<Tmp.length; i++) {
Tmp[i] = 1;
}
writeMessage(socket, Tmp);
for (int i=0; i<10; i++) {
byte [] Message = readMessage(socket);
System.out.println(Message);
}
}
public void writeMessage (Socket socket, byte [] myByteMessage) {
try {
OutputStream out = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
dos.write(myByteMessage, 0, myByteMessage.length);
PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
printWriter.print(myByteMessage);
printWriter.flush();
}
catch (Exception e) {
System.out.println("Could not send data over TCP");
return;
}
}
public byte [] readMessage (Socket socket) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1];
int len = -1;
while((len = socket.getInputStream().read(buf))!=-1){
baos.write(buf, 0, len);
}
for (int i=0; i<baos.toByteArray().length; i++) {
System.out.println(baos.toByteArray()[i]);
}
System.out.println("Test");
return baos.toByteArray();
}
catch (Exception e) {
System.out.println("Server fault: "+ e.getMessage());
}
return null;
}
}
The problem is, that the client send something to the server but the server doesn't receive anything, so he hangs at the readMessage function.
On the other hand, the client receive some weird stuff, but not the response from the server.
The server receives bytes, but it never leaves the while loop because read() never returns -1. read() returns -1 when the end of the stream is reached. And that happens only when the client closes the socket output stream. Since the client never closes the output stream, the server keeps waiting for the more bytes to come.
Side note: your code is hard to read because you don't respect the standard Java naming conventions: variables start with a lowercase letter.
Does anyone know why this crashes? All I'm doing is reading in a file in a txt file from my raw folder and when I click the load button in the other activity window, the code breaks when I call the variable testing within the file reader object upon click. log.d(null, ReadFileObject.fileText) Thanks in advance!
public class ReadFile extends Activity{
public String test;
public String testing;
protected void onCreate(Bundle savedInstanceState) {
}
public void fileText() {
InputStream fis;
fis = getResources().openRawResource(R.raw.checkit);
byte[] input;
try {
input = new byte [fis.available()];
while(fis.read() != -1)
{
test += new String (input);
}
testing = test;
fis.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(e.getMessage());
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(e.getMessage());
}
/* InputStream fis = null;
try {
fis = getResources().openRawResource(R.raw.checkit);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
String nextLine;
int i = 0, j = 0;
while ((nextLine = br.readLine()) != null) {
if (j == 5) {
j = 0;
i++;
}
test += nextLine;
}
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
} finally {
if (fis != null) {
try { fis.close(); }
catch (IOException ignored) {}
}
}*/
}
}
Your code is broken here:
byte[] input;
input = new byte [fis.available()];
while(fis.read() != -1) {
test += new String (input);
}
testing = test;
fis.close();
In Java available() is unreliable (read the Javadoc).... and may even return 0. You should instead use a loop similar to:
InputStream fis = getResources().openRawResource(R.raw.checkit);
try {
byte[] buffer = new byte[4096]; // 4K buffer
int len = 0;
while((len = fis.read(buffer)) != -1) {
test += new String (buffer, 0, len);
}
testing = test;
} catch (IOException ioe) {
ioe.printStackTrace();
// make sure you do any other appropriate handling.
} finally {
fis.close();
}
(although using string concatenation is probably not the best idea, use a StringBuilder).
Your class extends `activity but theres nothing inside oncreate. If you need a simple java program try to create New java Project . Since you extend activity you should setcontentview(yourLayout). Then call your method from oncreate and do your stuffs
I am trying to record audio into a file in the server side which is an android device and send it to client, another android device when the record is done. It works fine for the first time, but when I record again, my second record is not received by the client. Here is my code
SERVER THREAD:
public class ServerThread implements Runnable {
public void run() {
try {
if (SERVERIP != null) {
serverSocket = new ServerSocket(SERVERPORT);
while (true) {
client = serverSocket.accept();
OutputStream out = client.getOutputStream();
while(true){
//record status is true
//when record is done
if(record_status){
try {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(mFileName)));
BufferedOutputStream bout = new BufferedOutputStream(out);
copyFile(bis, bout);
bout.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
record_status = false;
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
CLIENT THREAD:
public class ClientThread implements Runnable {
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVERIP);
Socket socket = new Socket(serverAddr, SERVERPORT);
connected = true;
while (connected) {
try {
dis = socket.getInputStream();
while(true){
if(dis.available()>0){
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(mFileName)));
copyFile(socket.getInputStream(), bos);
bos.flush();
//file has been received
//start playing the audio
startPlaying();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
socket.close();
} catch (Exception e) {
connected = false;
}
}
}
method copyFile:
public static boolean copyFile(InputStream inputStream, OutputStream out) {
byte buf[] = new byte[4092];
int len;
try {
while ((len = inputStream.read(buf)) != -1) {
out.write(buf, 0, len);
}
out.close();
inputStream.close();
} catch (IOException e) {
return false;
}
return true;
}
This really should be a comment, however i don't have the rep yet. But it seems to me that on the server side you have record_status set to true on first iteration of while loop once that stream is sent to client then record_status is set false and never actually set to true again inside the while loop. As a result the code inside the if statement is never executed again. So where does record_status get set to true again? check the logcat on server side device to see if anything is actually put into bitstream for the second recording if not this is your problem