Hallo i an trying to send Firmware file to modem board thru telnet.
Here is my code:
Socket s = null;
try {
SocketAddress socketAddress = new InetSocketAddress(InetAddress.getByName(addr), 23);
s = new Socket();
s.connect(socketAddress, 1000);
InputStream inputStream = s.getInputStream();
OutputStream outputStream = s.getOutputStream();
outputStream.write( (login + "\n") .getBytes());
Thread.sleep(300);
outputStream.write( (password + "\n") .getBytes());
Thread.sleep(300);
outputStream.write(("swupdate" + "\n").getBytes());
Thread.sleep(300);
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(path_frm_vdsl);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
// Read File Line By Line
while ((line = br.readLine()) != null) {
// Print the content on the console
line = br.readLine();
if (line == null) {
Thread.sleep(1000);
} else {
//System.out.println(line);
outputStream.write(line.getBytes());
Log.v("---", line.getBytes() + "" + consumeInput(500, inputStream));
//Log.v("Update_Modem","Updated " + consumeInput(500, inputStream));
//outputStream.write(line.getBytes());
Thread.sleep(10);
}
}
It simply logs in sends swupdate command and dumps firmware file to output. After first line of input i am having java.net.SocketException: Broken pipe
And i can not read all file at once, not enough memory exception. (3Mb)
You know telnet uses in-channel signalling? the data stream contains escaped command instructions. When you open a telnet connection, a whole slew of initial commands are passed back and forth, as the server and client determine each others capabilities and preferences.
You may well find your byte stream is corrupted, if you just take whatever you get turning up at the server. You will need to honour the telnet protocol, e.g. properly understand the byte stream you're receiving.
The line terminator in the Telnet protcol is \r\n.
But why would you want to read the whole file into memory? And why all the sleeps? And why are you skipping every second line? And what is consumeInput()?
Just read and write bytes.
Not sure how your receiving end wants the firmware, plain binary, hex encoded, base64 encoded?
Anyway, here is how you would send it in plain binary
Socket s = null;
try {
SocketAddress socketAddress = new InetSocketAddress(InetAddress.getByName(addr), 23);
s = new Socket();
s.connect(socketAddress, 1000);
InputStream inputStream = s.getInputStream();
OutputStream outputStream = s.getOutputStream();
outputStream.write((login + "\n").getBytes());
Thread.sleep(300);
outputStream.write((password + "\n").getBytes());
Thread.sleep(300);
outputStream.write(("swupdate" + "\n").getBytes());
Thread.sleep(300);
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(path_frm_vdsl);
byte[] buffer = new byte[1024];
int fillSize;
// Read File chunk by chunk
while ((fillSize = fstream.read(buffer)) != -1) {
outputStream.write(buffer, 0, fillSize);
}
outputStream.close();
} finally {
s.close();
}
So, read the file in chunks until there is no more data (read returns -1) and write the chunk (read returns how much was actually read).
Related
I write some file transfer application. Between client and server i send 3 type of data:
1) Some "command words" like READY_FOR_UPLOAD.
2) Some serializable data
3) Big files in byte array.
I get client connections on server socket and create new Thread for every client.
try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),true);
InputStream inputStream = clientSocket.getInputStream();
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream)) {}
I create these streams using try with resources and there is no problem.
I use:
1) "in" for read messages from client:
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
2)"out" for send messages.
3)"inputStream" for receive files:
try (FileOutputStream fileOutputStream = new
FileOutputStream("D:\\testDownload.zip");
BufferedOutputStream bufferedOutputStream = new
BufferedOutputStream(fileOutputStream)
) {
byte[] buffer = new byte[1024 * 100];
int read;
while ((read = inputStream.read(buffer)) != -1) {
bufferedOutputStream.write(buffer, 0, read);
}
}
4) "objectInputStream" for serializable data:
Object object;
if ((object = objectInputStream.readObject()) != null) {
if (object instanceof File) {
File file = (File) object;
System.out.println(file.getAbsolutePath());
System.out.println(file.length());
}
}
While i use them separately - there is no problem. But i need read "command word" first of all i.e. in start of the method run of my tread.
public void run() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),true);
InputStream inputStream = clientSocket.getInputStream();
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream)) {
String line;
if ((line = in.readLine()) != null) {
System.out.println(line);
there i should try to read other types of data
}
}
And if this is no "command word" i can try read serializable data or file data. But this is a problem! I may try to read a line but it can be part of serializable data of file data and because inputsream readed "one-by-one" byte method, i can't try read it like serializable or file data, because input not whole anymore, i read some data in "readLine()". I should know what type of data i receive before i try to read it. How can it be done?
You need to create a protocol - rules how client and server exchange information between them.
When you write data you specify what data type you are sending and its size. And don't use ObjectInputStream and ObjectOutputStream on Socket - convert the data into array of bytes, so that you know what the size is when you writing and then convert them back. Send the data as bytes.
I'm having issues with this question right now.
For this question, I have to:
Client side: compress each input line from the console, send it to the server and decompress each message from server
Server side: decompress data from client, change the lower-case letters to upper case, compress it and send back to the client
The best I can do is do everything above with only ONE line.
Client Side:
/* SOCKET CONNECTING STUFF UP HERE */
/*PROBLEMS START AROUND HERE */
String line;
BufferedReader bis = new BufferedReader(new InputStreamReader(System.in));
DeflaterOutputStream compress = new DeflaterOutputStream(socket.getOutputStream(), true);
InflaterInputStream decompress = new InflaterInputStream(socket.getInputStream());
BufferedReader fromClient = new BufferedReader(new InputStreamReader(decompress));
line = bis.readLine();
line = line + "\n";
compress.write(line.getBytes(), 0, line.length());
compress.finish();
System.out.println("Message sent: " + line);
System.out.println("Message Returned : " +fromClient.readLine());
/* closing the streams here */
bis.close();
decompress.close();
compress.close();
fromClient.close();
socket.close();
}
}
Server Side:
String line = "";
OutputStream outstream = new FileOutputStream("compessserver.txt");
InflaterInputStream decompress = new InflaterInputStream(clientsocket.getInputStream());
BufferedReader fromClient = new BufferedReader(new InputStreamReader(decompress));
DeflaterOutputStream compress = new DeflaterOutputStream(clientsocket.getOutputStream());
while ((line = fromClient.readLine()) != null) {
String upperLine = line.toUpperCase();
System.out.println("Message received and converted: " + upperLine);
System.out.println();
upperLine = upperLine + "\n";
byte[] input = upperLine.getBytes();
outstream.write(input);
outstream.write("\r\n".getBytes());
compress.write(input);
System.out.println("Message returned : " + upperLine);
compress.finish();
if (upperLine.equalsIgnoreCase("x")) {
break;
}
}
decompress.close();
compress.close();
fromClient.close();
outstream.close();
socket.close();
}
}
I really need help in this please. If I try to make this multiple inputs instead, the whole code just messes up. Been at this for days.
EDIT: Forgot to mention this. What I'm supposed to do is input a line, compress it, send to server, server decompress it and upper case letters, compress it, send back to client. And then I supposed to input more lines until I put in a single letter like "Q" which in case, ends the program
I tried the following code to make it work for multiple lines
Second Try Client Side:
String line;
BufferedReader bis = new BufferedReader(new InputStreamReader(System.in));
DeflaterOutputStream compress = new DeflaterOutputStream(socket.getOutputStream(), true);
InflaterInputStream decompress = new InflaterInputStream(socket.getInputStream());
BufferedReader fromClient = new BufferedReader(new InputStreamReader(decompress));
line = bis.readLine();
while ((!line.equalsIgnoreCase("x"))) {
compress.write(line.getBytes(), 0, line.length());
System.out.println("Message sent: " + line);
System.out.println("Message returned:" +fromClient.readLine() );
line = bis.readLine();
}
bis.close();
fromClient.close();
socket.close();
}
}
Second Try Server Side:
OutputStream outstream = new FileOutputStream("compessserver.txt");
InflaterInputStream decompress = new InflaterInputStream(clientsocket.getInputStream());
BufferedReader fromClient = new BufferedReader(new InputStreamReader(decompress));
DeflaterOutputStream compress = new DeflaterOutputStream(clientsocket.getOutputStream());
while ((line = fromClient.readLine()) != null) {
String upperLine = line.toUpperCase();
System.out.println("Message received and converted: " + upperLine);
System.out.println();
upperLine = upperLine + "\n";
byte[] input = upperLine.getBytes();
outstream.write(input);
outstream.write("\r\n".getBytes());
compress.write(input);
System.out.println("Message returned : " + upperLine);
if (upperLine.equalsIgnoreCase("x")) {
break;
}
}
decompress.close();
fromClient.close();
outstream.close();
socket.close();
}
}
You can't use these streams interactively. You would have to call finish() after every write, or rather before every read, which means you could only do one write. They are designed for large one-way streams, not interactive request/response sessions.
In any case there is no advantage to be gained from compressing single lines. You need a lot of data for compression to start working.
NB compress.write(line.getBytes(), 0, line.length()) isn't valid. It assumes the number of chars in the String is the same as the number of bytes when converted, which isn't always so. It should be compress.write(line.getBytes(), 0, line.getBytes().length()), or more simply compress.write(line.getBytes()).
I have stucked for 4h already with the sockets, the way I am using is is that there is only one application as client and server, once the client connect it is opening the theard with new client and waiting for message.
Once the message is send to the server, the client will receive respond, that part is working without any problems.
Part of the Client Theard:
while (true)
{
InputStreamReader IR = new InputStreamReader(clientSocket.getInputStream());
BufferedReader BR = new BufferedReader(IR);
PrintStream PS = new PrintStream(clientSocket.getOutputStream());
String message = BR.readLine();
if (message != null)
{
System.out.println(clientSocket.getInetAddress() + ":" + clientSocket.getPort() + " has connected."+message);
if (message.equals("exit"))
{
PS.println("Exiting...");
exit();
}
else if (message.equals("list"))
{
getList(PS);
}
else if ((message.contains("get") && (message.contains(",") && (message.contains(" ")))))
{
String[] spliter = message.split(" ");
String[] file = spliter[1].split(",");
String file_name = file[0];
String file_md5 = file[1];
getFile(file_name, file_md5, clientSocket);
}
}
else
{
break;
}
}
There are 2 messages that the server is supporting, the first one is "list" and the send one command is "get with values".
if client will request command "list" it will run this:
There is a "server/client", it is sending request and receive the one line string and it is working without any problem, I am receiving the list of files from the server.
PrintStream PS = new PrintStream(clientSocket.getOutputStream());
PS.println("list");
InputStreamReader IR = new InputStreamReader(clientSocket.getInputStream());
BufferedReader BR = new BufferedReader(IR);
String lista_plikow = BR.readLine();
if ( lista_plikow != null)
{
return lista_plikow;
}
But I have problems to send the files over the sockets using code found on stackoverflow, but the "receiving" is not working, there is my receive function, the loop is always as 0 (even if first bytes length is correct), but the length of the bytes is correct, it is using newly created file but nothing is happening, the file is always on use, and has 0 bytes instead of content of the PS.println.
PrintStream PS = new PrintStream(clientSocket.getOutputStream());
PS.println("get "+filename+","+file_md5);
int bytesRead;
int current = 0;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
try
{
byte [] mybytearray = new byte [Integer.parseInt(size)];
InputStream is = clientSocket.getInputStream();
fos = new FileOutputStream(filename + ".recived");
bos = new BufferedOutputStream(fos);
bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;
System.out.println("X" + bytesRead);
do {
bytesRead =
is.read(mybytearray, current, (mybytearray.length-current));
System.out.println(bytesRead + " = " + current + " " + (mybytearray.length-current));
if(bytesRead >= 0) current += bytesRead;
System.out.println(bytesRead);
} while(bytesRead > -1);
bos.write(mybytearray, 0 , current);
bos.flush();
System.out.println("File " + "recived." +filename.replace(":", " ")
+ " downloaded (" + current + " bytes read)");
}catch (Exception e)
{
System.out.println(e.getMessage());
}
And last part of the scrip the "PS.println("get "+filename+","+file_md5);" is doing exactly this one, the sending is working fine:
FileInputStream fis = null;
BufferedInputStream bis = null;
OutputStream os = null;
String the_file = TorrentAppGui.folder+"\\"+file_name.replace(":", " ");
File myFile = new File (the_file);
byte [] mybytearray = new byte [(int)myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
os = clientSocket.getOutputStream();
System.out.println("Sending " + the_file + "(" + mybytearray.length + " bytes)");
os.write(mybytearray, 0, mybytearray.length);
os.flush();
System.out.println("Done.");
I have no idea why I cannot save the bytes received by the "get" command, do you have any ideas?
I know that only the "receve" function is not working, because if I looged to the application via telnet I could get the file in the console, but it doesnt reach my target. See the screen from cli.
You can't mixed buffered and unbuffered streams/readers/writers on the same socket. You will lose data in the buffers. Use the same stream pair for the life of the socket. In this case I would use DataInputStream and DataOutputStream, and the readUTF()/writeUTF() methods for the messages and filenames. You will also need to send the file length ahead of the file, unless the file is the last thing sent over the connection: otherwise the peer won't know when to stop reading the file and go back and start reading messages again.
I am trying to create a program with Java which takes a screenshot of the user's screen, compresses the image, and sends it to a server over sockets.
For some reason the image is saved corrupted in the end (it's unreadable). Can you maybe help me find what the problem could be?
CLIENT: (the screenshot is entered as a BufferedImage, and the returned byte array is then returned to the second function which sends it to the server)
public static byte[] compressImage(BufferedImage image) throws IOException {
System.out.println("starting compression");
ByteArrayOutputStream os = new ByteArrayOutputStream(37628);
float quality = 0.16f;
// create a BufferedImage as the result of decoding the supplied InputStream
// get all image writers for JPG format
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
//Iterator iter = ImageIO.getImageWritersByFormatName("jpeg");
if (!writers.hasNext())
throw new IllegalStateException("No writers found");
ImageWriter writer = (ImageWriter) writers.next();
ImageOutputStream ios = ImageIO.createImageOutputStream(os);
writer.setOutput(ios);
ImageWriteParam param = writer.getDefaultWriteParam();
// compress to a given quality
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(quality);
// appends a complete image stream containing a single image and
//associated stream and image metadata and thumbnails to the output
writer.write(null, new IIOImage(image, null, null), param);
os.flush();
return os.toByteArray();
}
public void uploadShot(byte[] imgData, String nickname) {
try {
/* Try to connect to the server on localhost, port 5555 */
Socket sk = new Socket("localhost", 23232);
OutputStream output = sk.getOutputStream();
/* Send filename to server */
OutputStreamWriter outputStream = new OutputStreamWriter(sk.getOutputStream());
outputStream.write(nickname + "\n");
outputStream.flush();
/* Get response from server */
BufferedReader inReader = new BufferedReader(new InputStreamReader(sk.getInputStream()));
String serverStatus = inReader.readLine(); // Read the first line
/* If server is ready, send the file */
if (serverStatus.equals("READY")){
int len = imgData.length;
int start = 0;
if (len < 0)
throw new IllegalArgumentException("Negative length not allowed");
if (start < 0 || start >= imgData.length)
throw new IndexOutOfBoundsException("Out of bounds: " + start);
// Other checks if needed.
// May be better to save the streams in the support class;
// just like the socket variable.
OutputStream out = sk.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
dos.writeInt(len);
if (len > 0) {
dos.write(imgData, start, len);
}
dos.close();
output.close();
sk.close();
System.out.println("Transfer complete.");
}
} catch (Exception ex){
/* Catch any errors */
System.out.println(ex.getMessage());
}
}
SERVER: (the received image is saved to the folder mentioned with a timestamp)
public static void main(String args[]) throws Exception{
System.out.println("Server running...");
/* Listen on port 5555 */
ServerSocket server = new ServerSocket(23232);
/* Accept the sk */
Socket sk = server.accept();
System.out.println("Server accepted client");
InputStream input = sk.getInputStream();
BufferedReader inReader = new BufferedReader(new InputStreamReader(sk.getInputStream()));
BufferedWriter outReader = new BufferedWriter(new OutputStreamWriter(sk.getOutputStream()));
/* Read the filename */
String nickname = inReader.readLine();
if ( !nickname.equals("") ){
/* Reply back to client with READY status */
outReader.write("READY\n");
outReader.flush();
}
String current = "/home/kasgel/screenshots";
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy__HH:mm:ss");
Date timestamp = new Date();
File filename = new File(current + "/" + nickname + "-" + dateFormat.format(timestamp) + ".jpg");
if (!filename.exists()) {
filename.createNewFile();
}
FileOutputStream wr = new FileOutputStream(filename);
byte[] buffer = new byte[sk.getReceiveBufferSize()];
int bytesReceived = 0;
while((bytesReceived = input.read(buffer))>0) {
wr.write(buffer,0,bytesReceived);
}
wr.close();
}
And the error message which I get when opening the saved screenshot is the following:
display.im6: Not a JPEG file: starts with 0x00 0x03 `MyNick-30-03-2015__19:27:58.jpg' # error/jpeg.c/JPEGErrorHandler/316.
When you're writing your image, you first write a 32-bit signed integer containing the length in bytes of the image:
dos.writeInt(len);
if (len > 0) {
dos.write(imgData, start, len);
}
But when you're reading the image back, you don't read the length first; you're reading all the data (including the length) as if they were part of the image.
You have a second problem though, that will by itself also cause this problem. When you create a BufferedReader, and call readLine on it, it will read beyond the newline - it will read until its buffer is full. Which is not a problem if you keep reading from it, but after reading the line, you continue reading from the underlying InputStream, which will often have more bytes consumed from it after the newline.
The solution is: only use one abstraction to read/write data. In this case, the easiest is absolutely to use DataOutputStream and DataInputStream. Write the file name using writeUTF and read it back using readUTF. Write the length of the file with writeInt and read it back with readInt. Write the data with write and read it with read - and make sure to read only as many bytes as you received from the readInt call. And most important of all, keep using the same DataOutputStream and DataInputStream instances; don't constructor buffered readers and input-streams on the same underlying InputStream
Is there any way to make the method readline() (from bufferedReader) block until it has in fact something to read??
I'm creating an client/server application socketBased and I have this
The Server reads and then writes. The Client writes and then reads.. this is the communication between client/server (based on sockets)
The only problem is that on the server I'm reading with bufferedReader.readLine() which isn't a blocking method. I have already tried replacing the bufferedReader.readLine() by dataInputstream().read() (handle all the byte stuffs and getting out when -1 is received) and it isn't working either.
The problem in all this is that the server is expecting to read but do not blocks. the client is only going to write to the server (through a socket) when the user press a button (so the server must be waiting for reading and it is not)
On the server side i have this:
BufferedReader READ = new BufferedReader(new InputStreamReader(skt.getInputStream()));
BufferedWriter WRITE = new BufferedWriter(new OutputStreamWriter(skt.getOutputStream()));
FileInputStream fstream = new FileInputStream(file);
DataInputStream in = new DataInputStream(fstream);
boolean FLAG = true;
String s = new String("#$");
while (FLAG) {
if (skt == null)
FLAG = false;
// READING FROM THE CLIENT
while (!READ.ready()){System.out.println("Blocking")};
while ((s = READ.readLine()) != null) {
System.out.println("RECEIVING: " + s);
System.out.println("$$$");
}
System.out.print("hi");
// READING FROM THE FILE AND SENDING TO THE CLIENT
//WRITTING TO THE CLIENT
while ((strLine = in.readLine()) != null) {
System.out.println("SENDING: " + strLine);
strLine += "\n";
WRITE.write(strLine);
WRITE.flush();
strLine = new String();
}
}
On the Client side i have this:
//READING FROM THE FILE AND SENDING TO THE SERVER
while((strLine = in.readLine()) != null)
{
strLine += "\n";
soma+=strLine.length();
WRITE.write(strLine);
WRITE.flush();
TextArea1.append(strLine);
ProgressBar.setValue(soma);
ProgressBar.repaint();
};
in.close();
ProgressBar.setValue(0);
soma=0;
//READING FROM THE SERVER
while((strLine=READ.readLine()) != null)
{
strLine+="\n";
soma+=strLine.length();
TextArea2.append(strLine);
strLine = new String();
ProgressBar.setValue(soma);
ProgressBar.repaint();
}
in.close();
fstream.close();
WRITE.close();
READ.close();
Skt.close();
NOTE: Skt is a socket connecting client to server.
the problem here is that. When the client connects to the server, the server expects to read from the socket right after the connection is established.. however the code on the client (writing to the server) is only expected to run when the user presses a button.. So, the server must be blocked until the client in fact writes something to the socket which is not (the server is not blocking). :-/ hope to make my self more clear this time.. Sorry
BufferedReader.readLine() always blocks until it finds '\n'.
If you can give examples of data you're sending around, I might help you further.
Try to use file lock approach like:
file = new RandomAccessFile("file.txt", "rw");
FileChannel channel = file.getChannel();
fl = channel.tryLock();
// file now is locked
fl.release();