Java socket BufferedReader read not reading - java

Im trying to make a client/server socket connection via BufferedReader and Buffered Writer, but reader not reading anything it is just hanged, where client send and flush properly.
Server does not throw any exception as if client not sending anything to server.
My head is going go explode...
Im using same for both client and server:
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
Here is the code of server:
//inside of try catch
while(true){
while(!in.ready())// just to debug
System.out.println("READY: " + in.ready()); //just to debug
System.out.println("READY: OK"); //just to debug
msg = receive().toString(); //hangs here...
System.out.println("KEYIS: " + msg);
///some stuff to do ....
public StringBuilder receive() throws IOException {
StringBuilder str = new StringBuilder();
int tmp;
while(true){
tmp = in.read();
if(tmp == 0)
break;
else if(tmp == -1)
throw new IOException();
str.append((char)tmp);
}
return str;
}
Client code: not hanging here
//inside of try catch
send(KEY); //sended properly, no exception
while(true){
send(KEY); // sended properly, no exception
System.out.println("sent");
//System.out.println(receive().toString());
}
public void send(String str) throws IOException{
out.write(str + "\n"); //
//out.newLine(); //tried too, not helped
out.flush(); //push message to server
}

Well server waits for if(tmp == 0) which is 0 is a nil, and the client never sends it.
I think You are waiting about \n which it's not 0, it's 10(line feed).
Just wondered why don't you use DataOutputStream#writeUTF() and DataInputStream#readUTF()?

You're writing lines but you have a pretty pointless and elaborate and very buggy input method which doesn't actually read lines, and which throws the wrong exception at end of stream.
Try BufferedReader.readLine(), not forgetting to test for null.

StringBuffer sb = new StringBuffer();
int i;
while ((i = bi.read()) != -1) {
char c = (char) i;
sb.append(c);
}
return sb.toString();

Solved the problem... So stupid mistake... I just forgot to add a \0 to determine the end of message, so recieve method was waiting as if more data coming...

Related

Java: cannot read from socket, thread gets stuck on readLine()

Here is my code for the server side:
#Override
public void run(){
String message;
String command;
String[] arguments;
try{
BufferedReader inStream = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
while(online){
message = inStream.readLine();
if(message == null)
continue;
if(message.charAt(0) == '/'){
int endOfCommandIndex = message.indexOf(' ');
command = message.substring(1, endOfCommandIndex);
arguments = message.substring(endOfCommandIndex + 1).split(" ");
if(command.equals("login")){
setUserName(arguments[0]);
setName(arguments[0]);
sendMessage(this, "Connected");
}
//....
}
}
}
As mentioned in the title, the thread gets stuck reading from the InputStream of the Socket (I checked with JDB and it's not a conditional waiting because it appears to be still "running").
I tried to write a line to the socket but it doesn't change its state at all. I'm trying to build a chat-like local application and I'm quite new to socket and streams. Thanks in advance.
For the client side:
String msg;
try{
while(!((msg = stdIn.readLine()).equals("/quit")))
toServer.println(msg);
}
catch(IOException e){
e.printStackTrace();
}
In case someone wants review my entire code, it is here hosted on github
It looks like the message is never flushed after being written into the socket stream.
Try either call:
toServer.flush();
after println, or enable auto flushing when constructing toServer:
toServer = new PrintWriter(socket.getOutputStream(), true);

How to properly stream data from a socket with Java

I am attempting stream data over a socket with Java in an attempt to write a Kafka producer. I've written a class to pull the data in but I'm not getting the results I'd expect. I've got it set up so the data is being streamed from a Linux box. The source of the data is a csv file that I'm using the nc utility to stream. The class is running on a Windows 10 machine from Eclipse. When I run the class I see two weird things.
The column headers don't get transmitted.
I can only run the class once. If I want to run it again, I have to stop nc and restart it.
Below is my code. Am I missing anything? At this point I'm just trying to connect to the socket and pull the data over.
I run nc with the following command:
$ nc -kl 9999 < uber_data.csv
Below is my class
import java.net.*;
import java.io.*;
public class Client
{
static String userInput;
public static void main(String [] args)
{
try
{
InetAddress serverAddress = InetAddress.getByName("servername");
Socket socket = new Socket(serverAddress, 9999);
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while ((userInput = input.readLine()) != null) {
System.out.println(input.readLine());
}
input.close();
socket.close();
}
catch(UnknownHostException e1)
{
System.out.println("Unknown host exception " + e1.toString());
}
catch(IOException e2)
{
System.out.println("IOException " + e2.toString());
}
catch(IllegalArgumentException e3)
{
System.out.println("Illegal Argument Exception " + e3.toString());
}
catch(Exception e4)
{
System.out.println("Other exceptions " + e4.toString());
}
}
}
You're throwing away every odd-numbered line. It should be:
while ((userInput = input.readLine()) != null) {
System.out.println(userInput);
}
Secondly, you aren't closing the socket. Use a try-with-resources:
try
{
InetAddress serverAddress = InetAddress.getByName("servername");
try (
Socket socket = new Socket(serverAddress, 9999);
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
) {
while ((userInput = input.readLine()) != null) {
System.out.println(input.readLine());
}
}
}
catch (...)
First, each call readLine() tries to read line from input stream.
In userInput = input.readLine() you read header, but println(input.readLine()) read body and print in console.
while ((userInput = input.readLine()) != null) {
System.out.println(userInput); //instead input.readLine()
}
Second, I didn't use nc, but I think problem will solve if you will close socket (and reader) in finally statement.
I hope it would be helpful.
For the first question: you were trying to print userInput string. But it's printing the result of another readline() call.
For the second: after the file has been transferred, you have to stop and restart nc; no matter what you do from your side. It's from nc side.
See the nc documentation.

When to register OP_WRITE

I use NIO with reactor pattern to connect a server to a client. My codes are as follows:
Server side codes, in the block of if(selectionKey.isWritable){} :
public void isWritable(SelectionKey selectionKey) throws Exception {
SocketChannel socketChannel =
(SocketChannel) selectionKey.channel();
Integer myInteger = (Integer) selectionKey.attachment();
if (myInteger == null){
int myJob = jobFacade.isAnyJob(socketChannel, 100 /*deadline*/);
if (myJob > 0){
ByteBuffer inputBuffer = ByteBuffer.wrap("available\n".getBytes("UTF-8"));
socketChannel.write(inputBuffer);
myInteger = myJob;
socketChannel.register(
selector, SelectionKey.OP_WRITE, myInteger);
}else if (myJob == -1){
ByteBuffer inputBuffer = ByteBuffer.wrap("unavailable\n".getBytes("UTF-8"));
socketChannel.write(inputBuffer);
socketChannel.close();
UnsupportedOperationException un = new UnsupportedOperationException();
throw un;
}else if (myJob == -2){
ByteBuffer inputBuffer = ByteBuffer.wrap("pending\n".getBytes("UTF-8"));
inputBuffer.flip();
socketChannel.write(inputBuffer);
myInteger = null;
socketChannel.register(
selector, SelectionKey.OP_WRITE, myInteger);
}
// is there any new job to do?
}else{
int myInt = myInteger.intValue();
if ( myInt > 0 ){
long startRange = jobFacade.findByID(myInt);
sendTextFile(startRange, Integer.parseInt(properties.getProperty("workUnit")),
properties.getProperty("textPath"), socketChannel);
myInteger = -3;
socketChannel.register(
selector, SelectionKey.OP_WRITE, myInteger);
}else if (myInt == -3){
sendAlgorithmFile(socketChannel, properties.getProperty("algorithmPath"));
myInteger = -4;
socketChannel.register(
selector, SelectionKey.OP_WRITE, myInteger);
// send algorithm file
}else if (myInt == -4){
int isOK = jobFacade.isAccepted(socketChannel.socket().getInetAddress().toString(),
Long.parseLong(properties.getProperty("deadline")));
if(isOK == -1){
ByteBuffer inputBuffer = ByteBuffer.wrap("notaccepted\n".getBytes("UTF-8"));
socketChannel.write(inputBuffer);
myInteger = null;
socketChannel.register(
selector, SelectionKey.OP_WRITE, myInteger);
}else {
ByteBuffer inputBuffer = ByteBuffer.wrap("accepted\n".getBytes("UTF-8"));
socketChannel.write(inputBuffer);
myInteger = isOK;
socketChannel.register(
selector, SelectionKey.OP_READ, myInteger);
}
// send "accepted" or "not accepted"
}
}
}
It is no need to know what my methods in each block do except that these methods generate a number with this order at first. 1)myInteger=null, 2) myInteger > 0, 3) myInteger = -3, 4) myInteger = -4
In this order, OP-WRITE will register consecutively for four times. And this part is so important. So lets see my Client side code and then I will tell you my problem:
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
sentence = inFromServer.readLine();
System.out.println("Response from Server : " + sentence);
if (sentence.equals("available")){
BufferedReader inFromServer1 = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while ((sentence = inFromServer1.readLine()) != null) {
myJob = myJob + sentence ;
}
inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String acception = inFromServer.readLine();
if (acception.equals("accepted")){
File file = new File("account.json");
byte[] bytes = new byte[2048];
InputStream inputStream = new FileInputStream(file);
OutputStream outputStream = clientSocket.getOutputStream();
int count;
try {
while ((count = inputStream.read(bytes)) > 0){
outputStream.write(bytes, 0, count);
}
outputStream.close();
inputStream.close();
}catch (IOException io){}
continue;
}else if (acception.equals("notaccepted")){
continue;
}
Now, my problem is that when I run my server and then my client, my server will run without waiting for my client to get input stream. First, the client get "available" but when the second getInputStream will be reached in client, the server paced all the phase of OP-WRITE registering and wait for client to get streams of data (As I defined in my code).
Actually, my server do its job well. It will pass all the stages in required order. But the problem is that sending and receiving data is not synchronous.
I do not know what my problem is. But I guess when I register OP-WRITE consecutively, it means that my server did not send all bytes of data, so just the first getInputStream will get the data.
On the other hand, I need this order to run my program. So, Is there any Idea?
I find out my problem. There is no problem with my code. OP_WRITE can be registered any time with any order. The most important thing is to write to buffer and read from socket correctly.
Actually, when I send something for the second time to my client, I did not clear the buffer. In this case I found it, and correct it.
But when I send some characters to my client and then want to send a file, because in my client side I have a loop to get all characters, the content if the file is gotten by the same loop.
The question here is that how I can make them separate?
I will help you clarify the problem before thinking about patterns:
You have one thread/process that passes a message asking another thread/ process to act upon the message.
The receiver needs to read the message and maybe start some child threads of its own to perform that work because it can receive other requests.
It would be nice to tell the sender that an acknowledgment that the request was received.
It seems necessary that the message passing is protected. Because if another requests comes in while you are reading you could end up processing garbage.
You can configure nio to have several readers and just one writer, just read one portion of a buffer, etc. Check the how-tos, api docs. It is plenty powerful
exactly after sending a message
There is no such thing as a message in TCP. It is a byte stream. Two writes at the sender are very likely to by read by one read at the receiver. If you want messages you have to implement them yourself, with count words, terminators, STX/ETX, XML, etc.

Server Client communication fails at Outputstreams

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.

Retrieve the double of the number inserted -- Client Server Programming

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());

Categories