Java: Bytes are not transferred correctly - java

I've made a server that should let the client udpate a file. All in all it is working, but some bytes, for example HEX 9D is getting to HEX 3F. I have no more ideas and didn't find anything on the web. My server code:
package de;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class UpdateThread extends Thread {
public UpdateThread(Socket s) {
socket = s;
}
public void run() {
try {
execute();
} catch (IOException e) {
e.printStackTrace();
}
}
#SuppressWarnings("resource")
public void execute() throws IOException {
if (UpdateProvider.update) {
int i = 0;
SocketTools.sendData(1, socket);
File file = new File("." + System.getProperty("file.separator").toString() + "update_package.jar");
OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream());
FileReader reader = new FileReader(file);
while ((i = reader.read()) != -1) {
writer.write(i);
}
writer.flush();
writer.close();
} else {
SocketTools.sendData(0, socket);
}
}
private Socket socket;
}
And my client code:
package de;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class Main {
#SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
Socket s = new Socket("localhost", 16642);
BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
//InputStreamReader reader = new InputStreamReader(s.getInputStream());
int i = 0;
FileWriter writer = new FileWriter(new File("C:\\update_package.jar"));
int state = reader.read();
if (state == 48) {
System.exit(0);
}
if (state == 49) {
while ((i = reader.read()) != -1) {
System.out.println(i);
writer.write(i);
}
System.out.println("ENDE");
writer.flush();
}
}
}

You're not specifying a proper encoding for the transmission (you should use InputStream/OutputStreams instead of Reader/Writer for this anyways, since you're handling binary data and not text). 0x3F is the questionmark '?', meaning that a non-ASCII character (128 or higher) has been converted.
So lose the Readers and Writers and go with Streams.

Encoding is needed for text files only. I looked at your source code. You are trasferring a jar, which is a binary file, not text. If you use use text processing classes for binary data, you can get a lot of unpredictable transformations. Don't use OutputStreamWriter. Use socket.getOutputStream() directly:
OutputStream = socket.getOutputStream();
...
out.write(...);
Same for client. Don't use InputStreamReader. Use s.getInputStream() directly:
InputStream in = s.getInputStream();
...
in.read(...);

Related

Java Client/Server does not return UTF-8 string

