Java client stuck in datastream of data from nodejs server - java

My problem is that when i send data ( with socket.write()) from the nodejs server to the java client the java client is stuck in the datastream as long as there is no FIN packet( which would be send when i use socket.end() in nodejs) from the server.
My quesiton is now wether there is a way java can read it without the FIN package.
I thought there has to be a way because it works perfectly when you create a client with
the net module of NodeJS.
Server
var server = require("net").Server();
function cl(t){console.log(t)};
server.listen("5022","127.0.0.1", function(req,res){
cl("Server started...");
});
server.on("connection", function(socket){
var ip = socket.remoteAddress;
socket.setEncoding("utf8");
cl("connection --> "+ip);
socket.write("Welcome...");
socket.on("data",function(d){
var data = JSON.stringify(d);
cl("Data arrived "+data);
});
socket.on("end", function(){
cl("end");
})
socket.on("close",function(){
cl("Disconnect --> "+ip+"\n");
})
socket.on("error", function(err){
cl("ERROR "+err);
});
});
Note: So as is said, when i would add socket.end() a FIN packet would be send and the java client gets out of the datastream and returns the data. So at the moment i can send data from the server once in the entire session.
part of Client
Socket sc = new Socket(ip, port);
BufferedReader in = new BufferedReader(new
InputStreamReader(sc.getInputStream()));
DataOutputStream out = new DataOutputStream(sc.getOutputStream());
String input;
while(true)
{
while (!in.ready()) {Thread.sleep(2000);}
input = in.readLine();
System.out.println("Message : " + input);
out.writeUTF(input);
}
Note: Sending data to the server does work from this java client.

in.readLine() is doing just what it says, reading a line, which means it's looking for a newline character to know when to stop reading. So in your node code just append a \n when you .write() so that the Java code can resume. Example: socket.write("Welcome...\n");

Related

Send message from Java client to Python server using sockets and vice versa

