I have a client/server pair in which I have this messaging application to which i'm trying to add SSL support. The client/server normally use DataInputStream and DataOutputStream to send/receive their info, working with byte arrays (DataOutputStream.write(byte[]) and DataInputStream.readFully(byte[])). But for some reason, that doesn't work with SSL sockets. I've tried using DataOutputStream.writeUTF() and DataInputStream.readUTF() and it works. I even tried using other types of reader/writers like BufferedReader/BufferedWriter, and they work, but when I try to use bytes, it doesn't send anything. What's weirder is the fact that after checking the DataOutputStream.size() in both sides, they both print that they have sended data.
Server side:
logger.info("Waiting to accept a new client socket");
clientSocket = (SSLSocket) serverSocket.accept();
logger.info("Socket accepted successfully");
DataOutputStream dataOutputStream=newDataOutputStream(clientSocket.getOutputStream());
DataInputStream dataInputStream=new DataInputStream(clientSocket.getInputStream());
logger.trace("Socket is going to read");
int data=dataInputStream.available();
byte[] message=new byte[data];
dataInputStream.readFully(message);
logger.trace("Message received: {}",message);
logger.trace("Gonna respond");
if(message.length>0){
dataOutputStream.write(message,0,message.length);
}else{
String response=new String("wot?".getBytes(),"ASCII");
dataOutputStream.write(response.getBytes(),0,response.getBytes().length);
}
dataOutputStream.flush();
logger.trace("Chars written: {}",dataOutputStream.size());
Client side:
SSLSocketFactory sslsocketfactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
logger.trace("SSL Socket factory created");
javax.net.ssl.SSLSocket sslSocket = (javax.net.ssl.SSLSocket)sslsocketfactory.createSocket(url, port);
logger.trace("SSL Socket created");
sslSocket.setSoTimeout(6000);
outputStream = sslSocket.getOutputStream();
inputStream=sslSocket.getInputStream();
DataOutputStream dataOutputStream=new DataOutputStream(outputStream);
DataInputStream dataInputStream=new DataInputStream(inputStream);
logger.trace("Input and output created");
//dataOutputStream.writeBytes(frame);
//dataOutputStream.writeUTF(frame);
dataOutputStream.write(frame.getBytes(),0,frame.getBytes().length);
dataOutputStream.flush();
logger.trace("Frame {} sent",frame);
logger.trace("Bytes sent: {}",dataOutputStream.size());
int data=dataInputStream.available();
byte[] messageRead = new byte[data];
dataInputStream.readFully(messageRead);
Any help would be highly appreciated. I've been looking around and I don't know what else to try.
Related
I have an assignment where I have to build a Client-Server communication using Java. So what I did was building a Client-Server connect using Sockets, the following way:
//Client code
Socket socket = new Socket("127.0.0.1", 4999);
//Server code
ServerSocket ss = new ServerSocket(4999);
Socket socket = ss.accept();
System.out.println("Client is connected");
For now, the communication between the client and the server is successful, I am able to send messages from client to server and vice versa. but the main problem is storing data on the server host, we were asked to store relevant data on the server host so the server could send it to the client.
Can someone please explain to me how to store data on the server and how to retrieve it ??
Thanks
To read from the server socket:
ServerSocket server = new ServerSocket(port);
Socket socket = server.accept();
DataInputStream in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
//Do whatever you want with the DataInputStream
Source: https://www.baeldung.com/java-inputstream-server-socket
Then we can move to the input stream processing, here is a sample:
...
int i;
char c;
...
try{
// reads till the end of the stream
while((i = in .read())!=-1) {
// converts integer to character
c = (char)i;
// prints character
System.out.print(c);
}
} catch(Exception e){
//Handle....
} finally {
// Close stream...
}
Source: https://www.tutorialspoint.com/java/io/inputstream_read.htm#:~:text=io.-,InputStream.,the%20returned%20value%20is%20%2D1.
For writing to the socket (the response to the client), just follow the following tutorial, no need to repeat it here:
http://www.avajava.com/tutorials/lessons/how-do-i-write-a-server-socket-that-can-handle-input-and-output.html
I hope it helps
I would like to run a combination of Dart and Java code, that can communicate with each other.
Therefore I chose to go with sockets, with the server socket written in Java and the client socket written in Dart.
This is the code I wrote:
Server
ServerSocket server = new ServerSocket(12345);
server.setSoTimeout(0);
System.out.println("waiting for connection...");
while (true) {
try {
Socket client = socket.accept();
DataInputStream input = new DataInputStream(client.getInputStream());
DataOutputStream output = new DataOutputStream(client.getOutputStream());
System.out.println("connected to " + client.getLocalSocketAddress() + ".");
while (true) {
output.write(input.readLine());
}
} catch (IOException e) {
System.out.println("disconnected.\n\nwaiting for connection...");
}
}
Client
Socket client = await Socket.connect('localhost', 12345);
client.write('hello there\n');
client.close();
Unfortunately the server does not receive the ping message sent by the client.
By now I suppose, that the problem lies in the Dart code, because when executing a client written in Java worked just fine.
Do you know, how to solve this? If so, please let me know ho. Thank you in advance!
Please note:
As there will never be more than one client at a time, I chose to go with this approach. I am aware, that normally this is no good style.
In the documentation for close() on the Socket class:
NOTE: Writes to the IOSink may be buffered, and may not be flushed by a call to close(). To flush all buffered writes, call flush() before calling close().
https://api.dart.dev/stable/2.7.1/dart-io/Socket/close.html
I do not know why, but it seems that the problem lies in the DataInputStream/DataOutputStream.
Here is what worked:
Server
ServerSocket server = new ServerSocket(12345);
server.setSoTimeout(0);
System.out.println("waiting for connection...");
while (true) {
try {
Socket client = socket.accept();
BufferedWriter output = BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
BufferedReader input = new BufferedReader(new InputStreamReader(client.getInputStream()));
System.out.println("connected to " + client.getLocalSocketAddress() + ".");
while (true) {
output.writeUTF(input.readUTF());
}
} catch (IOException e) {
System.out.println("disconnected.\n\nwaiting for connection...");
}
}
Client
Socket client = await Socket.connect('localhost', 12345);
client.write('hello there\n');
client.close();
This is working for me.
Socket client = socket.accept();
byte[] b = new byte[100];
client.getInputStream().read(b);
System.out.println(new String(b));
I have a project where I will receive data from a TCP port, I need to be constantly waiting to check if I receive data.
My code for now is:
Socket socket = new Socket();
socket.connect(new InetSocketAddress(ip,8000));
while(true){
DataOutputStream outToClient = new DataOutputStream(socket.getOutputStream());
InputStream inFromClient = socket.getInputStream();
while(true){
int i = inFromClient.read();
System.out.println("data = " + i);
l++;
}
I don't like this strategy based in while(true), There is some strategy to receive data from a callback or something similar?
You can use java File I/O (Featuring NIO.2). Please follow the link for sample
https://github.com/dublintech/async_nio2_java7_examples/blob/master/echo-nio2-server/src/main/java/com/alex/asyncexamples/server/AsyncEchoServer.java
Client
Socket socket = new Socket("ip", 5555);
PrintStream out = new PrintStream(socket.getOutputStream());
out.println("Hello Server!");
out.close();
socket.close();
Server
ServerSocket serverSocket = new ServerSocket(5555);
while (true) {
//keep listening
Socket socket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
String line = in.readLine();
System.out.println(line);
in.close();
socket.close();
}
if ignore concurrency issue, is the way to close sockets connection correct?
if ignore concurrency issue, is the way to close sockets connection correct?
Yes, but you don't need to close the socket if you've already closed the output stream.
if client closed socket immediately after sent data, will it cause some exception like 'socket is close' while server tries to read data from stream?
No. 'Socket is closed' means you closed the socket and then continued to use it. As long has the client has read everything the server is going to send, the client can close the socket: the server will read all the data the client has sent, and then get end-of-stream on the next read.
I set up a client and server sockets. When I use classes ObjectOutputStream and ObjectInputStream and the method readObject/writeObject everything works fine.
It simulates communication with a robot that I know for sure interprets correctly only method
DataOutputStream.writeBytes.
So I set up the new architecture for simulation since the robot is not available for testing on a daily basis.
In the following code where ObjectOutputStream/ObjectInputStream readObject/writeObject were replaced with DataInputStream/DataOutputStream writeBytes and IOutils.toByteArray.
The server socket correctly receives the message but when it tries to write back a response I get a broken pipe as if the connection was closed somewhere.
Notice that I never close sockets or streams because the robot can answer even after 30 seconds.
Any help to make DataOutputStream.writeBytes work would be appreciated.
Here's the non-working code:
Client:
Socket serverSocket = new Socket("server", 9899);
DataOutputStream outputStream = new DataOutputStream(serverSocket.getOutputStream());
//ObjectOutputStream outputStream = new ObjectOutputStream(serverSocket.getOutputStream());
//outputStream.writeObject("\n" + "message" + "\r");
outputStream.writeBytes("\n" + "message" + "\r");
outputStream.flush();
DataInputStream inputStream = new DataInputStream(serverSocket.getInputStream());
//ObjectInputStream inputStream = new ObjectInputStream(serverSocket.getInputStream());
byte [] bytes = IOUtils.toByteArray(inputStream);
String serverResponse = new String(bytes,"UTF-8");
// String serverResponse = (String)inputStream.readObject();
Server:
ServerSocket serverSocket = new ServerSocket(9899);
while (true) {
Socket socket = serverSocket.accept();
//ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
byte [] bytes = IOUtils.toByteArray(inputStream);
String message = new String(bytes,"UTF-8");
//String message = (String) inputStream.readObject();
Thread.sleep(15000);
//ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
//outputStream.writeObject("server response");
outputStream.writeBytes("server response"); //EXCEPTION THROWN HERE FOR BROKEN PIPE
outputStream.flush();
}
Thanks for your time
IOUtils.toString(InputStream) must read the stream until its end, which would imply that the peer has disconnected. So you can't write to it.
If you're exchanging Strings with data streams you should use writeUTF() and readUTF().
Or read and write lines, with a BufferedReader/Writer.