Use case:
NodeMCU connects to Android over TCP socket, then Android plays a sound, when user presses a button, which is connected to NodeMCU.
I couldn't find a way (that I could believe as reliable) to have Android's ServerSocket to notice a reset from NodeMCU client socket, right at once, when NodeMCU's socket is disconnected, or trying to reconnect.
This is my newbee socket code bellow, which I got it working also with the help of this forum. I tried to make it as short as possible when posting here, keeping only relevant parts, but if you need I can just drop all the code, so please let me know in case.
Please suggest me a way. Any other comment to help me understand more of sockets is very welcome.
I'd like to finally learn what sockets are!
public class MainActivity extends AppCompatActivity {
ServerSocket serverSocket;
Thread socketServerThread = null;
protected void onCreate(Bundle savedInstanceState) {
//...
Globals.snd = MediaPlayer.create(this, R.raw.bike_horn);// Globals - static class
//...
socketServerThread = new Thread(new SocketServerThread());
socketServerThread.start();
}
protected void onDestroy() {
if (serverSocket != null) {...//try close it}
}
private class SocketServerThread extends Thread {
//...
static final int SocketServerPORT = 8080;
public void run() {
Socket socket = null;
DataInputStream dataInputStream = null;
DataOutputStream dataOutputStream = null;
BufferedReader input = null;
try {
serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress(SocketServerPORT));
while (true) {
socket = serverSocket.accept();
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream = new DataOutputStream(socket.getOutputStream());
while(socket.isConnected()){
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
message = input.readLine();
if(message == null) break;
int x = Integer.valueOf(message);
if(x == 1) Globals.snd.start();
}
}
}catch (IOException e) {// print error stack
}finally{//close socket, dataInputStream, dataOutputStream
}
NodeMCU code:
#include <ESP8266WiFi.h>
//...variables defined
void setup() {
//...connect to wifi
client.connect(host, port);
}
void loop() {
if(!client.connected()){
if (!client.connect(host, port)) {
return;
}
}
while(digitalRead(beepBtnPin) == LOW && client.connected()){
client.println("2");
client.flush();
delay(500);
}
}
You should put all code after
socket = serverSocket.accept();
In a so called client thread. This is normally done to handle more clients at once.
The server then immediately waits for the next client to connect.
Related
I'm playing around ServerSocket on Android as the server part. I don't understand how it behaves. Here are what I tested :
A1. Instantiates a ServerSocket on Android
A2. ServerSocket sends "hello" to client
A3. Client can read the "hello" and can answer back to ServerSocket
A4. ServerSocket on Android receives the answer from the client
=> That works perfectly
Now I want the client to be the first to send a message to ServerSocket :
B1. Instantiates a ServerSocket on Android
B2. Client sends data to ServerSocket
B3. ServerSocket receives the data from client
B4. IMPOSSIBLE TO REPLY to the client
May that be a possible normal behaviour ?
Thanks
here is the source code
public void startServer()
{
log("startServer");
UUID uuid = UUID.randomUUID();
final String sessionId = uuid.toString().replace("-", "");
log("Session ID = " + sessionId);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
while (stopServer == false) {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(7777);
final Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
String strFromClient = "";
int i = 0;
while (i != -1) {
try {
i = inputStream.read();
if (i != -1)
strFromClient += (char) i;
}catch (Exception e){
break;
}
}
inputStream.close();
OutputStream outputStream = socket.getOutputStream();
String strToClient = "test";
byte[] cArray = strToClient.getBytes();
outputStream.write(cArray);
outputStream.flush();
outputStream.close();
socket.close();
serverSocket.close();
log("end server");
} catch (Exception e) {
//log(e.toString());
}
}
}
});
t.start();
}
Ok I found the solution ! The error was because the C# client was not sending the "-1" value (this is only triggered after closing a stream or stuff like that).
The solution is on the Android side, and the reading of the data from the client is now done as follow :
InputStream inputStream = socket.getInputStream();
String strFromClient = "";
int available = inputStream.available();
Log.d("intelsms", "available from client:" + available);
for (int i=0;i<available;i++){
int c = inputStream.read();
strFromClient+=(char)c;
}
I use the "available()" method in order to know how many bytes are available for reading from the client.
OUF !
I have created a server and client with Android and Arduino but I have a problem. Android reads only one time. Why? this is my code:
Client Android:
new Thread(new ClientThread()).start();
}
class ClientThread implements Runnable {
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName("192.168.1.240");
socket = new Socket(serverAddr, 8888);
if(socket == null)System.out.println("SOCKET NULL");
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),true);
inFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(true){
msgFromServer = inFromServer.readLine();
System.out.println(msgFromServer);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (socket != null) {
System.out.println("STOP SOCKET");
// close socket
}
}
}
}
Arduino Server:
void loop() {
YunClient client = server.accept();
sensorValue = analogRead(sensorPin);
String myString = String(sensorValue);
if (client) {
String command = "none";
command = client.readString();
Serial.println(sensorValue);
client.print(myString+"\n");
}
}
LOGCAT:
07-24 11:44:24.468: D/OpenGLRenderer(19693): Enabling debug mode 0
07-24 11:44:25.363: I/System.out(19693): 121
121 is the value from Arduino. But this is showing only once.
It works only once. I want receive data from the Arduino every second.
Thank you guys!
You need to take the accept out of the loop. otherwise it send a string and wait for another connect from client.
YunClient client = server.accept();
void loop() {
sensorValue = analogRead(sensorPin);
String myString = String(sensorValue);
if (client) {
String command = "none";
command = client.readString();
Serial.println(sensorValue);
client.print(myString+"\n");
}
}
Also, I don't see where the client sends something to the server. Instead of System.out.println should't it be out.println?
I'm trying to make a simple chatting app, using socket communication.
My goal is to send and receive text and images(from smartphone gallery) successfully.
Text part successful, but I'm having trouble with images.
I wrote a code using dataInput/OutputStream, and below is the code, which is establishing socket connection for image transfer, using bytearray(The app use different port for text and image).
class image_connection_thread extends Thread{
public boolean flag=true;
public void run(){
try{
socket2 = new Socket(Ip,port_img);
//Imgage Streams
img_output= new DataOutputStream(socket2.getOutputStream());
img_input= new DataInputStream(socket2.getInputStream());
while(flag)
{
///////////////////
img_input.readFully(byte_input);
**////// This line makes problem(App dies). But no exception message occurs. ////**
if(byte_input==null)
break;
image_received=BitmapFactory.decodeByteArray(byte_input, 0, byte_input.length);
Message Msg = new Message();
Msg.obj=image_received;
handler_img.sendMessage(Msg);
}
socket2.close();
}catch(Exception e)
{
tv_Text.append(e.getMessage()+"connection failed3\n");
}
}
}
While loop is to wait for input bytearray from server. Handler displays decoded bytearray on display.
--> img_input.readFully(byte_input); I think this line makes problem. I checked that handler works well, and with empty while block, App didn't die.
What would be the problem?
Server side code is shown below.(message threads are omitted)
public class server
{
public static void main(String[] args) {
Thread thread1=new port1_thread();
Thread thread2=new port2_thread();
thread1.start();
thread2.start();
}
}
class port2_thread extends Thread
{
ServerSocket serversocket = null;
public void run()
{
try
{
serversocket = new ServerSocket(9003);
while(true)
{
Socket socket = serversocket.accept();
Thread thread= new image_thread(socket);
thread.start();
}
}catch(Exception e){System.out.println("1-2"+e.getMessage());}
}
}
class image_thread extends Thread
{
static ArrayList<DataOutputStream> list2 = new ArrayList<DataOutputStream>();
Socket socket;
DataOutputStream output2 = null;
image_thread(Socket socket)//constructor
{
this.socket=socket;
try //data output stream
{
output2 = new DataOutputStream(socket.getOutputStream());
list2.add(output2);
}
catch (Exception e)
{
System.out.println("22"+e.getMessage());
}
}
public void run()
{
try
{
//output2= new DataOutputStream(socket.getOutputStream());
DataInputStream input2=new DataInputStream(socket.getInputStream());
while(true)
{
for (DataOutputStream output2 : list2)
{
byte[] b = new byte[1024];
input2.readFully(b);
output2.write(b);
output2.flush();
}
}
}catch(Exception e){System.out.println("33"+e.getMessage());}
finally
{
list2.remove(output2);
try
{
socket.close();
}catch(Exception ignored){}
}
}
}
I am a beginner in developing the java applications. I'm making a chat application on android. I use a thread to serve the client who comes in, but when the client has connected to the server I can not retrieve the data contained in the socket, but when a client connection is lost, data can be displayed. I use the ReadLine method to read data from the socket.
This is the program code on the server side:
package server;
import java.net.*;
import java.io.*;
import java.util.Vector;
import com.sun.org.apache.bcel.internal.generic.NEW;
public class Server {
public static void main(String[] args)throws IOException, InstantiationException,
IllegalAccessException {
ServerSocket servsocket = null;
Socket sock = null;
byte[] bytebuffer = new byte[512];
try {
System.out.println("SERVER IS RUNNING...");
servsocket = new ServerSocket(28000);
while(true){
sock = servsocket.accept();
System.out.println(servsocket.isBound());
System.out.println("Port "+servsocket+" Ready!!!");
System.out.println("Accept connection requests from " + sock);
System.out.println("From CLIENT "+sock.getInetAddress()+ " and PORT " +
sock.getPort());
ChatThread thread = new ChatThread(sock);
System.out.println("Thread is running");
thread.run();
}
} catch (IOException ioe) {
System.out.println(ioe);
}
finally{
try {
servsocket.close();
} catch (IOException ioe) {
System.out.println(ioe);
}
}
}
}
class ChatThread extends Thread{
static Vector<ChatThread> chatthread = new Vector<ChatThread>(10);
private Socket sock;
private BufferedReader in ;
private PrintWriter out;
public ChatThread (Socket socket) throws IOException {
this.sock = socket;
in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(
new OutputStreamWriter(socket.getOutputStream()));
byte[] bytebuffer = new byte[512];
int receivemssg;
}
public void run(){
int recvMsgSize;
byte[] bytebuffer = new byte[512];
String readsocket;
try {
readsocket = in.readLine();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Below the display on the server side when the program starts. I tried to send the word "Hello ...." from the client side. Can be seen that the thread is not running.
Server is running...
true
Port ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=28000] Ready!!!
Accept connection requests fromSocket[addr=/172.17.231.254,port=3567,localport=28000]
From CLIENT /172.17.231.254 and PORT 3567
Thread is Running...
When I replace the readline method on a thread with getInputStream the thread can be run from the client and the message can be displayed. This is the code that I enter the thread to replace the readline method that I used before.
public ChatThread (Socket socket) throws IOException {
this.sock = socket;
in = sock.getInputStream();
out = sock.getOutputStream();
byte[] bytebuffer = new byte[512];
int receivemssg;
}
public void run(){
int recvMsgSize;
byte[] bytebuffer = new byte[512];
System.out.println("Thread is Running...");
String masuk = new String(bytebuffer);
System.out.println(bytebuffer);
System.out.println(in.toString());
System.out.println("thread successfully executed !!!");
synchronized (chatthread) {
chatthread.addElement(this);
}
try {
while ((recvMsgSize = in.read(bytebuffer)) != -1) {
out.write(bytebuffer, 0, recvMsgSize);
System.out.println("The length of a character is received and returned "+bytebuffer.length);
}
} catch (IOException e) {
System.out.println(e);
}
}
}
but the next problem is I can not bring up the contents of a socket in a string / text that appears is as follows:
Port ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=28000] Siap!!!
Accept connection requests fromSocket[addr=/172.17.231.254,port=3577,localport=28000]
From CLIENT /172.17.231.254 and PORT 3577
Thread is Running...
[B#7c6768
java.net.SocketInputStream#1690726
thread successfully executed !!!
The length of a character is received and returned 512
Please Help me, thanks :) GBU guys...
See the developer docmentation
public final String readLine ()
Since: API Level 1
Returns a string containing the next line of text available from this stream.
A line is made of zero or more characters followed by '\n', '\r', "\r\n"
or the end of the stream. The string does not include the newline sequence.
readLine() will block and not return until it either sees an end-of-line condition such as a newline character, or the end of the stream is reached, which is probably what happens when the connection is lost.
If you want to use readLine() you need to send "Hello....\n" or otherwise append a terminating character for readLine() to see.
On Android I tried to implement a simple TCP Listener Thread (or copied it from anywhere). It should simply wait for a Text and then do something. The Text is sent, this part works, but this listener-Thread doesn´t even create the Socket for listening correctly.
Has anyone an Idea, whats wrong or another simple approach for me?
The text is defined b myself and not html. I only found much too complicated http-handlers.
import java.lang.*;
import java.io.*;
import java.net.*;
public class Client implements Runnable {
public static void main(String args[]) {
System.out.print("Listening Thread started\n");
try {
Socket skt = new Socket("localhost", 2999);
BufferedReader in = new BufferedReader(new
InputStreamReader(skt.getInputStream()));
System.out.print("Received string: '");
while (!in.ready()) {}
System.out.println(in.readLine()); // Read one line and output it
System.out.print("'\n");
in.close();
}
catch(Exception e) {
System.out.print("Whoops! It didn't work!\n");
System.err.println(e);
}
}
public Client () {
}
#Override
public void run() {
// TODO Auto-generated method stub
main(null);
}
}
The code you showed is used to create a client socket, not a server socket. see below an example of TCP server socket, taken from SystemBash:
class TCPServer
{
public static void main(String argv[]) throws Exception
{
String clientSentence;
String capitalizedSentence;
ServerSocket welcomeSocket = new ServerSocket(6789);
while(true)
{
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient =
new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
clientSentence = inFromClient.readLine();
System.out.println("Received: " + clientSentence);
capitalizedSentence = clientSentence.toUpperCase() + '\n';
outToClient.writeBytes(capitalizedSentence);
}
}
}