I am making an app which requires socket to send files from one to another Well i can successfully send and receive any file from one device to another but the problem is my socket connection closes itself automatically after file transfer. I also tried removing socket.close() from both sides but it still closes itself
Here is the server's code
try {
OutputStream os = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeInt(files.size());
dos.flush();
for(int i = 0 ; i < files.size();i++){
dos.writeUTF(files.get(i).getName());
dos.flush();
}
int n = 0;
byte[]buf = new byte[4092];
for(int i =0; i < files.size(); i++){
if (name == null){
dos.writeUTF(files.get(i).getName());
}else {
dos.writeUTF(filesName.get(i) + ".apk");
}
dos.writeLong(files.get(i).length());
FileInputStream fis = new FileInputStream(files.get(i));
while((n =fis.read(buf)) != -1){
dos.write(buf,0,n);
dos.flush();
}
}
dos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
And Here is the Client's code
try {
socket = new Socket(dstAddress, dstPort);
bufferSize = socket.getReceiveBufferSize();
in = socket.getInputStream();
DataInputStream dis = new DataInputStream(in);
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
int number = dis.readInt();
ArrayList<File>files = new ArrayList<File>(number);
for(int i = 0; i< number;i++){
File file = new File(dis.readUTF());
files.add(file);
}
int n = 0;
byte[]buf = new byte[4092];
for(int i = 0; i < files.size();i++){
int fileeesizee = 0;
publishProgress(String.valueOf(0));
String filename = dis.readUTF();
long fileSize = dis.readLong();
recyclername.add(filename);
recyclersize.add(android.text.format.Formatter.formatFileSize(test2.this, fileSize));
recyclerimg.add(filename);
final File f = new File(Environment.getExternalStorageDirectory()+"/SharePlus/.data/"+filename);
FileOutputStream fos = new FileOutputStream(f);
while (fileSize > 0 && (n = dis.read(buf, 0, (int)Math.min(buf.length, fileSize))) != -1)
{
fos.write(buf,0,n);
fileSize -= n;
fileeesizee+=n;
if (fileSize==0){
}else{
publishProgress(""+(int)((fileeesizee * 100) / fileSize));
}
}
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
Log.d("d", "1 catch = " + e.getMessage());
final String eMsg = "Something wrong: " + e.getMessage();
test2.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(test2.this, eMsg, Toast.LENGTH_LONG).show();
}
});
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
Log.d("d", "2 catch = " + e.getMessage());
e.printStackTrace();
}
}
}
dos.close();
Closing a stream closes the socket too.
Related
I'm trying to send and read the reply from the socket with no luck. What I got so far is, connected to the server and read connection reply (header from Ericsson telco exchange) and printed it on System.out. What I need to be able to do is send a command to the exchange and get the reply and that's where I'm stuck. Below is my test code.
Any help is appreciated.
public class ExchangeClientSocket {
public void run() {
try {
int serverPort = 23;
InetAddress host = InetAddress.getByName("my.host.ip.address");
Socket socket = new Socket(host, serverPort);
InputStreamReader isr = new InputStreamReader(socket.getInputStream());
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(isr);
int i;
StringBuffer buffer = new StringBuffer();
while (true) {
i = in.read();
if (i == 60) {
break;
} else {
buffer.append((char) i);
}
}
// this returns the head from exchange
System.out.println(buffer.toString());
out.write("allip;"); // command I want to send to exchange
out.flush();
System.out.println(in.ready()); // this returns false
System.out.println(in.read());
System.out.println("damn..");
buffer = new StringBuffer();
// can't get into this loop
// this is where I want to read the allip response
while ((i = in.read()) != -1) {
i = in.read();
if (i == 60) {
break;
} else {
buffer.append((char) i);
}
}
System.out.println(buffer.toString());
out.close();
in.close();
socket.close();
} catch (UnknownHostException ex) {
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Here is a suggestion on how to get input from the server after writing to the output stream: simply get another input stream from the socket.
So instead of reading from the same stream you create a new stream from the socket after you sent the command and read it.
I would therefore suggest to change your code to this here:
public void run() {
try {
int serverPort = 23;
InetAddress host = InetAddress.getByName("my.host.ip.address");
Socket socket = new Socket(host, serverPort);
InputStreamReader isr = new InputStreamReader(socket.getInputStream());
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(isr);
int i;
StringBuffer buffer = new StringBuffer();
while (true) {
i = in.read();
if (i == 60) {
break;
} else {
buffer.append((char) i);
}
}
// this returns the head from exchange
System.out.println(buffer.toString());
out.write("allip;"); // command I want to send to exchange
out.flush();
// Create a new input stream here !!!
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
buffer = new StringBuffer();
// can't get into this loop
while ((i = in.read()) != -1) {
i = in.read();
if (i == 60) {
break;
} else {
buffer.append((char) i);
}
}
System.out.println(buffer.toString());
out.close();
in.close();
socket.close();
} catch (UnknownHostException ex) {
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
I am trying to send a file from client to server. Below is the code i have tried. But at times, there is a packet loss during the transfer. I am not sure where i am wrong.
SERVER SIDE CODE:
public static void ReadAndWrite(byte[] aByte, Socket clientSocket,
InputStream inputStream, String fileOutput)
throws FileNotFoundException, IOException {
int bytesRead;
FileOutputStream fileOutputStream = null;
BufferedOutputStream bufferedOutputStream = null;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try
{
fileOutputStream = new FileOutputStream( fileOutput );
bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
bytesRead = inputStream.read(aByte, 0, aByte.length);
System.out.println("The length is "+bytesRead);
int count = 0;
do {
count++;
byteArrayOutputStream.write(aByte);
bytesRead = inputStream.read(aByte);
} while (bytesRead != -1);
System.out.println("The count is "+count);
System.out.println("The length is "+byteArrayOutputStream.size());
bufferedOutputStream.write(byteArrayOutputStream.toByteArray());
bufferedOutputStream.flush();
bufferedOutputStream.close();
clientSocket.close();
}
catch(Exception ex)
{
Logger.writeLog(ex,Listen.class.getName(), LogType.EXCEPTION);
throw ex;
}
CLIENT SIDE CODE:
public void readByteArrayAndWriteToClientSocket(
Socket connectionSocket, BufferedOutputStream outToClient, String fileToSend ) throws Exception
{
try{
if (outToClient != null)
{
File myFile = new File(fileToSend);
System.out.println(myFile.length());
byte[] byteArray = new byte[(int) myFile.length()];
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(myFile);
} catch (IOException ex) {
Logger.writeLog(ex, FileUtility.class.getName(), LogType.EXCEPTION);
throw ex;
}
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
try {
bufferedInputStream.read(byteArray, 0, byteArray.length);
outToClient.write(byteArray, 0, byteArray.length);
outToClient.flush();
outToClient.close();
connectionSocket.close();
return;
} catch (IOException ex) {
Logger.writeLog(ex, FileUtility.class.getName(), LogType.EXCEPTION);
throw ex;
}
}
}catch (Exception e) {
Logger.writeLog(e, getClass().getName(), LogType.EXCEPTION);
throw e;
}
}
There is no 'packet loss', just bugs in your code.
The canonical way to copy a stream in Java is as follows:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
If you know the number of bytes in advance and the sender must keep the connection open after the transfer, it becomes:
while (total < expected && (count = in.read(buffer, 0, expected-total > buffer.length ? buffer.length : (int)(expected-total))) > 0)
{
out.write(buffer, 0, count);
total += count;
}
Forget all the ByteArrayInput/OutputStreams and the extra copies. Just read from the file and send to the socket, or read from the socket and write to the file.
The sockets read method will return when its has obtained all the bytes you asked for, OR, when it stops receiving data from the network.
As transmission is often interrupted in any real network you need to keep issuing read calls until you have the number of bytes you want.
You need code something like this:
char [] buffer = new char[1024];
int expect = 1000;
int sofar = 0;
int chars_read;
try
{
while((chars_read = from_server.read(buffer[sofar])) != -1)
{
sofar = sofar + chars_read;
if (sofar >= expected) break;
}
}
catch(IOException e)
{
to_user.println(e);
}
I am developing an Android App to send a file via bluetooth to a java server using the BlueCove library version 2.1.0 based on this snippet. At the beginning everything looks fine, but the file will not transfered completly. Only about 7KB of 35KB.
Android
private void sendFileViaBluetooth(byte[] data){
OutputStream outStream = null;
BluetoothDevice device = btAdapter.getRemoteDevice(address);
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
btSocket.connect();
try {
outStream = btSocket.getOutputStream();
outStream.write( data );
outStream.write("end of file".getBytes());
outStream.flush();
} catch (IOException e) {
} finally{
try {
outStream.close();
btSocket.close();
device = null;
} catch (IOException e) {
}
}
}
PC Server
InputStream inStream = connection.openInputStream();
byte[] buffer = new byte[1024];
File f = new File("d:\\temp.jpg");
FileOutputStream fos = new FileOutputStream (f);
InputStream bis = new BufferedInputStream(inStream);
int bytes = 0;
boolean eof = false;
while (!eof) {
bytes = bis.read(buffer);
if (bytes > 0){
int offset = bytes - 11;
byte[] eofByte = new byte[11];
eofByte = Arrays.copyOfRange(buffer, offset, bytes);
String message = new String(eofByte, 0, 11);
if(message.equals("end of file")) {
eof = true;
} else {
fos.write (buffer, 0, bytes);
}
}
}
fos.close();
connection.close();
I tried already to split the byte array before writing:
public static byte[][] divideArray(byte[] source, int chunksize) {
byte[][] ret = new byte[(int)Math.ceil(source.length / (double)chunksize)][chunksize];
int start = 0;
for(int i = 0; i < ret.length; i++) {
ret[i] = Arrays.copyOfRange(source,start, start + chunksize);
start += chunksize ;
}
return ret;
}
private void sendFileViaBluetooth(byte[] data){
[...]
byte[][] chunks = divideArray(data, 1024);
for (int i = 0; i < (int)Math.ceil(data.length / 1024.0); i += 1) {
outStream.write( chunks[i][1024] );
}
outStream.write("end of file".getBytes());
outStream.flush();
[...]
}
Every help or ideas are appreciated.
You don't need any of this. The canonical way to copy a stream in Java is this:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
out.close();
Same at both ends. TCP/IP will do all the chunking for you. All you need to do is cope correctly with varying size reads, which this code does.
I have some problem with Java IO, this code below is not working, the variable count return -1 directly.
public void putFile(String name, InputStream is) {
try {
OutputStream output = new FileOutputStream("D:\\TEMP\\" + name);
byte[] buf = new byte[1024];
int count = is.read(buf);
while( count >0) {
output.write(buf, 0, count);
count = is.read(buf);
}
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
But if I commented the OutputStream such as
public void putFile(String name, InputStream is) {
try {
//OutputStream output = new FileOutputStream("D:\\TEMP\\" + name);
byte[] buf = new byte[1024];
int count = is.read(buf);
while( count >0) {
//output.write(buf, 0, count);
count = is.read(buf);
}
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
The count will return the right value (>-1).
How is this possible ? Is it a bug ?
I'm using Jetty in Eclipse with Google plugins and Java 6.21 in Windows 7.
PS :I change the original code, but it doesn't affect the question
Some bytes are missing when I'm sending files over TCP connection. Though there are times that file transfer is complete.
Sending side:
class SendFile extends Thread {
Socket s;
String toIP;
String fileName;
PrintWriter pw;
BufferedReader br;
String fromIP;
String nextHopIP;
String transferTime;
int routingIndex;
final int bufferSize = 65536;
int readFile;
byte[] buffer;
FileInputStream fileIn;
OutputStream fileOut;
long fileTransferTime;
SendFile(String toIP, String fileName) {
this.toIP = toIP;
this.fileName = fileName;
}
public void run() {
while (true) {
try {
fromIP = InetAddress.getLocalHost().getHostAddress();
nextHopIP = Tables.checkRoutingTable(toIP);
if (nextHopIP.equals("none")) {
System.out.println("Invalid IP address");
} else {
s = new Socket(nextHopIP, 3434);
fileIn = new FileInputStream(fileName);
fileOut = s.getOutputStream();
buffer = new byte[bufferSize];
pw = new PrintWriter(s.getOutputStream());
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
pw.println(fromIP);
pw.println(toIP);
pw.println(fileName.split("\\\\")[fileName.split("\\\\").length - 1]);
pw.flush();
//Send file
fileTransferTime = System.currentTimeMillis();
int sum = 0;
while ((readFile = fileIn.read(buffer)) != -1) {
fileOut.write(buffer, 0, readFile);
sum += readFile;
}
System.out.println(sum);
fileIn.close();
s.shutdownOutput();
br.readLine();
fileTransferTime = System.currentTimeMillis() - fileTransferTime;
System.out.println("File transfer time: " + fileTransferTime + " ms");
s.close();
break;
}
} catch (IOException ex) {
//Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("Connection timed out. Retrying...");
}
}
}
}
Receiving side:
class FileTransferThread extends Thread {
Socket fromSocket;
Socket toSocket;
String ip;
BufferedReader fromBR;
BufferedReader toBR;
PrintWriter fromPW;
PrintWriter toPW;
String[][] delta;
String token;
String toIP;
String fromIP;
String nextHopIP;
String absoluteFileName;
String fileName;
int deltaCount;
int entryCount;
int socketIndex;
int i;
int j;
int readFile;
final int bufferSize = 65536;
byte[] buffer;
InputStream fileIn;
FileOutputStream fileOut;
OutputStream fileHopOut;
File directory;
long fileTransferTime;
FileTransferThread(Socket s) {
this.fromSocket = s;
}
public void run() {
try {
ip = InetAddress.getLocalHost().getHostAddress();
fromBR = new BufferedReader(new InputStreamReader(fromSocket.getInputStream()));
fromPW = new PrintWriter(fromSocket.getOutputStream());
fromIP = fromBR.readLine();
toIP = fromBR.readLine();
nextHopIP = Tables.checkRoutingTable(toIP);
buffer = new byte[bufferSize];
fileIn = fromSocket.getInputStream();
fileName = fromBR.readLine();
if (!fileName.equals("\\send")) {
directory = new File("c:\\" + fromIP);
directory.mkdirs();
absoluteFileName = "c:\\" + fromIP + "\\" + fileName;
fileOut = new FileOutputStream(absoluteFileName);
while (true) {
try {
//if not yet the destination IP, pass to next hop
if (!toIP.equals(ip)) {
toSocket = new Socket(toIP, 3434);
fileHopOut = toSocket.getOutputStream();
toBR = new BufferedReader(new InputStreamReader(toSocket.getInputStream()));
toPW = new PrintWriter(toSocket.getOutputStream());
toPW.println(fromIP);
toPW.println(toIP);
toPW.println(fileName);
toPW.flush();
//Send file
while ((readFile = fileIn.read(buffer)) != -1) {
fileHopOut.write(buffer, 0, readFile);
}
toSocket.shutdownOutput();
fromPW.println(toBR.readLine());
fromPW.flush();
toSocket.close();
} else {
int sum = 0;
while ((readFile = fileIn.read(buffer)) != -1) {
fileOut.write(buffer, 0, readFile);
sum += readFile;
}
System.out.println(sum);
fileOut.flush();
fileOut.close();
fromPW.println("1");
fromPW.flush();
}
fromSocket.close();
break;
} catch (IOException ex) {
//Logger.getLogger(FileTransferThread.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("Connection timed out. Retrying...");
}
}
} else {
while(true) {
try {
//if not yet the destination IP, pass to next hop
if (!toIP.equals(ip)) {
toSocket = new Socket(toIP, 3434);
fileHopOut = toSocket.getOutputStream();
toBR = new BufferedReader(new InputStreamReader(toSocket.getInputStream()));
toPW = new PrintWriter(toSocket.getOutputStream());
toPW.println(fromIP);
toPW.println(toIP);
toPW.println(fileName);
toPW.flush();
//Send file
while ((readFile = fileIn.read(buffer)) != -1) {
fileHopOut.write(buffer, 0, readFile);
}
toSocket.shutdownOutput();
fromPW.println(toBR.readLine());
fromPW.flush();
toSocket.close();
} else {
while ((readFile = fileIn.read(buffer)) != -1) {
}
fromPW.println("1");
fromPW.flush();
}
fromSocket.close();
break;
}
catch (IOException ex) {
//Logger.getLogger(FileTransferThread.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("Connection timed out. Retrying...");
}
}
}
fromSocket.close();
} catch (IOException ex) {
Logger.getLogger(FileTransferThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
You are not closing - and hence not flushing - the SocketOutputStream called fileout. (You really should consider less misleading names ...).
Hm ... it appears shutdownOutput does that; its javadoc writes:
Disables the output stream for this socket.
For a TCP socket, any previously written data will be sent
followed by TCP's normal connection termination sequence.
If you write to a socket output stream after invoking
shutdownOutput() on the socket, the stream will throw
an IOException.
I leave this in case anybody else has the same idea.
Note that socket.getInputStream specifies the sorts of data loss that can happen using that facility. In particular:
The network software may discard bytes
that are buffered by the socket.
Found the error. It seems that BufferedReader is getting a chunk of data which is supposed to be for the file.