I want to send some data using TCP Socket;
keyboard input is ok.
redirecting binary files fine too.
but
when I redirect /dev/urandom to stdin (java prog < /dev/urandom) nothing happens, no errors, no data send.
public class P1{
static DataInputStream dis = new DataInputStream(System.in);
int port = 12345;
String host = "127.0.0.1";
Socket p1Socket;
DataOutputStream out;
byte data;
void run() {
try{
p1Socket = new Socket( host, port );
out = new DataOutputStream(p1Socket.getOutputStream());
while (dis.available() >0){
data = dis.readByte();
out.write ( data );
}
out.flush();
out.close();
p1Socket.close();
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String args[]) throws IOException {
P1 p1 = new P1();
while (dis.available() <=0);
p1.run();
}
}
Don't use the available method, it only tells you if something can be read without blocking, which is pretty useless. Use an infinite loop instead.
while (true) {
data = dis.readByte();
out.write(data);
}
End-of-file is signaled with EOFException. Make sure that you close the file when exceptions are thrown.
Related
I recently tried to create a copy/paste app with Java using this answer and I didn't change much other than directories of the file. I created a regular text file with "test" written inside it. When I run the app it copies the file, but gives me an error about utf-8 encoding in success_test.txt and I'm not sure how to fix this or what's causing the problem. I'm running this on Ubuntu 18.04 in Intellij Ultimate 2019.2
here's the server and the client is pretty much the same as in the answer
Server:
public class Server extends Thread {
public static final int PORT = 3332;
public static final int BUFFER_SIZE = 626;
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(PORT);
while (true) {
Socket s = serverSocket.accept();
saveFile(s);
}
} catch (Exception e) {
}
}
private void saveFile(Socket socket) throws Exception {
InputStream inputStream = socket.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream("/home/user/Documents/success_test.txt");;
byte[] byteArray = new byte[1024];
System.out.println("Reading file from server...");
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
int bytesRead;
while ((bytesRead = inputStream.read(byteArray)) != -1) {
bufferedOutputStream.write(byteArray);
}
bufferedOutputStream.close();
System.out.println("Writing file complete...");
}
public static void main(String[] args) {
new Server().start();
}
}
when I try to open success_test.txt this is what I see
https://imgur.com/a/3rpvkiJ
You are reading your data into a 1024 byte long array, then writing that to a file. This means your output file is padded to 1024 bytes with \00 which is the NULL character.
You have your bytesRead variable, so you should use it to only write that many bytes:
bufferedOutputStream.write(byteArray, 0, bytesRead);
As others have mentioned, you have a logic error: you’re ignoring bytesRead in your loop. However, you can eliminate that error, and the possibility of most other errors, by using Files.copy instead of writing your own save code:
try (InputStream inputStream = socket.getInputStream()) {
Files.copy(inputStream,
Paths.get("/home/user/Documents/success_test.txt"));
}
I'm learning distributed systems basics and currently I'm trying to do a simple yet realistic messenger between one server and one client. What I do intend is that on each endpoint socket side (Server and Client) text automatically updates (like a real "messaging app"). In other words, I want that the moment I write and "send" the message, it automatically appears on recipient side. What I have now follows this schema:
I send a message (let's assume from client)
To see that message on Server's side I need to reply first (because Server's BufferedReader / Client's PrintWriter is only read after asking for the answer)
My code:
public class ClientSide {
public static void main(String [] args){
String host_name = args[0];
int port_number = Integer.parseInt(args[1]);
try {
Socket s = new Socket(host_name, port_number);
PrintWriter out =
new PrintWriter(s.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(s.getInputStream()));
BufferedReader stdIn =
new BufferedReader(
new InputStreamReader(System.in));
String answer;
while ((answer = stdIn.readLine()) != null) {
out.println(answer);
System.out.println("\nlocalhost said\n\t" + in.readLine());
}
} catch (IOException ex) {
Logger.getLogger(ClientSide.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public class ServerSide {
public static void main(String [] args){
int port_number = Integer.parseInt(args[0]);
try {
ServerSocket ss = new ServerSocket(port_number);
Socket tcp = ss.accept();
PrintWriter out =
new PrintWriter(tcp.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(tcp.getInputStream()));
BufferedReader stdIn =
new BufferedReader(
new InputStreamReader(System.in));
String answer;
while ((answer = stdIn.readLine()) != null){
out.println(answer);
System.out.println("\nClient said\n\t" + in.readLine());
}
} catch (IOException ex) {
Logger.getLogger(ServerSide.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
How can I do this? Does it involve advanced knowledge on the matter?
Thanks in advance.
The core problem is that you want to wait for two events concurrently -- either a message from the socket, or input from the user!
You want to wait on both at the same time -- you don't want to be stuck waiting for a message in the socket if the user types a message; nor to be waiting for the user message while you have a new message from the network.
To 'wait' for messages from multiple streams, you have java.nio. I believe it is the most correct way of doing it.
But if you want to keep using the BufferedReader, there is a ready() method that returns true if and only if there is a message waiting to be read.
Your code after the in and stdIn declarations would then look something like (I didn't test it!!):
while(true) {
if(stdIn.ready()) {
System.out.println("I said " + stdIn.readLine());
}
if(in.ready()) (
System.out.println("He said " + in.readLine());
}
}
A few somewhat useful random links:
Java - Reading from a buffered reader (from a socket) is pausing the thread
Is there epoll equivalent in Java?
I hope to find any help on my old annoying problem.
I have a TCP sever program with java and client program with c#
packet protocol between those two is simply consist of 4byte length & body ASCII data.
The Problem is that C# client faces FormatException which is from parsing fail on length byte. If I look into an error from client side, then client is trying to parse somewhere in the body which is not length header.
But apparently, Server does not send broken packet.
meanwhile, at the server, I could find an Broken pipe error whenever this kind of problem happens.
Unfortunately this error does not always happen and was not able to recreate the problem situation. it makes me difficult to find exact cause of this problem
Please see below codes for server side
public class SimplifiedServer {
private Map<InetAddress, DataOutputStream> outMap;
private Map<InetAddress,DataInputStream> inMap;
protected void onAcceptNewClient(Socket client) {
DataOutputStream out = null;
DataInputStream in = null;
try {
out = new DataOutputStream(client.getOutputStream());
in = new DataInputStream(client.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
outMap.put(client.getInetAddress(), out);
inMap.put(client.getInetAddress(), in);
}
public void writeToAll(String packet) {
outMap.forEach((key, out) -> {
try {
byte[] body = packet.getBytes("UTF-8");
int len = body.length;
if (len > 9999) {
throw new IllegalArgumentException("packet length is longer than 10000, this try will be neglected");
}
String lenStr = String.format("%04d%s", len, packet);
byte[] obuf = lenStr.getBytes();
synchronized (out) {
out.write(obuf);
out.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
});
}
public void listenClient(Socket client) {
try {
DataOutputStream out = outMap.get(client.getInetAddress());
DataInputStream in = inMap.get(client.getInetAddress());
while (true) {
byte[] received = SimplePacketHandler.receiveLpControlerData(in);
byte[] lenBytes = new byte[4];
for( int i = 0 ; i < 4 ; i ++){
lenBytes[i] = in.readByte();
}
String lenString = new String(lenBytes);
int length = Integer.parseInt(lenString);
byte[] data = new byte[length];
for ( int i = 0 ; i < length ; i ++){
data[i] = in.readByte();
}
if ( data == null ){
System.out.println("NetWork error, closing socket :" + client.getInetAddress());
in.close();
out.close();
outMap.remove(client.getInetAddress());
inMap.remove(client.getInetAddress());
return;
}
doSomethingWithData(out, data);
}
} catch (NumberFormatException e) {
e.printStackTrace();
} catch ( Exception e ) {
e.printStackTrace();
} finally {
try {
System.out.println(client.getRemoteSocketAddress().toString() + " closing !!! ");
// remove stream handler from map
outMap.remove(client.getInetAddress());
inMap.remove(client.getInetAddress());
//close socket.
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
And here is client side code
public class ClientSide
{
public TcpClient client;
public String ip;
public int port;
public NetworkStream ns;
public BinaryWriter writer;
public BinaryReader reader;
public Boolean isConnected = false;
public System.Timers.Timer t;
public String lastPacketSucceeded = String.Empty;
public ClientSide(String ip, int port)
{
this.ip = ip;
this.port = port;
client = new TcpClient();
}
public bool connect()
{
try
{
client.Connect(ip, port);
}
catch (SocketException e)
{
Console.WriteLine(e.ToString());
return false;
}
Console.WriteLine("Connection Established");
reader = new BinaryReader(client.GetStream());
writer = new BinaryWriter(client.GetStream());
isConnected = true;
return true;
}
public void startListen()
{
Thread t = new Thread(new ThreadStart(listen));
t.Start();
}
public void listen()
{
byte[] buffer = new byte[4];
while (true)
{
try
{
reader.Read(buffer, 0, 4);
String len = Encoding.UTF8.GetString(buffer);
int length = Int32.Parse(len);
byte[] bodyBuf = new byte[length];
reader.Read(bodyBuf, 0, length);
String body = Encoding.UTF8.GetString(bodyBuf);
doSomethingWithBody(body);
}
catch (FormatException e)
{
Console.WriteLine(e.Message);
}
}
}
public void writeToServer(String bodyStr)
{
byte[] body = Encoding.UTF8.GetBytes(bodyStr);
int len = body.Length;
if (len > 10000)
{
Console.WriteLine("Send Abort:" + bodyStr);
}
len = len + 10000;
String lenStr = Convert.ToString(len);
lenStr = lenStr.Substring(1);
byte[] lengthHeader = Encoding.UTF8.GetBytes(lenStr);
String fullPacket = lenStr + bodyStr;
byte[] full = Encoding.UTF8.GetBytes(fullPacket);
try
{
writer.Write(full);
}
catch (Exception)
{
reader.Close();
writer.Close();
client.Close();
reader = null;
writer = null;
client = null;
Console.WriteLine("Send Fail" + fullPacket);
}
Console.WriteLine("Send complete " + fullPacket);
}
}
Considering it is impossible to recreate problem, I would guess this problem is from multithread issue. but I could not find any further clue to fix this problem.
Please let me know if you guys need any more information to solve this out.
Any help will be great appreciated, thanks in advance.
A broken pipe exception is caused by closing the connection on the other side. Most likely the C# client has a bug, causing the format exception which causes it to close the connection and therefore the broken pipe on the server side. See what is the meaning of Broken pipe Exception?.
Check the return value of this read:
byte[] bodyBuf = new byte[length];
reader.Read(bodyBuf, 0, length);
According to Microsoft documentation for BinaryReader.Read https://msdn.microsoft.com/en-us/library/ms143295%28v=vs.110%29.aspx
[The return value is ] The number of bytes read into buffer. This might be less than the number of bytes requested if that many bytes are not available, or it might be zero if the end of the stream is reached.
If it reads less than the length bytes then next time it will be parsing the length using data somewhere in the middle of the last message.
These broke pipe exceptions happen when the client (browser) has closed the connection, but the server (your tag) continues to try to write to the stream.
This usually happens when someone clicks Back, Stop, etc. in the browser and it disconnects from the server before the request is finished. Sometimes, it can happen because, for example, the Content-Length header is incorrect (and the browser takes its value as true).
Usually, this is a non-event, and nothing to worry about. But if you are seeing them in your dev environment when you know you have not interrupted your browser, you might dig a bit more to find out why.
WLS server will try to filter these exceptions from the web container out of the log, since it is due to client (browser) action and we can't do anything about it. But the server doesn't catch all of them.
refer from :: https://community.oracle.com/thread/806884
My program is basically:
Client sends a String to Server,
Based on this String, Server is creating an ArrayList,
ArrayList is sent back to the Client.
What is failing here is:
After Client sends a String, the Server receives it and doesn't do anything else. In this time Client keeps on working and gets a NullPointer.
Client side:
public static ArrayList<String> sendStringToServer(String report) {
Socket socket;
ArrayList<String> fieldsList = new ArrayList<String>();
try {
socket = new Socket("localhost", 2345);
OutputStream os = socket.getOutputStream();
PrintStream ps = new PrintStream(os, true);
ps.println(report);
ps.flush();
//Here the debugger should stop and wait for server to create a List
//at this point there is no answer, code breaks
ObjectInputStream objectInput = new ObjectInputStream(socket.getInputStream());
Object object = objectInput.readObject();
fieldsList = (ArrayList<String>) object;
socket.close();
return fieldsList;
} catch (IOException e1) {
e1.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
Server side:
public class Server {
private ServerSocket serverSocket;
private Socket clientSocket;
private String telegram;
private StringBuilder telegramSB;
public static void main(String[] args) throws IOException, JRException {
new Server();
}
public Server() {
try {
serverSocket = new ServerSocket(2345);
while (true) {
clientSocket = serverSocket.accept();
InputStream is = clientSocket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
try {
//debugger goes to here and then stops
telegram = br.readLine();
int counter = 0;
boolean startSeq = false;
for (char ch : telegram.toCharArray()) {
if (counter == 0 && ch == '/') {
startSeq = true;
}
if (startSeq == true) {
telegramSB = new StringBuilder();
telegramSB.append(ch);
}
if (ch == '\n') {
if (telegram.length() < 255) {
sendListWithFields();
} else {
new Launcher(telegram).run();
}
}
counter++;
}
} catch (JRException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
System.out.println(e);
}
}
My guess here would be that the BufferedReader is waiting to fill its buffer and you haven't sent enough data for it to do that and return so its waiting for more data to come through that never does (because your clients stops writing and starts to read). You could test this theory temporarily by dumping a load more data into the OutputStream on the client and flushing it.
If the above is the case then you probably want to not use BufferedReader but you have other issues here which also mean you probably want to avoid using PrintStream and BufferedReader for communication and serialisation anyway. For example the default character encoding on two different machines and JVMs could be different. When you create your PrintStream and InputStreamReader you don't specify a character encoding so they could end up being mismatched and the string that you write (including the newline character) could end up being understood completely differently by the remote side, this could also be a reason why its blocking (the client side encodes the newline character in one way but the server is expecting it to be encoded a completely different way), though less likely I think .
If you don't have to use PrintStream then I would suggest instead using DataOutputStream / DataInputStream:
//Client
BufferedOutputStream bufout = new BufferedOutputStream(socket.getOutputStream());
DataOutputStream dout = new DataOutputStream(bufout);
dout.writeUTF(report);
dout.flush();
//Server
BufferedInputStream bufin = new BufferedInputStream(socket.getInputStream());
DataInputStream din = new DataInputStream(bufin);
String report = din.readUTF();
You still get buffering from the BufferedIn/OutputStreams so it will be performant but the DataIn/OutputStreams will manage termination of variable length objects for you - they will send a length prefixing the string to tell the other side exactly how many bytes to read, so you don't need to use a special character to terminate the string you wrote, and this also means it doesn't matter what the content of your String is. In your example above even if it was working if your String had a newline character in it the server would read up until that first newline character, not to the end of the string you sent and that would put them out of sync for the next send/receive along that stream.
Using write/readUTF also specifies an encoding (UTF-8) so there is no mismatch there either.
I'm beginning client-server programming. what I'm trying to do is basically a Echo server but instead of return the same thing as the client inserted, I want the server to return 2*(The number I insert).
I have the following server:
public class Server {
public static void main(String args[]) throws Exception {
ServerSocket server = new ServerSocket(6789);
while(true) {
try {
Socket aux = server.accept();
DataInputStream dis = new DataInputStream(aux.getInputStream());
DataOutputStream dos = new DataOutputStream(aux.getOutputStream());
int total = 0;
while(dis != null) {
int res = dis.read();
total = 2*(res);
dos.writeInt(total);
}
}
catch (EOFException e) {
out.println("The client exit!");
continue;
}
}
}
}
And the following client:
public class Client {
public static void main(String args[]) throws Exception {
Socket client = new Socket("localhost", 6789);
DataInputStream dis = new DataInputStream(client.getInputStream());
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
BufferedReader input = new BufferedReader(new InputStreamReader(in));
while(true) {
int fromClient = input.read();
dos.writeInt(fromClient);
client.shutdownOutput(); //to show to the server the end of file
int fromServer = dis.readInt();
out.println(fromServer);
}
}
}
Can somebody help please?
I got the following error on the server side:
Exception in thread "main" java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)
at java.net.SocketOutputStream.write(SocketOutputStream.java:132)
at java.io.DataOutputStream.writeInt(DataOutputStream.java:197)
at Server.main(Exercicio3.java:21)
And on the client side when I insert a value (in this case '1'):
1
0
Exception in thread "main" java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)
at java.net.SocketOutputStream.write(SocketOutputStream.java:132)
at java.io.DataOutputStream.writeInt(DataOutputStream.java:197)
at Client.main(Exercicio4.java:25)
Thanks
Without knowing what your problem is, one issue I can see is:
int res = dis.read();
res is the next byte in the input (see the doc) and is not an integer as entered by your user. It will be the first byte of the character code of whatever your user has entered.
There is an infinite loop before you send the result back to the
client.
while(dis != null) {
int res = dis.read();
total = 2*(res);
}
dos.writeInt(total);
Move that last line inside the brackets and it should work.
while(dis != null) {
int res = dis.read();
total = 2*(res);
dos.writeInt(total);
}
Additionally, calling client.shutdownOutput() is not necessary. You
will just get exceptions when you try to write to it the next time:
Disables the output stream for this socket. For a TCP socket, any previously written data will be sent followed by TCP's normal
connection termination sequence. If you write to a socket output
stream after invoking shutdownOutput() on the socket, the stream will
throw an IOException. `
And then there is also the issue mentioned previously:
int res = dis.read();
should be
int res = dis.readInt();
You have a similar issue reading the user's input in the client.
Use this instead:
int fromClient = Integer.parseInt(input.readLine());