I am trying to send receive data using a Python server and a Java client. First, Java sends a JSON in string to Python Server. After the string received, Python server will send a JSON back to the client. After the client receives the JSON from the server, it again sends a JSON in string to server. (Client sends the same message all the time) This is a recursive process.
ISSUE: After when I execute both Python server and Java, Python server receives the message sent by the Java Client and it sent back the JSON. But in the client side, the message sent by the server didnt receive.
Server.py
import socket
import threading
import json
import numpy
HEADER_INITIAL = 25
PORT = 1234
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
def handle_client(self, conn, addr):
print(f"[NEW CONNECTION] {addr} connected.")
connected = True
while connected:
msg = conn.recv(HEADER_INITIAL).decode(FORMAT)
if msg:
print("[DATA] RECEIVED"+ str(msg))
x = {
"Sentence": "This is a value"
}
y = json.dumps(x)
conn.send(y.encode(FORMAT))
conn.send("\n".encode(FORMAT));
conn.close()
Client.java
try (Socket socket = new Socket(Address, Port)) {
InputStream input = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(input);
OutputStream output = socket.getOutputStream();
PrintWriter writer = new PrintWriter(output, true);
int character;
StringBuilder data = new StringBuilder();
while(true){
Thread.sleep(4000);
String strJson = "{'message':'Hello World'}";
JSONObject jsonObj = new JSONObject(strJson);
writer.println(jsonObj.toString());
while((character = reader.read()) != -1) {
data.append((char) character);
}
System.out.println(data);
}
} catch (UnknownHostException ex) {
System.out.println("Server not found: " + ex.getMessage());
} catch (IOException ex) {
System.out.println("I/O error: " + ex.getMessage());
}
UPDATE
Here is the debug output.
I first started the server and then started client. Initially server receives the {'message':'Hello World'} value which is sent by the client and the server sends back the value of the x variable to the client. Then the server receives nothing from the client, but the client prints the value of x continuously.( System.out.println(data);) I tried to send dynamic values from the server to client, but the client prints only the value which is sent by the server in the first time.
You don't provide any debugging output so it's difficult to be 100% sure this is the entire cause. However, it seems pretty evident that this section of your client code isn't correct:
while((character = reader.read()) != -1) {
data.append((char) character);
}
System.out.println(data);
The server is holding the connection open forever (nothing ever sets connected to false). And so in the loop above, the character returned by reader.read will never be -1 because -1 is only returned at "end of stream". End of stream will only occur when the server closes its socket -- or is otherwise disconnected.
You should add a check for the newline to break out of the read loop:
if (character == '\n')
break;
or you could add it to the while condition:
while ((character = reader.read()) != -1 && character != '\n') {
...
Your code overall lacks appropriate handling of possible exceptional conditions. For example, if the client disconnects, your server will never exit its loop. It will call recv, get back an empty string (signifying "end of file" on the connection), and so will correctly bypass sending a response, but it will then simply go back and execute recv again, get an empty string again, and so forth forever.
Also, your python code makes the implicit assumption that the recv returns exactly the single string that was sent by the client, which is not guaranteed. If the client sends a 20 character string for example, it's possible that the first server recv call returns the first 10 characters, and the next call returns the rest.
(In practice, given the sleep in the client side code, that's unlikely to be a problem in this snippet of code, but one should program defensively because in a real production program, there will inevitably be a race or edge case that will do exactly this and it will cause the client and server to get out of sync and be difficult to debug.)

C# to Java UTF8 string over TCP

I'm unable to send a UTF-8 string from a C# server to a Java client due to an EOF error in the client. How do I properly configure the C# server? I assume the error lies there because this client works with the Java server shown below.
Java client's receive function does this (this also works if I receive from a Java server, shown below):
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); //The constructor initialises a field, using the socket object.
StringBuilder inputMessage = new StringBuilder();
inputMessage.append((String) dataInputStream.readUTF());
Desired C# server:
static async Task Main(string[] args)
{
TcpListener server = new TcpListener(IPAddress.Any, 34567);
server.Start();
byte[] bytes = new byte[4096];
byte[] responseBytes;
using (var client = await server.AcceptTcpClientAsync()){
using(var tcpStream = client.GetStream())
{
await tcpStream.ReadAsync(bytes, 0, bytes.Length);
var playerNumber = Encoding.UTF8.GetString(bytes);
Console.WriteLine("Player " + playerNumber + " connected."); //java client to server works.
StringBuilder outputMessage = new StringBuilder("Some output");
responseBytes = Encoding.UTF8.GetBytes(outputMessage.ToString());
await tcpStream.WriteAsync(responseBytes, 0, responseBytes.Length); //This doesn't work...
}
server.Stop();
}
}
The error:
java.io.EOFException
at java.base/java.io.DataInputStream.readFully(DataInputStream.java:201)
at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:613)
at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:568)
at Client.Connection.Receive(Connection.java:26)
at Client.Main.lambda$main$0(Main.java:30)
at com.sun.javafx.application.PlatformImpl.lambda$startup$5(PlatformImpl.java:271)
at com.sun.glass.ui.Application.invokeAndWait(Application.java:464)
at com.sun.javafx.tk.quantum.QuantumToolkit.runToolkit(QuantumToolkit.java:366)
at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$startup$10(QuantumToolkit.java:280)
at com.sun.glass.ui.Application.lambda$run$1(Application.java:153)
Interestingly, a Java server doing this works:
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
StringBuilder outputMessage = new StringBuilder("Some output");
dataOutputStream.writeUTF(outputMessage.toString());
dataOutputStream.flush();
EDIT
This is received from the working Java server. The "bytearr" contains 100 bytes that I am using for my message and 100 bytes that are 0 (they come after my message). The "chararr" correctly sees the first 100 bytes as something meaningful and the last 200 bytes as '\u0000':
This is received form the non-working C# server. It seems to start two bytes in compared to the correct version and also it's "chararr" contains only thousands of '\u0000':
DataInputStream's readUTF reads a special data format, it is not a general purpose method for reading a sequence of UTF-8 bytes. Most notably, it expects an initial sequence of bytes specifying the length of the stream.
I found the answer here. Changing the way the Java client reads to this, works:
byte[] buff = dataInputStream.readAllBytes();
String str = new String(buff, "UTF-8");

