My project involves reading the status of an LED on Arduino, from java. It will move on to reading temperature from Arduino, but I got stuck. So here it is:
I send the "Turn on/off!" message from my java program, and I want it to show if the LED is on and off.
So when I send "192.168.0.100/ON", the LED turns on and I shoud get the "ON" message in my program.
The code on Arduino:
byte mac[] = {0x90, 0xA2, 0xDA, 0x0D, 0x2F, 0xD4 };
IPAddress ip(192,168,0,100);
EthernetServer server(80);
String message = String(30);
void setup()
{
pinMode(2, OUTPUT);
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
server.begin();
Serial.begin(9600);
}
void loop()
{
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
// an http request ends with a blank line
while (client.connected()) {
if (client.available()) {
char c = client.read();
if (message.length() < 30) {
message += c;
}
Serial.print(message);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n') {
if (message.indexOf("ON") > 0) {
digitalWrite(2, HIGH);
client.print("ON");
}
if (message.indexOf("OFF") > 0) {
digitalWrite(2, LOW);
client.print("OFF");
}
message = "";
client.stop();
}
}
}
// give the web browser time to receive the data
delay(1);
}
}
The code in java:
public class TestClient {
public static void main(String[] args) {
HttpURLConnection connection = null;
BufferedReader serverResponse = null;
try {
// OPEN CONNECTION
connection = (HttpURLConnection) new URL("http://192.168.0.100/ON")
.openConnection();
connection.connect();
// RESPONSE STREAM
serverResponse = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
// READ THE RESPOSNE
String line;
while ((line = serverResponse.readLine()) != null) {
System.out.println(line);
}
} catch (MalformedURLException mue) {
mue.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
if (connection != null)
connection.disconnect();
if (serverResponse != null) {
try {
serverResponse.close();
} catch (Exception ex) {
}
}
}
}
}
What happens: The LED turns on, but I get this error in java:
java.net.SocketException: Unexpected end of file from server at TestClient.main(TestClient.java:23) -> connection.getInputStream();
What I want: After sending the "ON" message, it should be printed in console.
Mention: if I send 192.168.0.100/ON from my browser, the LED turns on and the message appears in the web page.
There are two issues here:
If the exception is thrown when getting the InputStream, then it's happening because the connection has been closed at that point, and this happens because the Arduino sends the message then immediately "closes" the client, effectively terminating the connection. You can do three things:
a. Try and creating the input stream before calling connect(), but this most likely will fail due to the connection not existing at that point.
b. Put a delay before calling client.stop();
c. (recommended) Let the client close the connection, don't do it on the server.
Try adding a \n after ON and OFF in client.print() method, in the Arduino code.
client.print("ON\n");
...
client.print("OFF\n");
readLine() will read until the first end-of-line char which never comes.
Try reverse the order in your finally block. Close the input stream before you close the socket.
As this guy here says, the Arduino can serve HTML pages, so I guessed my HttpURLConnection must know about this. Here, it says that "The version of an HTTP message is indicated by an HTTP-Version field in the first line of the message."
So I simply added the following code into the Arduino sketch, right after I check (c == "\n"):
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
I didn't get to this very quickly, but after reading others` code and the resources I mentioned above, I came to this conclusion. The explanation could be as well wrong for all I know, but it worked, and my project runs.
Related
I'm trying to send commands from my client side, implemented with Java, to the server side, implemented using C++, through TCP connection. The server-side code is given and tested, so I'm fairly certain that the parsing of the command is not the problem. But when I try to send String commands from the Java side, the server side receives multiple packages sometimes so it does not get parsed correctly. Since the server only executes a command when it ends with a new line symbol, the first part of the command gets discarded and an unknown message error is thrown.
I'm using the DataOutputStream for the Java side, and using DataOutputStream.writeBytes(String s) to write my command, and using a BufferedReader to read the message returned by the server.
I'm able to test the server by using telnet to connect to the server without launching Java side code. From telnet, I can successfully send multiple commands and they get parsed correctly. However, when I try to send commands from Java, they get broken up into pieces. The first command is always fine, which is always "add_server 3\n", and the second command, which is "dec_dimmer\n" gets chopped up into "d" and "ec_dimmer\n" and all the subsequent commands in a similar fashion.
Here's how the send command part is implemented:
DataOutputStream outToServer = null;
try {
outToServer = new DataOutputStream(mClientSocket.getOutputStream());
} catch(IOException e) {
e.printStackTrace();
}
try {
String cmd = command + '\n';
if(mDebug) {
System.out.println("Sending Command: " + cmd);
}
outToServer.writeBytes(cmd);
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader inFromServer = null;
try {
inFromServer = new BufferedReader(new InputStreamReader(mClientSocket.getInputStream()));
} catch(IOException e) {
e.printStackTrace();
}
String jsonOutput = null;
try {
jsonOutput = inFromServer.readLine();
} catch(IOException e) {
e.printStackTrace();
}
if(mDebug) {
System.out.println("FROM SERVER: " + jsonOutput);
}
return jsonOutput;
In addition, the exact same client has been implemented in c++ before and is working perfectly fine. The following function is the send command function from the c++ version of the client:
std::string SwimClient::sendCommand(const char* command) {
if (!socket.is_open()) {
throw std::runtime_error("socket is closed");
}
boost::system::error_code ignored_error;
cout << "sending command = " << command << endl;
boost::asio::write(socket, boost::asio::buffer(command, strlen(command)),
boost::asio::transfer_all(), ignored_error);
vector<char> buffer(128);
boost::system::error_code error;
size_t len = socket.read_some(boost::asio::buffer(buffer), error);
if (error)
throw boost::system::system_error(error);
string reply(buffer.data(), len);
if (reply.compare(0, 6, "error:") == 0) {
// trim strings
size_t last = reply.length() - 1;
while (isspace(reply.at(last))) {
reply.erase(last--);
}
string cmd(command);
last = cmd.length() - 1;
while (isspace(cmd.at(last))) {
cmd.erase(last--);
}
throw std::logic_error(reply + "(cmd " + cmd + ')');
}
return reply;
}
EDIT: I uploaded some sourcecode here: http://stabbedbit.com/MCapp/
I'm having the problem with my stream that the client throws a StreamCorruptedException every other time.
For example:
first time: works fine -> exit client application.
second time: StreamCorruptedException -> exit client application.
third time: works fine -> exit client application.
forth time: StreamCorruptedException -> exit client application.
and so forth.
Here's the story (in short)
The server while(true) loops for clients, accepts them and if an accepted client quits the server's inputStream throws a Socket Exception which I catch and use to run this bit code:
if(dataSender != null) dataSender.stop();
if(dataReceiver != null) dataReceiver.stop();
try { if(output != null) output .close(); } catch(IOException e) { streamNotClosed("output"); }
try { if(input != null) input .close(); } catch(IOException e) { streamNotClosed("input"); }
try { if(cryptOut!= null) cryptOut .close(); } catch(IOException e) { streamNotClosed("encrypted output"); }
try { if(cryptIn != null) cryptIn .close(); } catch(IOException e) { streamNotClosed("encrypted input"); }
try { if(clientSocket != null) clientSocket.close(); }
catch(IOException e){ logger.warning(socketNotClosed); }
That all seems to work fine
The client and the server both use this bit of code for initializing streams:
cryptOut = new CipherOutputStream(clientSocket.getOutputStream(), protocol.encoder);
output = new ObjectOutputStream(cryptOut);
cryptIn = new CipherInputStream(clientSocket.getInputStream(), protocol.decoder);
input = new ObjectInputStream(cryptIn);
if all goes well a String is exchanged as handshake, the user gets verified and then input and output get forwarded to be handled by separate threads.
But when it doesn't the following error gets thrown at "input = new ObjectInputStream(cryptIn);"
java.io.StreamCorruptedException: invalid stream header: 81C69F13
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:801)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:298)
at com.stabbedbit.minecraftRemoteAdmin.desktop.connection.ConnectionManager.run(ConnectionManager.java:89)
at java.lang.Thread.run(Thread.java:722)
(The code it throws (81C69F13) is different every time)
I have tried solving this by calling the garbage collector when stopping the threads and closing the streams. But it without result. And I don't have any idea why else this could happening.
Edit: I also found out my server breaks if I connect a second client...
If anyone knows anything to help me out, Thanks in advance.
In your outputstream after you are done writing, flush() the stream. Also, check your Ciphers are properly initialized/reset in your code
Maybe you need to close the ObjectOutputStream code;
out.close();
I'm writing a program that connects to a servlet thanks to a HttpURLConnection but I stuck while checking the url
public void connect (String method) throws Exception {
server = (HttpURLConnection) url.openConnection ();
server.setDoInput (true);
server.setDoOutput (true);
server.setUseCaches (false);
server.setRequestMethod (method);
server.setRequestProperty ("Content-Type", "application / xml");
server.connect ();
/*if (server.getResponseCode () == 200)
{
System.out.println ("Connection OK at the url:" + url);
System.out.println ("------------------------------------------- ------- ");
}
else
System.out.println ("Connection failed");
}*/
I got the error :
java.net.ProtocolException: Cannot write output after reading input.
if i check the url with the code in comments but it work perfectly without it
unfortunately, I need to check the url so i think the problem comes from the getResponseCode method but i don t know how to resolve it
Thank you very much
The HTTP protocol is based on a request-response pattern: you send your request first and the server responds. Once the server responded, you can't send any more content, it wouldn't make sense. (How could the server give you a response code before it knows what is it you're trying to send?)
So when you call server.getResponseCode(), you effectively tell the server that your request has finished and it can process it. If you want to send more data, you have to start a new request.
Looking at your code you want to check whether the connection itself was successful, but there's no need for that: if the connection isn't successful, an Exception is thrown by server.connect(). But the outcome of a connection attempt isn't the same as the HTTP response code, which always comes after the server processed all your input.
I think the exception is not due toprinting url. There should some piece of code which is trying to write to set the request body after the response is read.
This exception will occur if you are trying to get HttpURLConnection.getOutputStream() after obtaining HttpURLConnection.getInputStream()
Here is the implentation of sun.net.www.protocol.http.HttpURLConnection.getOutputStream:
public synchronized OutputStream getOutputStream() throws IOException {
try {
if (!doOutput) {
throw new ProtocolException("cannot write to a URLConnection"
+ " if doOutput=false - call setDoOutput(true)");
}
if (method.equals("GET")) {
method = "POST"; // Backward compatibility
}
if (!"POST".equals(method) && !"PUT".equals(method) &&
"http".equals(url.getProtocol())) {
throw new ProtocolException("HTTP method " + method +
" doesn't support output");
}
// if there's already an input stream open, throw an exception
if (inputStream != null) {
throw new ProtocolException("Cannot write output after reading
input.");
}
if (!checkReuseConnection())
connect();
/* REMIND: This exists to fix the HttpsURLConnection subclass.
* Hotjava needs to run on JDK.FCS. Do proper fix in subclass
* for . and remove this.
*/
if (streaming() && strOutputStream == null) {
writeRequests();
}
ps = (PrintStream)http.getOutputStream();
if (streaming()) {
if (strOutputStream == null) {
if (fixedContentLength != -) {
strOutputStream =
new StreamingOutputStream (ps, fixedContentLength);
} else if (chunkLength != -) {
strOutputStream = new StreamingOutputStream(
new ChunkedOutputStream (ps, chunkLength), -);
}
}
return strOutputStream;
} else {
if (poster == null) {
poster = new PosterOutputStream();
}
return poster;
}
} catch (RuntimeException e) {
disconnectInternal();
throw e;
} catch (IOException e) {
disconnectInternal();
throw e;
}
}
I have this problem too, what surprises me is that the error is caused by my added code System.out.println(conn.getHeaderFields());
Below is my code:
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
conn.setRequestMethod("POST");
configureConnection(conn);
//System.out.println(conn.getHeaderFields()); //if i comment this code,everything is ok, if not the 'Cannot write output after reading input' error happens
conn.connect();
OutputStream os = conn.getOutputStream();
os.write(paramsContent.getBytes());
os.flush();
os.close();
I had the same problem.
The solution for the problem is that you need to use the sequence
openConnection -> getOutputStream -> write -> getInputStream -> read
That means..:
public String sendReceive(String url, String toSend) {
URL url = new URL(url);
URLConnection conn = url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.sets...
OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
out.write(toSend);
out.close();
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String receive = "";
do {
String line = in.readLine();
if (line == null)
break;
receive += line;
} while (true);
in.close();
return receive;
}
String results1 = sendReceive("site.com/update.php", params1);
String results2 = sendReceive("site.com/update.php", params2);
...
i have a java client-server app in java, both using the same connection class that contains both send/receive messages.
for some reason, some of the messages i send are received in a malformed order:
here's the code
//set up
_in = new BufferedReader(new InputStreamReader(this._socket.getInputStream()));
_out = new BufferedWriter(new OutputStreamWriter(this._socket.getOutputStream()));
this._socket.setSoTimeout(S_TIMEOUT);
public synchronized boolean send(String message){
try {
_out.write(message);
_out.write(Connection.DELIMITER);
_out.flush();
return true;
} catch (IOException e) {
}
return false;
}
public String receive(){
int c;
try {
String message = "";
System.out.println("Getting message:");
c = _in.read();
while(c != -1 && c != Connection.DELIMITER) {
message += (char) c;
c = _in.read();
}
if (c == -1) {
return null;
}
return message;
} catch (IOException e) { }
return null;
}
some messages, for example "new_order" will might return with "ew_ord".
some characters are lost, others are sent separately. this seems odd as its TCP
could this be an encoding related issue?
Delimiter is (char) 0
socket timeout is 20000 (ie 20 senconds). every 10 seconds i send an empty message to make sure socket does not close
EDIT:
although it was solved using the Scanner, i must say that the original code worked fine for many messages/various machines for a very long time (a few weeks), and then suddenly failed to work with one specific message on one specific machine (other messages went through just fine). i've done socket data transfer in java MANY times and i've written many read/write methods to handle the sockets. it's the first time i ran into this.
although in the original code i set the encoding (in the posted code i didn't), i believe that the problem was encoding related. at one point, the message that was received had every second character missing. afterwards i changed it a bit, and the first/second character of the message were received in a separate message. from my understanding, it's either an encoding issue or some firewall/other security program that was running on the message sender machine, that decided to filter outgoing packets.
Try replacing your receive with a Scanner and let it do the work for you.
// in your setup
Scanner sc = new Scanner(_in).useDelimiter(Connection.DELIMETER);
public String receive() {
try {
return sc.next();
} catch(IOException e) {
return "";
}
}
For starters, I would make sure you're printing exceptions in those catch blocks.
Then, you're using the platform default encoding for converting characters to bytes. If these two processes are running on different machines, it's possible they're using different encodings. I would make sure you're specifying an encoding when you set up the Reader and Writer.
You can use UTF encoding for getting Full String of Message.
U can try this code and I am Sure About this code because i used it in My Chat Application.
String data=" ";
socket = new Socket("localhost",999);
while(true)
{
dos = new DataOutputStream(socket.getOutputStream());
dis = new DataInputStream(socket.getInputStream());
data = dis.readUTF();
jta.append(data +"\n");
}
Where jta is JTextArea.
It's for Client Side
Now For Server Side:
try
{
server = new ServerSocket(999);
Socket soc = server.accept();
while(true)
{
String data="";
try
{
dis = new DataInputStream(soc.getInputStream());
dos = new DataOutputStream(soc.getOutputStream());
data = dis.readUTF();
}
catch(Exception e)
{ }
jta.append(data + "\n");
}
}
catch (IOException e)
{
JOptionPane.showMessageDialog(this, e);
System.exit(-1);
}
I have a server which initially does this:-
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
for (;;) {
String cmdLine = br.readLine();
if (cmdLine == null || cmdLine.length() == 0)
break;
...
}
later it passes the socket to another class "foo"
This class wait for application specific messages.
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
appCmd=br.readLine();
My client sends this sequence:
"bar\n"
"how are u?\n"
"\n"
"passing it to foo\n"
"\n"
The problem is that sometimes "foo" does not get its response. It hangs in the readLine().
What is the chance that readLine() in the server is buffering up the data using the read ahead and "foo" class is getting starved?
If I add a sleep in the client side, it works. But what is the chance that it will always work?
"bar\n"
"how are u?\n"
"\n"
sleep(1000);
"passing it to foo\n"
"\n"
How to fix the problem? Appreciate any help on this regard.
eee's solution works perfectly. I was trying to read output from an SMTP conversation but it would block on:
while ((response = br.readLine()) != null) {
...Do Stuff
}
Changing to:
while (br.ready()) {
response = br.readLine();
...Do Stuff
}
I can read everything just fine. br is a BufferedReader object, BTW.
There is data already in the first BufferedReader (that has been read from the socket, and is no longer available from the socket), so pass the BufferedReader created in the first example to the class that reads the app specific messages, rather then creating a new BufferedReader from the socket.
I had the same problem and here is my solution:
try {
StringBuilder response = new StringBuilder();
response.append("SERVER -> CLIENT message:").append(CRLF);
//Infinite loop
while (true) {
//Checks wheather the stream is ready
if (in.ready()) {
//Actually read line
lastLineFromServer = in.readLine();
//If we have normal behavior at the end of stream
if (lastLineFromServer != null) {
response
.append(lastLineFromServer)
.append(CRLF);
} else {
return response.toString();
}
} else {//If stream is not ready
//If number of tries is not exceeded
if (numberOfTry < MAX_NUMBER_OF_TRIES) {
numberOfTry++;
//Wait for stream to become ready
Thread.sleep(MAX_DELAY_BEFORE_NEXT_TRY);
} else {//If number of tries is exeeded
//Adds warning that things go weired
response
.append("WARNING \r\n")
.append("Server sends responses not poroperly.\r\n")
.append("Response might be incomplete.")
.append(CRLF);
return response.toString();
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
return "";
}
The answer might be late but this is the simplest and latest answer in 2020, just use the simple way to receive the data from the socket server or client using the input stream read() method.
EOFException will be thrown when the client is disconnected or the server closed the connection.
private String waitForData() throws IOException {
String data = "";
do {
int c = inputStream.read();
if (c > -1) data += (char) c;
else throw new EOFException();
} while (inputStream.available() > 0);
return data;
}