I'm trying to implement basic communication through sockets, what I have now is:
server start's to listen on socket,
this.serverSocket_ = new ServerSocket(this.serverPort_);
clientSocket = this.serverSocket_.accept();
client connects, and server starts separate thread to operate with that client,
both open Object output and input streams,
out = new ObjectOutputStream(clientSocket_.getOutputStream());
out.flush();
in = new ObjectInputStream(clientSocket_.getInputStream());
client sends two i Doubles, String and Long over that stream (flushes after each one),
out.writeObject(conf_);
out.flush();
out.writeObject(supp_);
out.flush();
out.writeObject(separator_);
out.flush();
out.writeObject(new Long(dataFile_.length()));
out.flush();
server succesfully receives those objects over previously opened streams,
conf_ = (Double) in_.readObject();
supp_ = (Double) in_.readObject();
separator_ = (String) in_.readObject();
fileSize_ = (Long) in_.readObject();
and now "the hard part",
clients wants to send a file so opens different output stream (not object output stream) and sends the file,
FileInputStream fis = new FileInputStream(dataFile_);
BufferedInputStream bis = new BufferedInputStream(fis);
OutputStream os = clientSocket_.getOutputStream();
while (current < fileSize) {
bytesRead = bis.read(mybytearray, 0, mybytearray.length);
if (bytesRead >= 0) {
os.write(mybytearray, 0, mybytearray.length);
current += bytesRead;
}
progressBar_.setValue(current);
progressBar_.repaint();
}
os.flush();
the server receives the file (also uses simple input stream instead ObjectInputStream),
int bytesRead;
int current = 0;
tmpFile_ = File.createTempFile("BasketAnalysis", "rec.dat");
byte[] mybytearray = new byte[fileSize];
InputStream is = clientSocket_.getInputStream();
FileOutputStream fos = new FileOutputStream(tmpFile_);
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead = is.read(mybytearray, 0, mybytearray.length);
current = bytesRead;
do {
bytesRead = is.read(mybytearray, current,
(mybytearray.length - current));
if (bytesRead >= 0)
current += bytesRead;
} while ((bytesRead > -1) && (current < fileSize));
bos.write(mybytearray, 0, current);
bos.flush();
bos.close();
so far everything works fine, file is received, but now server performs some time consuming processing on that file after which sends response with whe results to client,
String resp = new String("Some processing result...");
out_.writeObject(resp);
out_.flush();
the client is supposed to receive the result what finishes the whole communication,
String message = (String) in.readObject();
Console.info("server > " + message);
Unfortunately, that last step on client side fails with exception:
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at basketAnalysis.client.Client.run(Client.java:74)
at java.lang.Thread.run(Unknown Source)
I want client to block on waiting for server response after sending the file, but it suddenly finishes with the exception after sending the file. I am pretty sure that I do something wrong with switching between simple streams and Object streams.
Does anybody know what should I change to haave it working?
Thank you in advance!
I think your basic misunderstanding is here:
clients wants to send a file so opens different output stream
OutputStream os = clientSocket_.getOutputStream();
That doesn't open a different output stream - that will get another reference to the same output stream which you've already got wrapped in the ObjectOutputStream. If you want two streams of data, you'll need to open two separate connections.
Related
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 run the server and client on separate cmd windows. The server prints out "Upload successful" and indeed the file gets uploaded to the server but the client freezes and i have to quit the client process using Ctrl+C. It seems to me that the client cannot break out of the while loop. Please tell me where i am going wrong?
(The code snippets are parts of much larger code body that i am writing to implement file read, write, read/write-lock, delete file etc from the server. Once a request to upload the file from the client is handled by the server I want the process to return to the command line menu i have incorporated with the client program[not shown below]. So it is important that the client returns to that user interface. Any help is greatly appreciated. Thanks in advance! )
Client side:
// initialized client and server connection made...
BufferedReader filePath = new BufferedReader(new InputStreamReader(System.in));
String pathname = filePath.readLine();
try{
File file_to_upload = new File(pathname);
byte[] bytearray = new byte[(int) file_to_upload.length()];
OutputStream os = client1.getOutputStream();
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file_to_upload));
do {
bis.read(bytearray, 0, bytearray.length);
os.write(bytearray, 0, bytearray.length);
os.flush();
bis.close();
} while (bis.read(bytearray, 0, bytearray.length)!= -1);
}
catch(FileNotFoundException e){
System.out.println(e);
}
catch(IOException e){
System.out.println(e);
}
System.out.println("\n" + inFromServer.readLine() + "\n");
client1.close();
break;
server side:
byte[] mybytearray = new byte[1];
InputStream is = server1accept.getInputStream();
FileOutputStream fos = new FileOutputStream("234rews");
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = is.read(mybytearray, 0, mybytearray.length);
bos.write(mybytearray, 0, bytesRead);
bos.close();
outToClient.writeBytes("Uploaded");
System.out.println("Upload Successful");
Both your copy loops are incorrect. The canonical way to copy between streams in Java is:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
At present you are doing extra reads and ignoring read() results and all kinds of other strange things. Use this code at both ends, with any buffer size greater than zero.
I have one client and one server communicating with each other via TCP sockets. The client would like to transfer two files and some description of the files to the server. I would like to design a protocol that once a socket is established between the client and the server, the server would expect to receive the file description first and then the two files. Currently, with the following code, the server can receive the description but fails to distinguish the two files (the two files transferred from the client are merged into one single file at the server). I found similar threads on this issue. But they separately discussed "file info + one single file" and "multiple file without pre-file-info". Please give me a hint on resolving this issue. Many thanks.
Sever-side code
dis = new DataInputStream(clientSocket.getInputStream());
callInfo = dis.readUTF();
callInfos = callInfo.split(" ");
FileOutputStream fos = new FileOutputStream(File1);
byte[] buffer = new byte[clientSocket.getReceiveBufferSize()];
int bytesReceived = 0;
while ((bytesReceived = dis.read(buffer)) > 0)
fos.write(buffer, 0, bytesReceived);
fos.flush();
fos.close();
fos = new FileOutputStream(File2);
while ((bytesReceived = dis.read(buffer)) > 0)
fos.write(buffer, 0, bytesReceived);
fos.flush();
fos.close();
Client-side code
String fileIno = "fileIno";
byte[] buffer = new byte[socket.getSendBufferSize()];
int bytesRead = 0;
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeUTF(fileInfo);
FileInputStream file = new FileInputStream(File1);
while ((bytesRead = file.read(buffer)) > 0)
dos.write(buffer, 0, bytesRead);
dos.flush();
file.close();
file = new FileInputStream(File2);
while ((bytesRead = file.read(buffer)) > 0)
dos.write(buffer, 0, bytesRead);
dos.flush();
file.close();
Design your protocol such that the "file description" information includes the number of bytes in each file. Then you will know where the first file begins and ends and where the second file begins and ends.
I have a problem to send a file(not necessarily a txt file) over a socket.I have 2 classes:Server,Client.When I read from a socket output stream and want to write the bytes in a file,it looks working but when i open the file it has nothing.(corrupted showing the size=0 kb).I also want it to transfer all kind of file over a socket.I don't want to use appache commons net.
Here is my code
Server class
FileOutputStream toFile1 = new FileOutputStream(f);
BufferedOutputStream toFile= new BufferedOutputStream(toFile1);
BufferedInputStream bis=new BufferedInputStream(incoming.getInputStream());
byte[]buffer=new byte[2048];
int bytesRead=0;
while((bytesRead = bis.read(buffer)) >= 0)
{
toFile.write(buffer, 0, bytesRead);
}
toFile.close();
toFile1.close();
bis.close();
out.println("226 Connection Closed");
out.flush();
}
Client class
BufferedOutputStream output = new BufferedOutputStream(socket.getOutputStream());
byte[] buffer = new byte[60*2024];
int bytesRead = 0;
while ((bytesRead = input.read(buffer,0,60*1024)) != -1) {
output.write(buffer, 0, bytesRead);
}
The only way that can happen with that code is if you are sending a zero length file, or maybe reading from a file input stream that is already positioned at EOF, or else you are looking at the wrong file afterwards.
I have a Java server class like this:
ServerSocket servsock = new ServerSocket(63456);
boolean read = false;
while (!read) {
Socket sock = servsock.accept();
int length = 1024;
byte[] mybytearray = new byte[length];
OutputStream os = sock.getOutputStream();
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
while (true) {
int i = bis.read(mybytearray, 0, mybytearray.length);
if (i == 1) {
break;
}
os.write(mybytearray, 0, mybytearray.length);
os.flush();
}
sock.close();
read = true;
}
`
And the client is like this:
Socket sock = new Socket("127.0.0.1", 63456);
byte[] mybytearray = new byte[1024];
InputStream is = sock.getInputStream();
FileOutputStream fos = new FileOutputStream("C:/tmp/NEWtmp.rar");
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = is.read(mybytearray, 0, mybytearray.length);
while(bytesRead != -1 ) {
bos.write(mybytearray, 0, bytesRead);
bytesRead = is.read(mybytearray, 0, mybytearray.length);
}
bos.close();
sock.close();
One question is: Why the loop does not stop at the end of the file?
A second question would be, why is also so slow?
It does not stop because
if (i == 1) {
in your server source should be
if (i == -1) {
Or, if you want to be really safe:
if (i <= 0) {
Also, you risk data corruption with this line:
os.write(mybytearray, 0, mybytearray.length);
You should change this to:
os.write(mybytearray, 0, i);
On performance -- move the os.flush(); call to outside the while loop. When you flush a network stream, you are forcing it to dispatch any buffered data to the network. This is forcing the network layer to send and acknowledge 1024-byte TCP payloads (larger Ethernet payloads, of course) which is probably significantly smaller than your PMTU. You only need to flush when you are done sending data, or when you want the client to receive the buffered data now. Removing the flush call from each iteration will allow the OS-level network buffer to do its job, and segment the data into as few packets as possible.
Second question - your client reads bytes directly from the raw socket stream. Use the BufferedInputStream/BufferedOutputStream decorators, this should increase performance:
Server Side
BufferedOutputStream os = new BufferedOutputStream(sock.getOutputStream());
Client side
BufferedInputStream is = new BufferedInputStream(sock.getInputStream());
The raw streams are not buffered (AFAIK) so you have to add the buffering manually, if needed.