SSLSocket receive and send requests without blocking thread - java

I'm trying to read from a SSLSocket server, I need the client to be open 24/7, Note I am only making the client, The server is already set up, I'm trying to read data and send data from the server, How ever when I do try to read the data it blocks my current thread and I can't seem to do anything else after that since the loop never ends, and if I make a loop that ends the program returns. I want it to be open always and keep getting incoming request and then send request back according to what I receive, this is what I currently have.
private SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
private SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(host, port);
private BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(sslsocket.getOutputStream()));
private InputStream is = sslsocket.getInputStream();
these are the global vars I have defined, and this is how I write data to the server
private void write_to_server(String date) throws IOException {
writer.write(date);
writer.flush();
}
and finally this is how I receive response and this is where I am having the problem.
public String getResponse() throws IOException {
byte[] buffer = new byte[16384];
String a = "";
for (int b; ((b = is.read(buffer)) > 0); ) {
a = new String(buffer, 0, b, StandardCharsets.UTF_8);
Log(a);
}
return a;
}
The loop never ends, causing the thread to be stuck, and even if the loop ends the program will just return after that causing the program to end. I need to know how I can have it set up to receive data 24/7 and then send data back after I received response.

Related

ESP8266 - client socket is getting closed after calling method readBytes

I'm trying to send a message from my pc to the board, but the problem is I keep losing connection before I decide to send a message.
This is code from which I'm sending the message. I create a socket, connect to the board, and then wait for inputs from the Scanner object. When I get some input I send a message to the board.
CLIENT
Socket socket = new Socket();
socket.connect(new InetSocketAddress("192.168.4.1",3000));
Scanner in = new Scanner(System.in);
String message = DataProtocol.sendMessageFormat("KLASA","METHOD","FILIP CACIC");
String message1 = DataProtocol.sendMessageFormat("KLASA","METHOD","FILIP CACIC");
message = message1 + message;
OutputStream outputStream = socket.getOutputStream();
String line;
while(!(line = in.nextLine()).equals("EXIT")){
outputStream.write(message.getBytes());
outputStream.flush();
}
This is code that is recv.message.
SERVER
void CommunicationProcessor::readFromStream(WiFiClient* wifiClient){
CLIENT_ACTIVE = true;
while(CLIENT_ACTIVE){
Serial.println(wifiClient->connected()); -> returns 1
int bytesRead = wifiClient->readBytes(buffer,1024); -> returns 0
Serial.println(wifiClient->connected()); -> returns 0
dataManager.appendData(bufferReader.getDataReaded(buffer,bytesRead));
if (checkIfEndLine(bytesRead)){
handleDataRecv();
dataManager.clearBuffer();
}
}
Serial.println("CLIENT QUIT");
}
Before method readBytes, I call method connected() and it returns 1. So everything is fine.
Method readBytes returns 0, because I did not yet send any message.
After that, I call connected() one more time and this time it returns 0.
Now if I remove this Scanner object and loop from code and send a message immediately, a server will recv. message.
Socket socket = new Socket();
socket.connect(new InetSocketAddress("192.168.4.1",3000));
Scanner in = new Scanner(System.in);
String message = DataProtocol.sendMessageFormat("KLASA","METHOD","FILIP CACIC");
String message1 = DataProtocol.sendMessageFormat("KLASA","METHOD","FILIP CACIC");
message = message1 + message;
OutputStream outputStream = socket.getOutputStream();
outputStream.write(message.getBytes());
outputStream.close();
My questions are why is connection closed after I call method readBytes?
EDIT
I just tested with this code and connection still get lost.
Line "Client alive" only gets printed one time.
SERVER
void loop(){
delay(1000);
if (client){
Serial.println("Client alive");
Serial.println(client.connected());
}else{
client = server.available();
if (client){
Serial.println(client.connected());
}
}
}
EDIT 2
I found the problem. I was using board as WIFI-ACCESS POINT, but when I connected board to my router and my pc, everything works fine.
So now my questions is why am I losing connection when board is configured as ACCESS-POINT?
EDIT 3
I found what was causing the problem. I had problem with connecting to wifi access point so i called method WIFI.persistent(false) and that was causing Broken Pipe exception (stream closed) in java.