Sending data from iOS server to java client

I am new to iOS development. What I want to achieve is create server on iPhone app and receive data in Java client app.
I have successfully created iPhone side server using this library
On java client side, I am receiving data from local host using same port number
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
System.out.println("Message received from the server : " +message);
I have made connection successfully.
I am tried sending number and text using this code
func sendObject(object: Any, type: UInt32, completion: ((_ success: Bool) -> Void)? = nil) {
let data = Data.toData(object: object)
if peerChannel != nil {
peerChannel?.sendFrame(ofType: type, tag: PTFrameNoTag, withPayload: (data as NSData).createReferencingDispatchData(), callback: { (error) in
completion?(true)
})
} else {
completion?(false)
}
}
static func toData(object: Any) -> Data {
return NSKeyedArchiver.archivedData(withRootObject: object)
}
But I always receive '?bplist?' in java client.
Do I have to convert data from server end? Please help.

Sending simple message to node.js from java class using java.net.Socket

I am trying to send a simple message "Hi" to node server where I am using express and socket.io.
Here is how I am initializing my node server
var express = require('express');
var app = express()
, http = require('http')
, server = http.createServer(app)
, io = require('socket.io').listen(server);
io.sockets.on('connection', function (socket) {
socket.on('message', function (msg) {
console.log('Message Received: ', msg);
socket.broadcast.emit('message', msg);
});
});
server.listen(9001);
an I am trying to send the message from my java class as
Socket socket=new Socket("192.168.9.132", 9001);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeUTF("Hi");
socket.close();
I am not getting any console log at the node server end about getting message from socket.
Help how can I achieve this?
socket.io is a websocket, which is a different protocol/implementation than a usual socket. See the net library for TCP sockets.

Desktop server and android client local connection

i try to connect my windows desktop java server from android client. I'm working cross-platform. Desktop server and desktop client working fine with same code, but desktop server and android client has a interesting problem. manifest permissions is setted.
Desktop java server code
ServerSocket serverSocket = new ServerSocket(tcp_port);
Socket link = null;
while(true) {
link = serverSocket.accept();
PrintWriter output = new PrintWriter(link.getOutputStream(),true); // flush true
BufferedReader input = new BufferedReader(new InputStreamReader(link.getInputStream()));
// step 1 password auth
String message = input.readLine(); // wait password
if(message.equals(password)) {
output.println("correct");
message = null;
message = input.readLine(); // wait udp port request
if(message.equals("UDP")) {
output.println(udp_port+"");
etc
.
.
Android client code
Socket link = null;
link = new Socket(hostip,tcp_port);
PrintWriter output = new PrintWriter(link.getOutputStream(),true); // auto flush true
BufferedReader input = new BufferedReader(new InputStreamReader(link.getInputStream()));
while(true) {
// step1 send the password wait the response
output.println(password);
String message = input.readLine(); // password response
if(message.equals("correct")) {
output.println("UDP"); // request udp
message = null;
message = input.readLine();
udpport = Integer.parseInt(message);
etc
.
.
My problem is same code works fine on java desktop client and java desktop server but
when i try to connect java desktop server from android client password auth part works fine but
output.println(udp_port+""); send data two times when i looked to the server side it sends empty string firstly and then sends my value what is wrong ?
message = null;
message = input.readLine(); // wait udp port request
if(message.equals("UDP")) {
it reads the empty string and jump the if statement but if i use
message = null;
message = input.readLine(); // read empty string
message = input.readLine(); // read my data
if(message.equals("UDP")) {
statement works
This is expected behavior if you try to read the data before it has been received - something that is more likely to occur when receiving from a remote system, but always a possibility you must allow for.
Your application must wait until a full message has been collected, in this case probably by looping on the readLine() call until you get a non-null message.

Categories

Resources