I tried to pass a UTF-8 String through a Java Socket.
The String contains a mix of English and Greek.
My problem is that when the message passes through the socket all Greek characters turn to "?".
I already tried to set the InputStream character set to UTF-8.
Bellow is my attempt, any help will be appreciated.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class Main {
public static void main(String[] args) {
try {
String msg = "This is a test - Αυτο ειναι μια δοκιμη";
ServerSocket serverSocket = new ServerSocket(9999);
Thread host = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
Socket socket = serverSocket.accept();
if (socket != null) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
while (true) {
String line = bufferedReader.readLine();
if (line != null) {
System.out.println(line);
} else if(bufferedReader.read() < 0) {
break;
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
host.start();
Socket socket = new Socket("127.0.0.1", 9999);
PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);
printWriter.println(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Edit 1
I run and build my code through IntelliJ Idea and that is where I found the problem.
But after #Ihar Sadounikau comment I updated and my JDK and tried to build and run through PowerShell but still the problem persists.
And this is my result
& 'C:\Program Files\Java\jdk-13.0.2\bin\java.exe' Main
This is a test - ??τ? ε??α? ??α δ?????
With this line: PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true); you are converting a bytestream (i.e., InputStream / OutputStream into a charstream (i.e., Reader / Writer). Anytime you do that, if you fail to specify the encoding, you get platform default, which is unlikely what you want.
You (and #IharSadounikau) are seeing different results, because the 'platform default' is switching around on you. It's one of the reasons you REALLY do not want to use it, ever. Figuring out that your code has the bug where it only works if your platform default encoding is the same as the person who developed it – is generally untestable.
Try new PrintWriter(socket.getOutputStream(), true, StandardCharsets.UTF_8).
Maybe this will help:
String msgEncode = URLEncoder.encode(msg, "UTF-8");
printWriter.println(msgEncode);
And:
String line = bufferedReader.readLine();
String msgDecode = URLDecoder.decode(line, "UTF-8");

Failed to send data stream by sockets in Java

I'm trying to stream audio through TCP sockets in java, using the Java sound api.
Up there all right, the problem comes when the client will play that data buffer that comes from the server, when entering the play method, automatically shows the following error:
Exception in thread "main" javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input stream
at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1121)
at AudioClient.play(AudioClient.java:37)
at AudioClient.main(AudioClient.java:18)
I do not know why he shows it, or what I'm doing wrong.
This is the server code, which looks for the file and sends it to the client
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class AudioServer {
public static void main(String[] args) throws IOException {
File soundFile = AudioUtil.getSoundFile("C:\\Users\\Carlos\\Desktop\\03- Walk.wav");
System.out.println("server: " + soundFile);
try (ServerSocket serverSocker = new ServerSocket(6666);
FileInputStream in = new FileInputStream(soundFile)) {
if (serverSocker.isBound()) {
Socket client = serverSocker.accept();
OutputStream out = client.getOutputStream();
byte buffer[] = new byte[2048];
int count;
while ((count = in.read(buffer)) != -1)
out.write(buffer, 0, count);
}
}
System.out.println("server: shutdown");
}
}
And this is the client code, which captures that data flow and reproduces it
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.net.Socket;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class AudioClient {
public static void main(String[] args) throws Exception {
// play soundfile from server
System.out.println("Client: reading from 192.168.0.19:6666");
try (Socket socket = new Socket("192.168.0.19", 6666)) {
if (socket.isConnected()) {
InputStream in = new BufferedInputStream(socket.getInputStream());
play(in);
}
}
System.out.println("Client: end");
}
private static synchronized void play(final InputStream in) throws Exception {
AudioInputStream ais = AudioSystem.getAudioInputStream(in);
try (Clip clip = AudioSystem.getClip()) {
clip.open(ais);
clip.start();
Thread.sleep(100); // given clip.drain a chance to start
clip.drain();
}
}
}
Additionally, there is an AudioUtils class, which only contains a static method, this static method only throws an exception in case the file passed by the programmer is not a file or does not exist. The code is the following
import java.io.File;
public class AudioUtil {
public static File getSoundFile(String fileName) {
File soundFile = new File(fileName);
if (!soundFile.exists() || !soundFile.isFile())
throw new IllegalArgumentException("not a file: " + soundFile);
return soundFile;
}
}
It should also be clarified that both classes, both server and controller have the proncipal method because they are 2 separate programs. My question is, how do I solve this error, I really do not know where to start. Thank you

java: Transfer a file to the server and get the file from the server in upper case

i want to send a .txt file from the client to server and get it back in upper case.
But this code do nothing.can anyone tell what is wrong here..?
SERVER : getting file from client and sending it back in upper case to the client.
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
public class Assignment4_Server {
public static void main(String[] args) throws IOException {
byte[] bytearray = new byte[4096];
try (ServerSocket ss = new ServerSocket(4444)) {
Socket s = ss.accept();
InputStream is = s.getInputStream();
OutputStream os = s.getOutputStream();
int count;
String data = null ;
while((count = is.read(bytearray))>0){
data = Arrays.toString(bytearray).toUpperCase();
byte[] bytearrayout = data.getBytes();
os.write(bytearrayout);
}
s.close();
}
}
}
CLIENT : sending text.txt file to the server and getting file back after converted in upper case.
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class Assignment4_client {
public static void main(String[] args) throws IOException {
File file = new File("test.txt");
byte[] bytearray = new byte[4096];
Socket sc = new Socket("localhost",4444);
//send file
int countS , countR;
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
OutputStream os = sc.getOutputStream();
while((countS = bis.read(bytearray))>0){
os.write(bytearray);
}
//recieve file in uppercase from server
InputStream is = sc.getInputStream();
byte[] bytearray2 = new byte[4096];
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
while((countR = is.read(bytearray2))>0){
bos.write(bytearray2);
}
}
}
Here is a code that should help you. But before reading it you should be aware of what is happening:
Your client is not sending a 'stop reading' information to the server (read the client code below). That's why the server is stuck in the while loop when it is trying to read the data sent by the client. That is probably why you have tried to send the data back directly to the client. Shut down the socket output from the client side to respect the Socket contract and correctly free the socket (see TCP/IP).
The solution given doesn't take in account that the server should stay up after it has done its duty. Then, the server will not be able to serve more than one client at a time. This server is offering a one time service, which is pointless. To overcome this issue you should put everything in a while loop and bind every new server process into a new thread (I let you do that, its quite a joy).
The server doesn't take in account the whole size of the data an it could possibly run into an out of memory error if the data is too heavy. You should find a way to avoid this problem in a real implementation.
Both program should catch the exception and log it somewhere so you could be aware of any errors.
Writing a server is not so simple. You should normally write some kind of protocol with headers and other stuff like that. To avoid that, use objects like ObjectOutputStream and ObjectInputStream but it has some limitation like constraining your server in the Java world.
CLIENT
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.Socket;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
public class Client {
public void send(File file)
{
Socket sc = null;
try
{
byte[] bytearray = new byte[4096];
sc = new Socket("localhost", 4444);
// 1. Read the file, send its content, close it.
int count;
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
OutputStream os = sc.getOutputStream();
while((count = bis.read(bytearray))>0)
{
os.write(bytearray);
}
fis.close();
sc.shutdownOutput();
// 2. Delete old file, receive data, write it to new File.
InputStream is = sc.getInputStream();
bytearray = new byte[4096];
// Eventually do what you want with the file: new one, append, etc.
file.delete();
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
count = 0;
while((count = is.read(bytearray)) > 0)
{
bos.write(bytearray, 0, count);
}
fos.close();
bos.close();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (sc != null)
{
try
{
sc.close();
} catch (IOException e) {}
}
}
}
}
SERVER
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server
{
Server()
{
Socket s = null;
byte[] bytearray = new byte[4096];
try (ServerSocket ss = new ServerSocket(4444))
{
s = ss.accept();
InputStream is = s.getInputStream();
// 1. Recieve data and put it to UpperCase.
String data = "";
int count;
while((count = is.read(bytearray)) > 0)
{
data += new String(bytearray, 0, count);
}
data = data.toUpperCase();
System.out.println(data);
// 2. Send back data.
OutputStream os = s.getOutputStream();
os.write(data.getBytes());
os.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
TEST PROGRAM
This one should help you to test your both programs in the same project in an IDE.
import java.io.File;
public class Test
{
public static void main(String[] args)
{
Client c = new Client();
(new Thread()
{
public void run()
{
Server s = new Server();
}
}).start();
c.send(new File("test.txt"));
}
}
What is wrong here is two simple things.
The server is reading until end of stream, on a socket that must be used for the reply. The client therefore cannot close it after sending the request to provide the EOS, so it must shutdown the socket for output after sending the request.
Your copy loops are wrong. The general form is:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
You are ignoring the read count when writing, so you will write junk at end of stream, or any other time that read() doesn't fill buffer, which can be any time at all.

outputstream does not write the data as expected

My server looks like this:
package marshexample;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.net.ServerSocket;
import java.net.Socket;
public class marshServer {
private ServerSocket ses;
private Reader br;
private OutputStream os;
public marshServer() {
StringBuilder sb = new StringBuilder();
try {
ses = new ServerSocket(7824);
Socket s = ses.accept();
br = new InputStreamReader(s.getInputStream());
char[] request = new char[6];
int count = br.read(request);
while (!sb.toString().contains("project")) {
sb.append(new String(request, 0, count));
count = br.read(request);
System.out.println(sb.toString());
}
System.out.println(sb);
os = s.getOutputStream();
os.write("string from server".getBytes());
os.write("empty line".getBytes());
os.flush();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(sb);
}}
The issue is I have to add the string os.write("empty line".getBytes()); in order to make it work correctly. Without this string the massage is not fully sent to the client. (The same situation is with client). So why flush method does not solve this problem? Thank you for any ideas!

No value is writtern in my tcp client/server program

In my TCP socket program I have to send data from client to server. In server side I have to read the streams and write it in file. But File is created and nothing is written inside.
Client side coding to send file:
try
{
Socket ss = new Socket("localhost", 5010);
BufferedOutputStream put = new BufferedOutputStream(ss.getOutputStream());
BufferedReader st = new BufferedReader(new InputStreamReader(ss.getInputStream()));
File f = new File("e://read.txt");
FileInputStream fis = new FileInputStream(f);
byte buf[] = new byte[1024];
int read;
while((read = fis.read(buf, 0, 1024)) != -1)
{
put.write(buf,0,read);
put.flush();
}
//d.close();
System.out.println("File transfered");
ss.close();
}
catch(Exception e)
{
System.out.println(e);
}
Server to read the inputstream and write it in a file:
try
{
ServerSocket ss = new ServerSocket(5010);
Socket s = ss.accept();
BufferedReader get = new BufferedReader(new InputStreamReader(s.getInputStream()));
FileWriter writedata = new FileWriter("c://write.txt");
BufferedWriter bw = new BufferedWriter(writedata);
String line=bw.toString();
while ((line = get.readLine()) != null) {
bw.write(line + "\n");
}
}
catch(Exception e)
{
System.out.println(e);
}
What is the problem?
You forgot bw.close and bw.flush....below is the code that works...
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class TestServer
{
public static void main(String[] args)
{
try
{
ServerSocket ss=new ServerSocket(5010);
Socket s=ss.accept();
BufferedReader get= new BufferedReader(new InputStreamReader(s.getInputStream()));
FileWriter writedata=new FileWriter("c://Test//testoutput.txt");
BufferedWriter bw=new BufferedWriter(writedata);
String line=bw.toString();
while ((line = get.readLine()) != null) {
bw.write(line + "\n");
}
bw.flush();
bw.close();
}
catch(Exception e)
{
System.out.println(e);
}
}
}
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.net.Socket;
public class TestClient
{
public static void main(String[] args)
{
try
{
Socket ss=new Socket("localhost",5010);
BufferedOutputStream put=new BufferedOutputStream(ss.getOutputStream());
BufferedReader st=new BufferedReader(new InputStreamReader(ss.getInputStream()));
File f=new File("c://Test//testinput.txt");
FileInputStream fis=new FileInputStream(f);
byte buf[]=new byte[1024];
int read;
while((read=fis.read(buf,0,1024))!=-1)
{
put.write(buf,0,read);
put.flush();
}
//d.close();
System.out.println("File transfered");
ss.close();
ss.close();
}
catch(Exception e)
{
System.out.println(e);
}
}
}
Don't use Readers and Writers unless you know that the data is text. Use InputStreams and OutputStreams, and copy them so:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
out.close();
in.close();
Use this logic in both the client and the server.
Notes:
It is counterproductive to put a flush() inside that loop.
If buffer is greater than 4096, which it should be, it is pointless to use a BufferedInputStream.

Categories

Resources