I have a Java server uploading files for the android client. It does the upload but when it is finished, it keeps throwing:
Error::java.net.SocketException: Socket is closed
I searched the code a lot, but didn't find anything. Since it is throwing after uploading the files, I think problem is at the end of code after last for loop, but I see nothing wrong. Any ideas guys?
class ClientThread extends Thread {
// the socket where to listen/talk
String Type;
Socket socket;
ObjectInputStream sInput;
ObjectOutputStream sOutput;
// my unique id (easier for deconnection)
int id;
// Constructore
ClientThread(Socket socket) throws InterruptedException {
// a unique id
id = ++uniqueId;
this.socket = socket;
/* Creating both Data Stream */
System.out.println("Thread trying to create Object Input/Output Streams");
while (!jobdone) {
try {
// create output first
sOutput = new ObjectOutputStream(socket.getOutputStream());
sInput = new ObjectInputStream(socket.getInputStream());
// read the username
OutputStream os = socket.getOutputStream();
FileInputStream fis = null;
DataOutputStream dos = new DataOutputStream(os);
String Request = (String) sInput.readObject();
System.out.println(Request);
String[] todoname = Request.split("\\#reza-hp");
String name = todoname[0];
System.out.println("Connecting...");
File fil = new File("D://Users//ProfileImages//reza");
System.out.println(fil);
File[] Files = fil.listFiles();
System.out.println(Files);
for (int count = 0; count < Files.length; count++) {
System.out.println(Files[count].getName());
}
os = socket.getOutputStream();
dos = new DataOutputStream(os);
dos.writeInt(Files.length);
for (int count = 0; count < Files.length; count++) {
dos.writeUTF(Files[count].getName());
}
for (int count = 0; count < Files.length; count++) {
int filesize = (int) Files[count].length();
dos.writeInt(filesize);
}
for (int count = 0; count < Files.length; count++) {
int filesize = (int) Files[count].length();
byte[] buffer = new byte[filesize];
fis = new FileInputStream(Files[count].toString());
BufferedInputStream bis = new BufferedInputStream(fis);
// Sending file name and file size to the server
bis.read(buffer, 0, buffer.length); // This line is
// important
dos.write(buffer, 0, buffer.length);
dos.flush();
fis.close();
}
dos.close();
os.close();
} catch (Exception e) {
System.out.println("Error::" + e);
}
}
Thread.sleep(5000);
Server.shutdown();
}
}
You should use ServerSocket to listen for incoming connections from your client application. Plain Socket is preatty straightforward. Open connection, exchange data, close connection, dispose. You could rebind your socket, but this is not the way you should do.
ServerSocket server=new ServerSocket(yourPort);
Socket clientSocket=server.listen(); // here you will block until incoming connection
Check docs for more info here
your socket is getting closed from Otherside
Related
I had a server client application to transfer files where i need to connect to many clients from one server using sockets. I tried, and got the connections but when compared to a single connection the speed is decreasing when connected to more number of clients so i got an idea to open more ports and connect to different clients from server on multiple ports
This is my code for opening a serversocket
try {
serverSocket = new ServerSocket(SocketServerPORT);
serverSocket1 = new ServerSocket(SocketServerPORT1);
while (true) {
socket = serverSocket.accept();
FileThread fileThread = new FileThread(socket);
fileThread.start();
socket1 = serverSocket1.accept();
FileTxThread fileTxThread = new FileTxThread(socket1);
fileTxThread.start();
}
This is the code for sending files from server
DataOutputStream dos=new DataOutputStream(socket.getOutputStream());
dos.writeInt(f.size());
for(File file1:f){
long length = file1.length();
dos.writeLong(length);
String name = file1.getAbsolutePath();
System.out.println(name);
dos.writeUTF(name);
FileInputStream in = new FileInputStream(file1);
int bs=65508;
byte[] b= new byte[bs];
int theByte = 0;
while((theByte = in.read(b,0,bs)) != -1) dos.write(b,0,theByte);
in.close();
This is my client side code(my client is android device)
private class ClntThread extends Thread {
String dstAddress;
int dstPort;
ClntThread(String address, int port) {
dstAddress = address;
dstPort = port;
}
#Override
public void run() {
Socket socket = null;
try {
socket = new Socket(dstAddress, dstPort);
DataInputStream dis = new DataInputStream(socket.getInputStream());
int filescount=dis.readInt();
File[] files=new File[filescount];
for(int i = 0; i < filescount; i++)
{
files[i] = new File(dirpath + "/" + filesname);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(files[i]));
int bs=65508;
byte[] b=new byte[bs];
int j=0;
while ((j = dis.read(b, 0, bs))!=-1){
bos.write(b, 0, j);
}
bos.flush();
bos.close();
}
dis.close();
socket.close();
Here how to open different ports on server side and how to connect to server from client as i am mentioning the port number on client side i dont know how client will connect to the unknown port????
I am new to programming and so please give me any suggestions if my approach is wrong
Thank you..
I need some help.
I have server socket side wrote in java and client socket side in C++.
I'm trying to send prepared XML file from server to client, seems it works but after all received file is broken at client side (only nulls in this file).
Where is the problem?
Server side sending code:
public void SendBytes() throws IOException {
File myFile = new File(XML.prepareFile());
int fileSize = (int) myFile.length();
byte[] mybytearray = new byte[fileSize];
FileInputStream fis = null;
BufferedInputStream bis = null;
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
try {
output.write(mybytearray, 0, mybytearray.length);
output.flush();
} catch (Exception e) {
System.out.println("sendBytes(); output error");
}
fis.close();
bis.close();
output.close();
}
and the Client C++ side receiving method code:
int Client::RecvBytes2() {
char buffer[4096];
int iNumBytes = 0;
iNumBytes = recv(m_iSock, buffer, 4096, 0);
char tmp[iNumBytes];
for (int i = 0; i < iNumBytes; i++) {
tmp[i] = buffer[i];
}
std::ofstream fout("receivedFile.xml", std::ios::out | std::ios::binary);
fout.write(tmp, iNumBytes);
return iNumBytes;
}
This question already has answers here:
Java sending and receiving file (byte[]) over sockets
(6 answers)
Closed 7 years ago.
I was experimenting with JAVA and found this question online.
Java sending and receiving file (byte[]) over sockets.
Just for curiosity i played with the code in the accepted answer, and with other code i found similar to the question. I tried the accepted answer,yes it works and is very fast. But the problem is Archive files are getting corrupted. So here is other code i tried. The downfall of my experimental code is it consume CPU cycles and takes more time than accepted answer (And i have no idea why it is happening so). So here is my code. Can somebody help me to optimize and improve this code more.
Time Taken by accepted Answer = 11ms for 4 Mb file.
Time taken by my experiment= 4 seconds for same file.
Server.java
public class Server implements Runnable {
private ServerSocket serverSocket = null;
private Socket socket = null;
private ObjectInputStream inStream = null;
public Server() {
}
#Override
public void run() {
try {
serverSocket = new ServerSocket(4445);
socket = serverSocket.accept();
DataInputStream dIn = new DataInputStream(socket.getInputStream());
OutputStream os = socket.getOutputStream();
DataOutputStream outToClient = new DataOutputStream(os);
System.out.println("Connected");
File myFile = new File("lib1.zip");
long flength = myFile.length();
System.out.println("File Length"+flength);
outToClient.writeLong(flength);
FileInputStream fis;
BufferedInputStream bis;
byte[] mybytearray = new byte[8192];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
int theByte = 0;
System.out.println("Sending " + myFile.getAbsolutePath() + "(" + myFile.length() + " bytes)");
while ((theByte = bis.read()) != -1) {
outToClient.write(theByte);
// bos.flush();
}
/*int count;
BufferedOutputStream bos= new BufferedOutputStream(os);
while ((count = bis.read(mybytearray))>0) {
bos.write(mybytearray, 0, count);
}*/
bis.close();
socket.close();
} catch (SocketException se) {
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Thread t = new Thread(new Server());
t.start();
}
}
ReceiveFile.java
public class RecieveFile {
public final static int SOCKET_PORT = 4445; // you may change this
String SERVER = "127.0.0.1"; // localhost
ArrayList<String> logmsg = new ArrayList<>();
public static void main(String[] args) {
new RecieveFile();
}
public RecieveFile() {
try (Socket sock = new Socket(SERVER, SOCKET_PORT)) {
System.out.println("Connecting...");
try (OutputStream os = sock.getOutputStream(); DataOutputStream outToServer = new DataOutputStream(os)) {
try (DataInputStream dIn = new DataInputStream(sock.getInputStream())) {
long fileLen, downData;
int bufferSize = sock.getReceiveBufferSize();
long starttime = System.currentTimeMillis();
File myFIle = new File("lib1.zip");
try (FileOutputStream fos = new FileOutputStream(myFIle); BufferedOutputStream bos = new BufferedOutputStream(fos)) {
fileLen = dIn.readLong();
/*for (long j = 0; j <= fileLen; j++) {
int tempint = is.read();
bos.write(tempint);
}*/
downData = fileLen;
int n = 0;
byte[] buf = new byte[8192];
while (fileLen > 0 && ((n = dIn.read(buf, 0, buf.length)) != -1)) {
bos.write(buf, 0, n);
fileLen -= n;
// System.out.println("Remaining "+fileLen);
}
/*while ((n = dIn.read(buf)) > 0) {
bos.write(buf, 0, n);
}*/
bos.flush();
long endtime = System.currentTimeMillis();
System.out.println("File " + myFIle.getAbsolutePath()
+ " downloaded (" + downData + " bytes read) in " + (endtime - starttime) + " ms");
}
}
}
} catch (IOException ex) {
Logger.getLogger(RecieveFile.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
You're copying a byte at a time. This is slow. You're also declaring a byte array but not using it. Try this:
int count;
byte[] buffer = new byte[8192]; // or more, double or quadruple it
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
Your solution takes a lot of time probably because you are reading a character at time, instead of all the buffer.
The solution is to use a construct similar to the linked question; the problem you got about corrupted file is really improbable, a malformed TCP packed that pass CRC check is really rare occurrence, and I would blame a bug instead. try to post the code you used. But you can add some hash check on the file and some part of it, if you are concerned about this
Here is a cleaned up version of your code, it should perform faster as it avoids single byte operations:
public class Server implements Runnable {
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(4445);
Socket socket = serverSocket.accept();
OutputStream os = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
File myFile = new File("lib1.zip");
long flength = myFile.length();
dos.writeLong(flength);
InputStream fis = new FileInputStream(myFile);
byte[] buf = new byte[16*1024]; // 16K
long written = 0;
while ((count = fis.read(buf))>0) {
dos.write(buf, 0, count);
written+=count;
}
if (written != flength)
System.out.println("Warning: file changed");
dos.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
System.exit();
}
}
An possible improvement would be to use NIO with channel.sendTo() but this should already have an acceptable performance. Note you do not need to use buffered streams on reading or writing as you use a larger byte array buffer anyway.
One possible improvement would be to not use the DataOutputStream for the long but poke the 8 bytes of it into the first buffer (array) write.
BTW: writing 4MB in 11ms is 390MB/s, that would be faster than most desktop disks can read and write.
I am having trouble with my client/server program. The server is supposed to get a file from the client then convert it to xml, and then stream the xml file back to the client.
As of now everything works up to the point of streaming the xml file back to the client. I can successfully send my file to the server and convert it to XML.
The server does not send anything to the client. The client is stuck in the area of reading bytes in from the InputStream. On line 57 in the Client class.
public class Server {
private ServerSocket serverSocket;
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public static void main(String[] args) {
int port = 8081;
Server srv = new Server(port);
}
public Server(int portNumber) {
try {
serverSocket = new ServerSocket(portNumber);
clientSocket = serverSocket.accept();
out = new PrintWriter(clientSocket.getOutputStream(), true);
//in = new BufferedReader(
//new InputStreamReader(clientSocket.getInputStream()));
byte[] myArray = new byte[22000]; // should be file size
InputStream is = clientSocket.getInputStream();
FileOutputStream fos = new FileOutputStream("file.csv");
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead;
int current = 0;
bytesRead = is.read(myArray, 0, myArray.length);
current = bytesRead;
do {
bytesRead = is.read(myArray, current, (myArray.length - current) );
if (bytesRead >= 0)
current += bytesRead;
} while (bytesRead > -1);
bos.write(myArray, 0, myArray.length);
bos.flush();
boolean flag = false;
System.out.println("Server: finished receiving file");
XMLWriter xmlWrite = new XMLWriter();
xmlWrite.createXmlDocument("file_copy.csv");
sendXML("server_file.XML");
clientSocket.close();
System.out.println("Server: disconnected with client");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void sendXML(String fileName) {
System.out.println("Sending file");
File file = new File(fileName);
BufferedInputStream bis;
try {
FileInputStream fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
DataInputStream dataIn = new DataInputStream( bis );
OutputStream outStream = clientSocket.getOutputStream();
int length;
try {
length = dataIn.readInt();
System.out.println("S: " + dataIn.readInt());
byte[] data = new byte[ length ];
dataIn.readFully(data, 0, data.length);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
public class Client {
private Socket mainSocket;
public static void main(String[] args) {
int port = 8081;
Client cli = new Client(port);
}
public Client(int portNumber) {
try {
mainSocket = new Socket("localhost", portNumber);
// send file to server
File file = new File("Passengers.csv");
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
OutputStream outStream = mainSocket.getOutputStream();
byte[] myBytes = new byte[(int) file.length()];
bis.read(myBytes, 0, myBytes.length);
outStream.write(myBytes, 0, myBytes.length);
outStream.flush();
System.out.println("Client: Done sending file");
byte[] fileData = new byte[30000];
InputStream is = mainSocket.getInputStream();
FileOutputStream fos = new FileOutputStream("client_file.XML");
BufferedOutputStream bos = new BufferedOutputStream(fos);
DataOutputStream dataOut = new DataOutputStream( bos );
dataOut.writeInt( fileData.length );
dataOut.write( fileData );
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
This loop will run until the stream is closed, not until the client finishes sending data.
do {
bytesRead = is.read(myArray, current, (myArray.length - current) );
if (bytesRead >= 0)
current += bytesRead;
} while (bytesRead > -1);
This is because InputStream.read will block until at least one byte of data is available or the stream is closed, causing a -1 to be returned. Since the client is done sending data but the stream is still open it will block forever.
A solution is to first send the length of the file in the first 4 bytes using something like DataOutputStream/DataInputStream, and then have the client send exactly that many bytes and the server read exactly that many bytes before moving on.
Client:
// Connect to the server and read in file data
byte[] fileData = ...;
DataOutputStream dataOut = new DataOutputStream( outStream );
dataOut.writeInt( fileData.length );
dataOut.write( fileData );
// Get reply from server
Server:
// Create ServerSocket and get Client connection
DataInputStream dataIn = new DataInputStream( is );
int length = dataIn.readInt();
byte[] data = new byte[ length ];
dataIn.readFully( data );
// Continue to process client connection
The general idea behind this kind of network communication is that every block of data, or packet, is prefixed with it's length before being send. This means that the recipient of the data can read in that number and know exactly how many bytes remain to form the complete block or packet. Communication goes along something like this for both sides of the connection. The only difference is in how you process the data.
public byte[] readPacket( DataInputStream dataIn ) throws IOException {
int length = dataIn.readInt();
byte[] packet = new byte[ length ];
dataIn.readFully( packet );
return packet;
}
public void writePacket( DataOutputStream dataOut, byte[] packet ) throws IOException {
dataOut.writeInt( packet.length );
dataOut.write( packet );
}
Only you would call these from some sort of loop preferably on background threads but it's not required for what you want to do. For your case you want to read in the file on the client side into a byte[] and then use writePacket to send it to the server. On the server side you would use readPacket to read in the file from the client. The same thing takes place when sending data back to the client but with the roles switched.
*i have have a folder in my pc in c:/ name share and in that i have 4 pictures after running my client and server code i got all 4 picture downloaded in my android emulator but only first image is correctly download other 3 are garbage
here is my code
SERVER SIDE
public class Multiplefilessending
{
public static void main(String[] args) throws IOException,EOFException
{
FileOutputStream fos;
BufferedOutputStream bos;
OutputStream output;
int len;
int smblen;
InputStream in;
boolean flag=true;
DataInputStream clientData;
BufferedInputStream clientBuff;
System.out.println("Waiting for Connection");
ServerSocket serverSocket = new ServerSocket(5991);
Socket clientSocket = null;
clientSocket = serverSocket.accept();
////////////////////////
File myFile = new File("C:/share");
File[] Files = myFile.listFiles();
OutputStream os = clientSocket.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeInt(Files.length);
for (int count=0;count<Files.length;count ++)
{
dos.writeUTF(Files[count].getName());
}
for (int count=0;count<Files.length;count ++)
{
int filesize = (int) Files[count].length();
dos.writeInt(filesize);
}
for (int count=0;count<Files.length;count ++)
{
int filesize = (int) Files[count].length();
byte [] buffer = new byte [filesize];
//FileInputStream fis = new FileInputStream(myFile);
FileInputStream fis = new FileInputStream(Files[count].toString());
BufferedInputStream bis = new BufferedInputStream(fis);
//Sending file name and file size to the server
bis.read(buffer, 0, buffer.length); //This line is important
dos.write(buffer, 0, buffer.length);
dos.flush();
//dos.close();
}
if (flag==false){
clientSocket = serverSocket.accept();
flag = true;
}
//Closing socket
//dos.close();
clientSocket.close();
}
}
And
CLIENT SIDE
Socket sock = new Socket("10.0.2.2", 5991);
System.out.println("Connecting.........");
FileOutputStream fos;
BufferedOutputStream bos;
OutputStream output;
DataOutputStream dos;
int len;
int smblen;
InputStream in;
boolean flag=true;
DataInputStream clientData;
BufferedInputStream clientBuff;
while (true)
{
//while(true && flag==true){
while(flag==true)
{
in = sock.getInputStream(); //used
clientData = new DataInputStream(in); //use
clientBuff = new BufferedInputStream(in); //use
int fileSize = clientData.read();
ArrayList<File>files=new ArrayList<File>(fileSize); ArrayList<Integer>sizes = new ArrayList<Integer>(fileSize); //store file size from client
//Start to accept those filename from server
for (int count=0;count < fileSize;count ++){
File ff=new File(clientData.readUTF());
files.add(ff);
}
for (int count=0;count < fileSize;count ++){
sizes.add(clientData.readInt());
}
for (int count =0;count < fileSize ;count ++)
{
if (fileSize - count == 1)
{
flag =false;
}
len=sizes.get(count);
//System.out.println("File Size ="+len);
output = new FileOutputStream("/mnt/sdcard/" + files.get(count));
dos=new DataOutputStream(output);
bos=new BufferedOutputStream(output);
byte[] buffer = new byte[1024];
bos.write(buffer, 0, buffer.length); //This line is important
while (len > 0 && (smblen = clientData.read(buffer)) > 0)
{
dos.write(buffer, 0, smblen);
len = len - smblen;
dos.flush();
}
dos.close(); //It should close to avoid continue deploy by resource under view
}
}
if (flag==false)
{
sock = new Socket("10.0.2.2", 5991);
flag = true;
}
} }
catch (UnknownHostException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
Your read loop is incorrect. You need to constrain the read length so you don't over-run into the next file:
while (len > 0 && (smblen = clientData,read(buffer, 0, len > buffer.length ? buffer.length : (int)len)) > 0)
{
bos.write(buffer, 0, smblen);
len -= smblen;
}
Other comments:
File lengths are longs, not ints.
Use a bigger buffer, at least 8192, and declare it once at the top of the method. You don't need a new one per file.
Don't flush inside the loop.
Don't keep recreating the streams. Use the same ones for the life of the socket, at both ends.
You should be writing to 'bos', not 'dos'. In fact you don't need the DataOutputStream to write to the file at all. Just the BufferedOutputStream and the FileOutputStream.
You should send one filename, one length, then one file, then the next filename, ... That way the sender can stop any time. That gets rid of the initial count, and it also gets rid of all that 'flag' nonsense. If you get EOFException reading the next name, the peer has closed the connection.