TCP Socket communication Java - Python - java

I want to transmit an integer number throught a socket.
I have a python script that open a socket and wait for requests, in the other side there is a Java servlet that send a request at this socket to obtain a value.
All the communication works well the problem is that the value obtained from java cause a EOFexception. I've tried some convertion and formats in the python script (I'm not expert of this language) but nothing works.
Instead, if I use in python a echo socket, picking all that socket receive and send back to java, all working fine.
But I need to send a simple value.
The following is the portion of code that I use, I've tried with float, this is with a String value:
[Python socket related istructions]
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(server_address)
sock.listen(1)
connection = sock.accept()
[Python echo socket working]
data = connection.recv(16)
if data:
connection.sendall(data)
instead I want to do:
[Python return a example value]
connection.sendall('55')
That working if I send request from a client like Hercules but cause a EOFexception in Java
[Java Servlet - send request]
socket = new Socket(address, port);
dataInputStream = new DataInputStream(socket.getInputStream());
String content = dataInputStream.readUTF(); //EOFexception
Destination.value = content;

Solved the problem by using InputStream instead of DataInputStream, write the python socket to send string as byte and changed the java receiver to read byte stream and convert in to string (good format for my purpose).

Related

Java Socket Client Returns Bad Characters as response for AT commands sent to the connected Modem

I am testing a java code to issue AT Commands to the Modem at the designated port. I was able to successfully make Socket connection to the Modem's default gateway IP and AT Command port and write AT commands to that socket. (something like below)
Socket socket = new Socket(address, port);
socket.setKeepAlive(true);
...
String command = "AT\r\n";
...
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
byte[] commandBytes = command.getBytes(StandardCharsets.US_ASCII);
out.write(commandBytes, 0, commandBytes.length);
out.flush();
And try to read the response from the socket as below
BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
byte[] byteArray = new byte[1024];
int count = in.read(byteArray, 0, byteArray.length);
System.out.println("Response Received: " + new String(byteArray, StandardCharsets.US_ASCII));
The problem is, I am getting bad characters (like ??) as the response. I am expecting the output as "OK". When I issue the same command from the command prompt of the same PC where I am running this code, I am getting the response in proper English. I am assuming (mostly true) that the modem might be using a different language like C, C++ and their byte rage is different from the byte range of Java. But if this is the case, I am not sure how to fix it. Need help.
Things that I have already tried:
Printed the bytes as retrieved and found that these are of negative byte values (like -1, -3, -5 etc)
Verified the default of charset of the modem and if found to be ISO-8859-1 and tried using the same in my code (both write and read) still getting similar bad characters only
Tried reading as characters using BufferredReader* classed, but nothing is getting received at the response
My question in short, how to read the binary(byte array) data received as response from Modem for the given AT commands issued from Java Socket Connection?
Any help in this regard is highly appreciated.

Socket blocked in transmitting json object from Java to Python