How to handle sending multiple messages over a socket connection?

I'm a bit of a beginner programmer so it's possible this is quite obvious and I'm overlooking the answer. But on to the question.
I have a two-part program (its a little more complicated than this example, but the situation is the same). The program has multiple messages fired between the client and the server. I have a PrintWriter on the server-side to send messages to the client, and on the client, I have a BufferedReader to read the messages sent.
When this example is run, I'm given two lines as output. The first message is both messages, and the second is NULL. What I am wondering is if there is a way to basically halt the server until I am ready for the second message, so that I can do something on the client-side before the second message is sent.
I am hoping to not use Thread.Sleep, as I would rather the Server wait around until the Client says it is ready.
This is the client:
public class Client{
public void run(){
Socket socket = null;
InputStream in = null;
BufferedReader reader = null;
try{
socket = new socket("LocalHost",1234);
in = socket.getInputStream();
reader = new BufferedReader(new InputStreamReader(in));
}
String messageFromServer = "";
try{
messageFromServer=reader.readLine();
}
System.out.println(messageFromServer);
String messageFromServer = "";
try{
messageFromServer=reader.readLine();
}
System.out.println(messagefromServer);
//close everything
}
}
This is the server:
public class Server{
public void run(){
ServerSocket server = null;
Socket client = null;
try{
server = new ServerSocket(1234);
client = server.accept();
}
PrintWriter writer = null;
OutputStream out = null;
try{
out = client.getOutputStream();
writer = new PrintWriter(out, true);
}
writer.write("Hi I'm a server");
//do some stuff that takes some time, user input, etc. etc.
writer.write("I'm still a server");
//close everything
}
Thanks :)
The problem with the way you currently have you code is the fact that you are using a BufferedReader, but the server is not terminating it's messages with a new line.
When you close the writer, the client is reaching the EOF or EOS and unblocking the read so it appears that both strings are being sent at once...
If you do something like...
writer.write("Hi I'm a server\n");
// This will force the message to be written to the client and picked up ;)
writer.flush();
writer.write("I'm still a server\n");
writer.flush();
Then you will get the messages seperatly...
You can use ObjectInputStream to read Objects instead of Strings.
This way you will read only one Message(String in your case) every call to ObjectInputStream.readObject();
BTW you can read the first message, "do something" and then read the second message. you don't have to read all of the sent messages at once.
If there are no other messages, then your thread will be blocked when trying to read an object from the ObjectInputStream.
Use it like:
ObjectInputStream inputStream = new ObjectInputStream( socket.getInputStream() )

performance issue. The Speed is too slow while reading bytes from socket using java

