Ok.... Trying to learn java on my own, been having trouble with this for awhile. I'm trying to transfer a large file over the network using sockets and buffered input and output streams. Doesn't matter what size file I try to transfer. Hopefully I posted my code correctly, I know theres probably many problems with this code, although it compiles and runs ok, I get an IndexOutOfBoundsException the second the client and server go into the while loops, the server gets it during the first bis.read(buf,0,len) and the client gets it during the while(off = fis.read(buf,0,len)..... Any help would be greatly appreciated
//Server Receive code receive method and main for testing
public File receive(Socket socket) throws IOException{
//temporarily hard coded filename
File file = new File("C:\\users\\tom5\\desktop\\sales\\input.dat");
DataInputStream dis = new DataInputStream(socket.getInputStream());
FileOutputStream fos = new FileOutputStream(file);
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//reads file length from datainputstream
int len = dis.readInt();
dis.close();
int bytesRead=0;
//create buffer
byte[]buf = new byte[4092];
int off = 0;
//read from BufferedInputStream and write to FileOutputStream?
while(bytesRead < len) {
bis.read(buf,0,len);
fos.write(buf,0,len);
bytesRead++;
}
fos.close();
bis.close();
return file;
}
public static void main(String[]args) throws IOException{
Server server = new Server();
Socket socket =server.accept();
File file = server.receive(socket);
}
}
//Client sending code
public void send(Socket socket,File file) throws IOException{
FileInputStream fis = new FileInputStream(file);
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
int len = (int)file.length();
dos.writeInt(len);
dos.flush();
dos.close();
System.out.println(file.length());
byte[]buf = new byte[4092];
int off= 0;
while((off = fis.read(buf,0,len)) != -1 ){
bos.write(buf,0,len);
}
}
public static void main(String[]args) throws UnknownHostException, IOException{
Client client = new Client();
Socket socket =client.connect("localhost",1055);
File file = new File("C:\\users\\tom5\\desktop\\movie.avi");
}
}
while(bytesRead < len) {
bis.read(buf,0,len);
fos.write(buf,0,len);
bytesRead++;
}
You're trying to read len bytes into buf, which is larger than its length, and you're incrementing bytes by 1 each time even though read can read multiple bytes. It should be more like:
while(bytesRead < len) {
int n = bis.read(buf);
fos.write(buf, 0, n);
bytesRead += n;
}
or if there's the possibility of extra bytes after the file you don't want to read:
while(bytesRead < len) {
int n = bis.read(buf, 0, Math.min(buf.length, len - bytesRead));
fos.write(buf, 0, n);
bytesRead += n;
}
There is a similar problem in the write method. You're storing the return value in off but you never use it.
You are wrapping the stream twice, once as dis and once as bis. This means that dis is not buffered but when you close it, you close the underlying stream.
I suggest you wrap use ONLY
DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
If you want an efficient buffer size, I suggest you a power of 2, i.e 4096 rather than 4092.
A #fgb notes: You correct use the length read() on the sending size but ignore it on the receiving size (The irony being that you usually get the size you ask for when reading a file, but not so much when reading a socket)
Consider using one common InputStream to OutputStream copier method which works in both situations e.g. like IOUtils.copy().
You are using fixed buffer size. Try this:
byte[] mybytearray = new byte[(int) myFile.length()];
Related
I just realized that DataInputStream and DataOutputStream in writing reading socket
could be used to differentiate the input that was coming over.
Check this code:
Server Side. (receiving string or file)
Socket bSock = serverSocket.accept();
DataInputStream inp = new DataInputStream(bSock.getInputStream());
int iCode = inp.readInt();
switch (iCode) {
case Request.STATE_FILESHARING:
byte bp[] = new byte[iCode];
FileOutputStream fos = new FileOutputStream("s.pdf");
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = inp.read(bp, 0, bp.length);
bos.write(bp, 0, bytesRead);
bos.close();
break;
case Request.STATE_CONVERSATION:
requestFound = new Request(inp.readUTF());
sendToUI(requestFound);
break;
}
Client Side. (sending string or file)
Socket socket = new Socket(myServerAddress, SocketServerPORT);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
if (isThisFileMode()) {
File myFile = new File(sLocationFile);
byte[] mybytearray = new byte[(int) myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray, 0, mybytearray.length);
out.writeInt(Request.STATE_FILESHARING);
out.write(mybytearray, 0, mybytearray.length);
out.flush();
} else {
out.writeInt(Request.STATE_CONVERSATION);
out.write(obReq.toString().getBytes());
out.flush();
}
But I ended up with Error. System crashed!
Anything that I forgot to add?
You're using readUTF() but not writeUTF(). Nearly all the methods of DataInputStream and DataOutputStream are symmetrical: if you call readXXX() you must call writeXXX() at the other end.
You're making the usual mistake of assuming that read() fills the buffer. It is only contracted to transfer at least one byte. You must loop:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
You need to close the socket at both server and client.
I am trying to communicate between two machines using socket programming.
What I basically need is both machines should be able to send and receive files. The code I am pasting below is not showing any error but the server side program seems to be running indefinitely, i.e., it is not terminating. It got stuck on the line marked with comment stuck here.
In this code, initially, server is sending the file named "file.txt" and client is receiving it and saving the file with name "copy.txt". Later client is sending a file named "file2.txt" and server is receiving and saving it with name "copy2.txt".
Can someone please tell me the error and suggest some improvements?
//server side code
import java.net.*;
import java.io.*;
public class server
{
public static void main (String [] args ) throws IOException
{
//sending file started
ServerSocket serverSocket = new ServerSocket(16167);
Socket socket = serverSocket.accept();
System.out.println("Accepted connection : " + socket);
File transferFile = new File ("/Users/abhishek/desktop/file.txt");
byte [] bytearray = new byte [(int)transferFile.length()];
FileInputStream fin = new FileInputStream(transferFile);
BufferedInputStream bin = new BufferedInputStream(fin);
bin.read(bytearray,0,bytearray.length);
OutputStream os = socket.getOutputStream();
System.out.println("Sending Files...");
os.write(bytearray,0,bytearray.length);
os.flush();
System.out.println("File transfer complete");
//socket.close();
//sending comleted
//receiving file started
int filesize=1022386;
int bytesRead=0;
int currentTot = 0;
byte [] bytearray1 = new byte [filesize];
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream("/Users/abhishek/desktop/copy2.txt");
//fos.flush();
BufferedOutputStream bos = new BufferedOutputStream(fos);
//bos.flush();
System.out.println("not moving ahead!!!");//program stucked here
bytesRead = is.read(bytearray1,0,bytearray1.length);
currentTot = bytesRead;
System.out.println("current"+currentTot);
do
{
bytesRead = is.read(bytearray1, currentTot, (bytearray1.length-currentTot));
if(bytesRead >= 0)
currentTot += bytesRead;
System.out.println("current"+currentTot);
} while(bytesRead > -1);
System.out.println("outside current"+currentTot);
bos.write(bytearray1, 0 , currentTot);
bos.flush();
//receiving complete
System.out.println("Receving file completed");
socket.close();
}
}
//client side code
import java.net.*;
import java.io.*;
public class client
{
public static void main (String [] args ) throws IOException
{
int filesize=1022386;
int bytesRead=0;
int currentTot = 0;
Socket socket = new Socket("localhost",16167);
byte [] bytearray = new byte [filesize];
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream("/Users/abhishek/desktop/copy.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead = is.read(bytearray,0,bytearray.length);
currentTot = bytesRead;
do
{
bytesRead = is.read(bytearray, currentTot, (bytearray.length-currentTot));
if(bytesRead >= 0)
currentTot += bytesRead;
} while(bytesRead > -1);
System.out.println("current"+currentTot);
bos.write(bytearray, 0 , currentTot);
bos.flush();
bos.close();
System.out.println("receiving first file completed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
//sending file
System.out.println("sending second file started!");
File transferFile = new File ("/Users/abhishek/desktop/file2.txt");
byte [] bytearray2 = new byte [(int)transferFile.length()];
FileInputStream fin = new FileInputStream(transferFile);
BufferedInputStream bin = new BufferedInputStream(fin);
bin.read(bytearray2,0,bytearray2.length);
OutputStream os = socket.getOutputStream();
os.flush();
os.write(bytearray2,0,bytearray2.length);
os.flush();
System.out.println("sending second file completed!");
//sending complete
socket.close();
}
}
Does the System.out.println("not moving ahead!!!");//program stucked here line actually execute? if so, then the problem is that the InputStream.read() functions are blobking functions; they will stop execution of the program ("block") until they are able to complete.
From the JavaDoc for InputStream:
Reads up to len bytes of data from the input stream into an array of bytes. An attempt is made to read as many as len bytes, but a smaller number may be read. The number of bytes actually read is returned as an integer.
This method blocks until input data is available, end of file is detected, or an exception is thrown.
Since you aren't getting an exception, this means that when you call .read(), there is no data available to be read, and you program sits around waiting for data to read (that never arrives). You should check that your client program is actually sending the data in the first place.
I'd bet
bytesRead = is.read(bytearray1,0,bytearray1.length);
is where you're really getting stuck. The problem normally if you are stuck here is that the other side of the communication has not sent any data, there's nothing to read, and your thread is stuck waiting for it to send.
on your client side, you call
bos.close();
after sending the first message. This is going to cause the socket to close as well, which will throw an IOException on your server end, and because you are not catching the IOException, your server program will just exit.
How much socket experience do you have? If you are just beginning with sockets, you might want to check out the extensions I wrote around this, starting with ServerSocketEx and DataFetcher.
I got working over socket file sender, it worked perfectly, but I couldn't send large files with it. Always got heap error. Then I changed the code of client, so it would send file in chunks. Now I can send big files, but there is new problem. Now I recieve small files empty and larger files for example videos can't be played. Here is the code of client that sends file:
public void send(File file) throws UnknownHostException, IOException {
// Create socket
hostIP = "localhost";
socket = new Socket(hostIP, 22333);
//Send file
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
OutputStream os = socket.getOutputStream();
//Sending size of file.
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(file.getName() + ":" + userName);
byte[] arr = new byte[1024];
try {
int len = 0;
while ((len = dis.read(arr)) != -1) {
dos.write(arr, 0, len);
}
} catch (IOException ex) {
ex.printStackTrace();
}
dos.flush();
socket.close();
}
and here is the server code:
void start() throws IOException {
// Starts server on port.
serverSocket = new ServerSocket(port);
int bytesRead;
while (true) {
connection = serverSocket.accept();
in = connection.getInputStream();
clientData = new DataInputStream(in);
String[] data = clientData.readUTF().split(":");
String fileName = data[0];
String userName = data[1];
output = new FileOutputStream("C:/" + fileName);
long size = clientData.readLong();
byte[] buffer = new byte[1024];
// Build new file
while (size > 0 && (bytesRead = clientData.read(buffer, 0, (int) Math.min(buffer.length, size))) != -1) {
output.write(buffer, 0, bytesRead);
size -= bytesRead;
}
output.close();
}
}
You failed to write out the length of the file to the stream in the client:
long size = clientData.readLong();
So that call in the server is reading the first 8 bytes of the actual file and who knows what that quantity is. You don't have to read the length from the stream since you only wrote a single file. After reading the filename, and username (not very secure is it?) you can just read the stream until EOF. If you ever wanted to send multiple files over the same open socket then you'd need to know the length before reading the file.
Also your buffers for reading are way to small. You should be at a minimum of 8192 instead of 1024. And you'll want to put all .close() in a finally block to make sure your server and clients shutdown appropriately if there is an exception ever.
Hii i am uploading a file to server using socket and i need the percent of file loaded?how can i do that?i have the maximun value i.e the file length ,how can i get how much file has been uploaded?
FileInputStream fis = new FileInputStream(fil);
BufferedInputStream in = new BufferedInputStream(fis);
BufferedOutputStream out = new BufferedOutputStream(skt.getOutputStream());
//Write the file to the server socket
int i;
while ((i = in.read()) != -1) {
publishProgress(???);
out.write(i);
System.out.println(i);
}
I need to pass the length of file uploded in the publishProgress method.
using buffered copying
FileInputStream fis = new FileInputStream(fil);
BufferedInputStream in = new BufferedInputStream(fis);
BufferedOutputStream out = new BufferedOutputStream(skt.getOutputStream());
//Write the file to the server socket
int i;
int written = 0;
byte[] buf = new byte[512];
while ((i = in.read(buff)) != -1) {
out.write(buff,0,i);
written += i;
publishProgress((double)written/length);
//passing a double value from 0-1 to say how much is transmitted (length is length of file)
System.out.println(buff+", "+i);
}
To do this you need to do one of a couple of things:
Use a Flash uploader such as swfupload (see http://demo.swfupload.org/Documentation/) as these typically provide access to upload progress of this sort.
Provide a back channel of your own: perform the form submit with Ajax and then while the form submit occurs you run a javascript timer that hits a URL on the server with a key of some kind that corresponds to the upload. The URL on the server looks up how much of the file has been uploaded and returns that number and you pass that through to your uploadProgress method.
Below is your modified code. written holds the number of ints written to the socket.
FileInputStream fis = new FileInputStream(fil);
BufferedInputStream in = new BufferedInputStream(fis);
BufferedOutputStream out = new BufferedOutputStream(skt.getOutputStream());
//Write the file to the server socket
int i;
int written = 0;
while ((i = in.read()) != -1) {
out.write(i);
publishProgress(++written);
System.out.println(i);
}
javax.swing.ProgressMonitorInputStream
Hello there im trying to send files using client-server classes in java. For some reason when the method that sends the file is called the socket closes. here is the code :
FileInputStream fIn = new FileInputStream(file);
out = new BufferedOutputStream(clientSocket.getOutputStream());
byte fileContent[] = new byte[(int) file.length()];
fIn.read(fileContent);
for (byte b : fileContent) {
out.write(b);
}
and the code from the client :
FileOutputStream fIn = new FileOutputStream("testing");
BufferedInputStream inAout = new BufferedInputStream(clientSocket.getInputStream());
byte fileContent[] = new byte[1000000];
inAout.read(fileContent);
fIn.write(fileContent);
and the error message i get : SEVERE: null
java.net.SocketException: Socket closed
Im not really experienced with this so if any can help it would be great.
The InputStream.read(byte[]) method returns an int for the number of bytes it actually read. It's not guaranteed to read as many bytes as you requested from the byte array. It'll often return the size of the underlying buffer and you'll have to call it many times.
You can use this to be more efficient by streaming the bytes from the socket to the file instead of buffering the whole byte array in memory. Likewise on the server side you can do the same thing to save memory and be faster than writing a byte at a time.
Here's a working example of a server and client in one that connects to itself to transfer a file:
public class SocketFileExample {
static void server() throws IOException {
ServerSocket ss = new ServerSocket(3434);
Socket socket = ss.accept();
InputStream in = new FileInputStream("send.jpg");
OutputStream out = socket.getOutputStream();
copy(in, out);
out.close();
in.close();
}
static void client() throws IOException {
Socket socket = new Socket("localhost", 3434);
InputStream in = socket.getInputStream();
OutputStream out = new FileOutputStream("recv.jpg");
copy(in, out);
out.close();
in.close();
}
static void copy(InputStream in, OutputStream out) throws IOException {
byte[] buf = new byte[8192];
int len = 0;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
}
public static void main(String[] args) throws IOException {
new Thread() {
public void run() {
try {
server();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
client();
}
}
The reason is pretty simple: The call inAout.read(fileContent) will return after about 4KB of data has been transmitted. That's the input buffer size. So instead of a single huge read, you need a loop and many reads and write as many bytes to fIn as you got from the socket.
Also don't forget to flush the output on the server side (closing will flush it) or some data will be lost.
SEVERE: null java.net.SocketException: Socket closed
That means you've closed the socket yourself and then called another operation that needs it open. For example, closing the socket or its input stream or output stream closes the other stream and the socket. Somewhere or other you are doing that.