I have a problem with a Java-Python Socket. My objective is to send a Json object from java application to python script via socket tcp and receive a response but the socket is blocked after Json sending. In the following there is my code:
try {
Socket socket = new Socket(dstAddress, dstPort);
is = new DataInputStream(socket.getInputStream());
os = new DataOutputStream(socket.getOutputStream());
PrintWriter pw = new PrintWriter(os, true);
pw.println(jsonObject.toString());
System.out.println("Send to the socket jsonObject.");
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String response = in.readLine();
System.out.println("Response: " + response);
is.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
In the following lines the python code:
HOST = "192.168.1.101" #localhost
PORT = 7011
s = socket(AF_INET, SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
while (1):
print("\n\nAttending for client.....\n\n")
conn, addr = s.accept()
print("Connected by: " , addr)
data = ""
while 1:
temp = conn.recv(1024).decode()
if not temp:
break
data = data + temp
print("JSON Received!!!!!")
imageJson = {}
imageJson = json.loads(data)
# responding to the client
response = DbImages[elem[0]]
resp = "Prova"
conn.send(resp.encode())
If I terminate the java code (ctrl+C) the socket exit from block and json arrive to python. What is the problem? The problem seems to be in.readLine (). If I delete that statement then the socket works without blocks.
Your Python code is waiting for the Java side to finish and send EOF before responding (that’s what it means to recv until you get an empty bytes).
Your Java code is waiting for the Python side to respond before closing the socket.
So, they’re both waiting for each other.
Removing the readLine means the Java code is no longer waiting for anything, so it just hangs up on the Python code as soon as it’s done sending, which does make the problem go away—but it isn’t much of a solution if you actually needed a response.
So, what should they be doing? Well, there are a few different options.
Use a framed protocol, where the Java side either sends a “message-done” delimiter after each message or sends a header (with, e.g., the byte length of the message) before each one. So, the Python code can read until it has a complete message, instead of until EOF.
If you encode your JSON in compact format with everything but printable ASCII escaped, then the delimiter can just be a newline (at which point you’re using JSONlines as your protocol), and the Python code can use makefile on the socket and call readline instead of looping over recv.
Cheat and use JSON as if it were a framed protocol. It isn’t, but as long as the only top-level values you ever send are objects and arrays, it works. Then the Python code can use raw_decode (see the json module docs) after each receive until it succeeds.
If you’re only ever going to send a single message, you can just half-shutdown the socket (close the write end) from Java, and then Python will get its EOF and respond on the still-open other side of the socket. (This may sound hacky, but it’s actually perfectly common—it’s how web browsers traditionally work, although HTTP 1.1 made things a bit more complicated.)
Your response is not a line, as it doesn't seem to contain a line ending.
That means it readLine will read forever.
Try adding a newline to your response to make readLine happy:
resp = "Prova\n"

Dart - How to receive and decode JSON packet sent from a Java application

In my server-side code I need to be able to listen to a socket to exchange JSON 'packets' with a Java 7 test application on the same machine. The connection is made and a JSON string is constructed and written to the socket by the Java test application. It is received by the Dart server-side application and passed to a callback method, handleJson, which attempts to decode it. The process dies on 'JSON.decode'.
I think it dies because the string is prepended, by the Java 'writeUTF' method with a short int that contains the number of bytes in the JSON UTF-8 uncluding the leading short and the leading byte is 0.
Is there a Dart method to handle this, in each direction, or must I write the code? (I had thought that JSON work easily between languages.)
The JSON string before writing to the socket in my Java test application:
{"target":"DOOR","command":"OPEN"} // 34 characters
A Java snippet:
// in a try-catch
Socket client = new Socket(serverName, port);
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF(json);
client.close();
The Java documentation states that the out.writeUTF method converts the json string to UTF-8 with the string length prepended as a short int containing the total number of bytes written.
In main:
ServerSocket.bind('127.0.0.1', 4041)
.then((serverSocket) {
print('connected');
// prints: 'connected'
serverSocket.listen((socket) {
socket.transform(UTF8.decoder).listen(handleJson);
});
});
handleJson method:
handleJson(String stringAsJson){
print('string length is ' + (stringAsJson.length).toString());
// prints: 'string length is 36'
print('received json $stringAsJson');
// prints: 'received json '
String json = JSON.decode(stringAsJson);
// dies on decode
print('Sever Socket received: $json');
}
This will give you some troubles, since Socket is raw TCP, and TCP is streaming. That means that the text (bytes) you send can be split and merged in any way the network may find suitable.
In your case, you need a way to mark the end of each JSON message. An example could be to accumulate all bytes received, until the byte 0 is seen (invalid in JSON). Those bytes could then be converted to UTF8 and then again converted to JSON. Note that the peer needs to send this 0 byte in between messages, for this to work.
Now, you also consider using WebSockets as a way to sent messages. After the initial HTTP handshake, it's actually just a raw TCP socket with some extra header information, to make it package oriented - exactly what you need. dart:io already includes a WebSocket implementation.

purpose of socket.shutdownOutput()

I am using the below code to send data to a tcp server. I am assuming that I need to use socket.shutdownOutput() to properly indicate that the client is done sending the request. Is my assumption correct? If not please let me know the purpose of shutdownOutput(). Also appreciate any further optimizations I can make.
Client
def address = new InetSocketAddress(tcpIpAddress, tcpPort as Integer)
clientSocket = new Socket()
clientSocket.connect(address, FIVE_SECONDS)
clientSocket.setSoTimeout(FIVE_SECONDS)
// default to 4K when writing to the server
BufferedOutputStream outputStream = new BufferedOutputStream(clientSocket.getOutputStream(), 4096)
//encode the data
final byte[] bytes = reqFFF.getBytes("8859_1")
outputStream.write(bytes,0,bytes.length)
outputStream.flush()
clientSocket.shutdownOutput()
Server
ServerSocket welcomeSocket = new ServerSocket(6789)
while(true)
{
println "ready to accept connections"
Socket connectionSocket = welcomeSocket.accept()
println "accepted client req"
BufferedInputStream inFromClient = new BufferedInputStream(connectionSocket.getInputStream())
BufferedOutputStream outToClient = new BufferedOutputStream(connectionSocket.getOutputStream())
ByteArrayOutputStream bos=new ByteArrayOutputStream()
println "reading data byte by byte"
byte b=inFromClient.read()
while(b!=-1)
{
bos.write(b)
b=inFromClient.read()
}
String s=bos.toString()
println("Received request: [" + s +"]")
def resp = "InvalidInput"
if(s=="hit") { resp = "some data" }
println "Sending resp: ["+resp+"]"
outToClient.write(resp.getBytes());
outToClient.flush()
}
I am using the below code to send data to a tcp server. I am assuming
that I need to use socket.shutdownOutput() to properly indicate that
the client is done sending the request. Is my assumption correct?
YES Your assumption is correct. And this output ShutDown is known as half close . Using half close the TCP provides the ability for one end of the connection to terminate its output, while still receiving data from the other end. Let me walk you through the effects of socket.shutdownOutput() method :
Locally, the local socket and its input stream behave normally for reading
purposes, but for writing purposes the socket and its output stream behave
as though the socket had been closed by this end: subsequent writes to the
socket will throw an IOException
TCP’s normal connection-termination sequence (a - FIN acknowledged by
an ACK) is queued to be sent after any pending data has been sent and acknowledged.
Remotely, the remote socket behaves normally for writing purposes, but for
reading purposes the socket behaves as though it had been closed by this
end: further reads from the socket return an EOF condition, i.e. a read count
of -1 or an EOFException , depending on the method being called.
When the local socket is finally closed, the connection-termination sequence
has already been sent, and is not repeated; if the other end has already
done a half-close as well, all protocol exchanges on the socket are now
complete.
Hence we see that When the EOF is received, that end is assured that the other end has done the output shutdown. And this scenario is perfectly achieved by socket.shutDownOutput() on the other side.
Source: Fundamental Networking in Java, Esmond Pitt
Socket.shutdownOutput() means that the client is finished sending any data through the TCP connection. It will send the remaining data followed by a termination sequence which will completely close its OUTGOING connection. It is not possible to send any further data, which will also indicate to your program that the request is completely finished. So its recommended if you are sure you don't have to send any more data.
But it's not needed to indicate that the request is finished (you don't have to open/close the output all the time if you have multiple requests), there are other ways.

Redirect InputStream to Socket´s OutputStream

Suppose I have following Java code on a server:
Socket aSocket = new Socket(aInetaddr, aPort); //aSocket is a client i m connecting to
InputStream input = aSocket.getInputStream();
Socket bSocket = new Socket(bInetaddr, bPort); //bSocket is a client i m connectin to
Now what I would like to achieve is, to pass the InputStream "input" from the aSocket to the bSocket. I have no information about whats coming from the InputStream, or how it is used in the end.
The whole transfer of data has to pass my server, I can't make a direct connection between the 2 clients.
Get the output stream for the second socket and then you can do this trivially using Apache Commons IOUtils.copy(). Amongst many variants there's one that takes an input and output stream as arguments.

Categories