these days I'm confused about the Tcp performance while using java socket. In fact the java code is very simple. details as below:
server open a port and begin to listen.
client request and after connect to server, client begin to write to socket.
after server got the request, it will open a new thread to handle this connection. (this connection is a long connection which will not time out).
the server will keep reading until it got the end separator, then give a response to the client and continue to keep reading again.
after client get the response, it will send another request again.
I find if the client write the whole message (including the end separator) one time, the communication speed is good satisfactorily, the speed can reach to 50000 messages per minute. How ever, if the client write the bytes to socket in separated times, the speed cut down quickly, just almost 1400 messages per minute, it is 1/40 times compared with the original speed. I'm quite confused about it. Any one could give me a hand? Any comments is appreciated!
my simulated server side is as below:
public class ServerForHelp {
final static int BUFSIZE = 10240;
Socket socket;
String delimiter = "" + (char) 28 + (char) 13;
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(9200);
System.out.println("begin to accept...");
while (true) {
Socket s = ss.accept();
Thread t = new Thread(new SocketThread1(s));
t.start();
}
}
public String readUntilDelimiter() throws Exception {
StringBuffer stringBuf = new StringBuffer();
InputStream stream = socket.getInputStream();
InputStreamReader reader = null;
reader = new InputStreamReader(stream);
char[] buf = new char[BUFSIZE];
while (true) {
int n = -1;
n = reader.read(buf, 0, BUFSIZE);
if (n == -1) {
return null; // it means the client has closed the connection, so return null.
} else if (n == 0) {
continue; // continue to read the data until got the delimiter from the socket.
}
stringBuf.append(buf, 0, n);
String s = stringBuf.toString();
int delimPos = s.indexOf(delimiter);
if (delimPos >= 0) {
// found the delimiter; return prefix of s up to separator and
// To make the thing simple, I have discarded the content after the delimiter.
String result = s.substring(0, delimPos);
sendTheResponse(socket);
return result;
}
}
}
private void sendTheResponse(Socket socket) throws IOException {
Writer writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
writer.write("Hi, From server response");
writer.flush();
}
}
class SocketThread1 implements Runnable {
Socket socket;
public SocketThread1(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
ServerForHelp server = new ServerForHelp();
server.socket = socket;
while (true) {
try {
if (server.readUntilDelimiter() == null) // it means that the client has closed the connection, exist
break;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
It is a normal socket programming.
and the following is my client side:
public void execute() throws Exception{
int msgCnt = 0;
Socket socket = null;
byte[] bufBytes = new byte[512];
long start = 0;
final char START_MESSAGE = 0x0B;
final char END_MESSAGE = 0x1C;
final char END_OF_RECORD = 0x0D;//\r
String MESSAGE = "HELLO, TEST";
socket = new Socket("192.168.81.39", 9200);
OutputStream os = socket.getOutputStream();
InputStream is = socket.getInputStream();
while (System.currentTimeMillis() - start < 60000)
{
// If you send the total message at one time, the speed will be improved significantly
// FORMAT 1
StringBuffer buf = new StringBuffer();
buf.append(START_MESSAGE);
buf.append(MESSAGE);
buf.append(END_MESSAGE);
buf.append(END_OF_RECORD);
os.write(buf.toString().getBytes());
// FORMAT 1 END
//FORMAT 2
// os.write(START_MESSAGE);
// os.write(MESSAGES[port].getBytes());
// os.write(END_MESSAGE);
// os.write(END_OF_RECORD);
//FORMAT 2 END
os.flush();
is.read(bufBytes);
msgCnt++;
System.out.println(msgCnt);
}
System.out.println( msgCnt + " messages per minute");
}
If I use the "FORMAT 1", to send the message, the speed could reach to 50000 messages per minute, but If use "FORMAT 2", the speed is down to 1400 messages per minute. Who is clear about the reason?
I'm trying to describe as detail as I can and any help will be appreciated very much.
Multiple very short writes to a socket in rapid succession followed by a read can trigger a bad interaction between Nagle's algorithm and TCP delayed acknowledgment; even if you disable Nagle's algorithm, you'll cause an entire packet to be sent per individual write call (with 40+ bytes of overhead, whether the write is one byte or a thousand).
Wrapping a BufferedOutputStream around the socket's output stream should give you performance similar to "FORMAT 1" (precisely because it holds things in a byte array until it fills or is flushed).
As John Nagle explained on Slashdot:
The user-level solution is to avoid write-write-read sequences on sockets. write-read-write-read is fine. write-write-write is fine. But write-write-read is a killer. So, if you can, buffer up your little writes to TCP and send them all at once.

Empty Socket InputStream

I'm trying to build a simple web server in Java as practice but I'm running into a very strange issue. When I attempt to read the InputStream from the Socket, sometimes there is no data to be read.
The process I'm following is this:
I create a ServerSocket, listening on port 80, and call accept() to get a Socket. I then send a request from my browser (Firefox) to localhost, which triggers the accept() to return the Socket.
Sometimes, it will read the HTTP request perfectly. Other times, it fails to read any data (read() returns a -1).
Here is some sample code to illustrate what I'm doing, without any exception handling thrown in:
ServerSocket serv = new ServerSocket(80);
while (true)
{
Socket con = ServerSocket.accept();
InputStream input = con.getInputStream();
bytes[] bytes = new bytes[4000000]; // for simplicity, I figured I'd
// just make the array huge for now
int bytesRead = input.read(bytes);
if (bytesRead > 0)
{
StringBuffer sBuffer = new StringBuffer(bytesRead);
for (int i = 0; i < bytesRead; i++)
{
sBuffer.append((char) bytes[i]);
}
System.out.println(sBuffer.toString());
}
}
EDIT: I've also tried using a BufferedInputStream and BufferedReader to not avail.
One socket can receive more packets. So you should create a new thread for every socket. Something like:
while(true){
Socket socket = serv.accept();
Client client = new Client(socket);
new Thread(client).start();
}
Then you need to create the Client class which implements the runable interface.
Socket socket;
public Client(Socket socket){
this.socket = socket;
}
public void run(){
while(socket.isConnected()){
//here reads the packets from the inputstream
}
}
You should always loop when reading data from an InputStream. there is no guarantee that all the data will be returned from a single read() call (loop until you receive -1).

Java - Socket - Freeze

i've a minimal server which wait until a client connect ,then he start a thread which will send a reply back to the client, the problem is the reply.
This is the code of the server:
int port = 1234;
ServerSocket servSock = null;
servSock = new ServerSocket(port);
while (true) {
Socket link = servSock.accept();
serverThread st = new serverThread(link);
st.start();
}
This is the code of the run() method of the thread,the one which send the answer back, sk is the socket "link" passed by parameter in the server code
public void run() {
String dato = "";
InputStream i = null;
try {
i = sk.getInputStream();
} catch (IOException ex) {
Logger.getLogger(serverThread.class.getName()).log(Level.SEVERE, null, ex);
}
Scanner input = new Scanner(i);
//i receive the data sent
while (input.hasNext()) {
dato += input.nextLine();
}
// then i send a reply
DataOutputStream outputStream=new DataOutputStream(sk.getOutputStream());
outputStream.writeInt(1);
outputStream.close();
Client side ( only the code which should receive the answer from the server) :
Socket link;
int valid = 0;
String url="localhost";
int port=1234;
link = new Socket(InetAddress.getByName(url), port);
//i've to send some data to the server
PrintWriter output = new PrintWriter(link.getOutputStream(), true);
String a = new String(Base64.encode(mex));
output.println(createXml(tag, a));
output.flush();
//then i need to receive an answer from the server
DataInputStream answerI = new DataInputStream(link.getInputStream());
while(answerI.available()!=0)// but answerI.available() is always equal 0
valid = answerI.readInt();
answerI.close();
output.close ();
link.close();
With this code the istruction valid = answerI.readInt(); is not reached.
Without the while cycle, the client freeze at line : valid = answerI.readInt();
Can anyone help me?
Thank you in advance
I'm guessing that the server is blocked in a call to input.hasNext(). This will return false when the socket is closed, and its InputStream returns -1 to signal the end of the stream. However, the socket is still open. The client can send another line; the Scanner is blocking to see what the client's next move will be.
There are ways to shutdown "half" of a socket, so that the server can tell that the client has closed its sending channel but can still receive a response.
However, this approach is complicated. I suggest a change to the protocol so that the server can determine when it is allowed to respond.
In this protocol you don't need the reply if it is always '1'. Just close the socket. The client should block in a read() which will return -1 when the server closes the socket.

Categories

Resources