I have a Java code that I have to convert to C#. The code is very basic, includes streams and sockets.
Java Code:
Socket fg = new Socket("localhost", 5400);
BufferedReader in = new BufferedReader(new FileReader("reg_flight.csv"));
PrintWriter out = new PrintWriter(fg.getOutputStream());
String line;
while((line=in.readLine())!=null) {
out.println(line);
out.flush();
Thread.sleep(100);
}
out.close();
in.close();
fg.close();
I was able of course to convert the first line, but I'm having trouble finding in Google a way to output line by line via Sockets. Specifically: PrintWriter out = new PrintWriter(fg.getOutputStream());.
My C# start:
TcpClient s = new TcpClient("localhost", 5400);
NetworkStream stream = s.GetStream();
StreamReader input = new StreamReader("reg_flight.csv");
StreamWriter output = new StreamWriter(stream);
String line;
while ((line = input.ReadLine())!= null) {
Console.WriteLine(line);
output.Write(line);
output.Flush();
System.Threading.Thread.Sleep(100);
}
For some reason, this is not working (the server doesn't receive the data correctly). I've printed the line inside the while loop and the reading seems correct. What could be the reason?
Thanks
Related
So I want to read from socket , but it doesn't gives me anything , I am newbie to java networking so please help me , it doesn't gives me any errors but doesn't gives me any output from client socket too... here is a source code:
ServerSocket server = new ServerSocket(4444);
Socket client = server.accept();
PrintWriter out = new PrintWriter(client.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String inputline = in.readLine();
while(inputline != null)
{
System.out.println("recieved "+inputline);
}
out.close();
in.close();
server.close();
client.close();
You call readLine() exactly once. If it's not null on the first iteration, you've got an infinite loop (because it will forever be non-null). Be sure to update it.
I am using following code
OutputStream out = socket.getOutputStream();
PrintWriter output = new PrintWriter(out);
#SuppressWarnings("unused")
byte[] b = message.getBytes("US-ASCII");
String convertedString = Normalizer.normalize(message, Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "");
Log.d("ASCII", convertedString);
output.println(convertedString);
Log.e("TCP Message sent", convertedString);
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//read line(s)
String st = input.readLine();
Log.e("TCP Message received", st);
But I am stuck at String st = input.readLine(); It just hangs there and never proceed to next line. Is this correct way of sending message using TCLP And then get response?
You are getting stuck at readLine() because the connection is still open - android is still waiting for more data to come in, and so can't move on.
This is what I did, but whether this is viable may depend on the protocol you are adhering to.
StringBuilder builder = new StringBuilder();
String line;
while ((line = input.readLine()) != ""){
builder.append(line);
}
Log.i("data", builder.toString());
What you need is flushing your output stream after sending message by:
output.flush();
or use auto flush by passing true while creating Output Stream like this:
PrintWriter output = new PrintWriter(out, true);
Hope this helps
I have to write server application that request questions from client and receives an answer. This is my client code:
clientSocket = new Socket("localhost", 1234);
System.err.println("Client started");
//get questions
ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
Question q = (Question)in.readObject();
//send answer
PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
out.print("a1");
out.flush();
and server code:
//sending questions
ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
List<Question> quest = Questions.getInstance().getQuestions();
out.writeObject(quest.get(0));
out.flush();
//get answer
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String temp = null;
while ((temp = in.readLine()) == null) {}
String answer = temp;
Questions successfully sent and later received by client, but server never get answer (infinite loop while reading temp variable). What is the problem?
Your calling out.print("a1"); on the client, but reading a line on the server using in.readLine(). Shouldn't you be writing out using println() on the client, else the server never gets to the end of the line? – CodeChimp Nov 21 at 21:07
Thanks for CodeChimp
When receiving data using readLine(), even though I put a "\n" at the end of the message
using the .flush when sending the message, the while loop that reads my message still blocks.
Only when closing the socket connection, it leaves the loop.
Here's the client code :
bos = new BufferedOutputStream(socket.
getOutputStream());
bis = new BufferedInputStream(socket.
getInputStream());
osw = new OutputStreamWriter(bos, "UTF-8");
osw.write(REG_CMD + "\n");
osw.flush();
isr = new InputStreamReader(bis, "UTF-8");
BufferedReader br = new BufferedReader(isr);
String response = "";
String line;
while((line = br.readLine()) != null){
response += line;
}
and the server's code:
BufferedInputStream is;
BufferedOutputStream os;
is = new BufferedInputStream(connection.getInputStream());
os = new BufferedOutputStream(connection.getOutputStream());
isr = new InputStreamReader(is);
String query= "";
String line;
while((line = br.readLine()) != null){
query+= line;
}
String response = executeMyQuery(query);
osw = new OutputStreamWriter(os, "UTF-8");
osw.write(returnCode + "\n");
osw.flush();
My code blocks at the server while loop.
Thanks.
The BufferedReader will keep on reading the input until it reaches the end (end of file or stream or source etc). In this case, the 'end' is the closing of the socket. So as long as the Socket connection is open, your loop will run, and the BufferedReader will just wait for more input, looping each time a '\n' is reached.
I tried a lot of solutions but the only one not blocking the execution was the following:
BufferedReader inStream = new BufferedReader(new InputStreamReader(yourInputStream));
String line;
while(inStream.ready() && (line = inStream.readLine()) != null) {
System.out.println(line);
}
The inStream.ready() returns false if the next readLine() call will block the execution.
This is because of the condition in the while-loop: while((line = br.readLine()) != null)
you read a line on every iteration and leve the loop if readLine returns null.
readLine returns only null, if eof is reached (= socked is closed) and returns a String if a '\n' is read.
if you want to exit the loop on readLine, you can omit the whole while-loop und just do:
line = br.readLine()
This happens because the InputStream is not ready to be red, so it blocks on in.readLine() .
Please try this :
boolean exitCondition= false;
while(!exitCondition){
if(in.ready()){
if((line=in.readLine())!=null){
// do whatever you like with the line
}
}
}
Of course you have to control the exitCondition .
An other option can be the use of nio package, which allows asynchronised (not blocking) reading but it depend on your need.
It'd be better avoid using readline(). This method is dangerous for network communications because some servers don't return LF/CR symbols and your code will be stuck. When you read from a file it isn't critical because you will reach end of the file anyway and stream will be closed.
public String readResponse(InputStream inStreamFromServer, int timeout) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(inStreamFromServer, Charsets.UTF_8));
char[] buffer = new char[8092];
boolean timeoutNotExceeded;
StringBuilder result = new StringBuilder();
final long startTime = System.nanoTime();
while ((timeoutNotExceeded = (TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) < timeout))) {
if (reader.ready()) {
int charsRead = reader.read(buffer);
if (charsRead == -1) {
break;
}
result.append(buffer, 0, charsRead);
} else {
try {
Thread.sleep(timeout / 200);
} catch (InterruptedException ex) {
LOG.error("InterruptedException ex=", ex);
}
}
}
if (!timeoutNotExceeded) throw new SocketTimeoutException("Command timeout limit was exceeded: " + timeout);
return result.toString();
}
It has a timeout and you can interrupt communication if it take a lot of time
if you want to get what's in the socket without being forced to close it simply use ObjectInputStream and ObjectOutputStream ..
Example:
ObjectInputStream ois;
ObjectOutputStream oos;
ois = new ObjectInputStream(connection.getInputStream());
String dataIn = ois.readUTF(); //or dataIn = (String)ois.readObject();
oos = new ObjectOutputStream(connection.getOutputStream());
oos.writeUtf("some message"); //or use oos.writeObject("some message");
oos.flush();
.....
readline() and read() will be blocked while socket doesn't close. So you should close socket:
Socket.shutdownInput();//after reader
Socket.shutdownOutput();//after wirite
rather than Socket.close();
I'm trying to replace a Netcat command that I'm running in my terminal that will reset some data on a server. The netcat command looks like this:
echo '{"id":1, "method":"object.deleteAll", "params":["subscriber"]} ' | nc x.x.x.x 3994
I've been trying to implement it in Java since I would like to be able to call this command from an application I'm developing. I'm having issues with it though, the command is never executed on the server.
This is my java code:
try {
Socket socket = new Socket("x.x.x.x", 3994);
String string = "{\"id\":1,\"method\":\"object.deleteAll\",\"params\":[\"subscriber\"]}";
DataInputStream is = new DataInputStream(socket.getInputStream());
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
os.write(string.getBytes());
os.flush();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
is.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
The code also hangs on the while loop that should read the InputStream, I have no idea why. I've been using Wireshark to capture the packets and the data that is going out looks the same:
{"id":1,"method":"object.deleteAll","params":["subscriber"]}
Perhaps the rest of the packets are not shaped in the same way but I really can't understand why that would be. Perhaps I am writing the string in a faulty way to the OutputStream? I have no idea :(
Note that I posted a question similar to this yesterday when I didn't properly understand the problem:
Can't post JSON to server with HTTP Client in Java
EDIT:
These are the possible results I get from running the nc command, I would expect to get the same messages to the InputStream if the OutputStream sends correct data in a correct way:
Wrong arguments:
{"id":1,"error":{"code":-32602,"message":"Invalid entity type: subscribe"}}
Ok, successful:
{"id":1,"result":100}
Nothing to delete:
{"id":1,"result":0}
Wow, I really had no idea. I experimented with some different Writers like "buffered writer" and "print writer" and it seems the PrintWriter was the solution. Although I couldn't use the PrintWriter.write() nor the PrintWriter.print() methods. I had to use PrintWriter.println().
If someone has the answer to why other writers wouldn't work and explain how they would impact the data sent to the server I will gladly accept that as the solution.
try {
Socket socket = new Socket(InetAddress.getByName("x.x.x.x"), 3994);
String string = "{\"id\":1,\"method\":\"object.deleteAll\",\"params\":[\"subscriber\"]}";
DataInputStream is = new DataInputStream(socket.getInputStream());
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
PrintWriter pw = new PrintWriter(os);
pw.println(string);
pw.flush();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
is.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
I think the server is expecting newline at the end of the message. Try to use your original code with write() and add \n at the end to confirm this.