香港专业教育学院一直试图在特定端口上使用ESP8266 wifi模块设置服务器。我已经完成了。

我现在想从中接收消息。
每当我使用socket.connect()连接时,我都能在esp8266中检测到它。但是我无法收到任何消息,服务器通过同一套接字发送。

我正在尝试在异步任务中的while循环内使用DataInputStream连续获取消息。请让我知道我的方法或代码是否错误!谢谢!

这是我的代码:

    package test.espclient;

import java.io.DataInputStream;
//import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;



public class MainActivity extends Activity {

    TextView textResponse;
    EditText editTextAddress, editTextPort;
    Button buttonConnect, buttonClear,buttonDiscon , buttonSendMsg;

    EditText welcomeMsg;

    Socket socket;

    boolean socketStatus = false;

    MyClientTask myClientTask;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        editTextAddress = (EditText) findViewById(R.id.address);
        editTextPort = (EditText) findViewById(R.id.port);
        buttonConnect = (Button) findViewById(R.id.connect);
        buttonClear = (Button) findViewById(R.id.clear);
        buttonDiscon = (Button) findViewById(R.id.closeSocket);
        buttonSendMsg = (Button) findViewById(R.id.sendMsg);
        textResponse = (TextView) findViewById(R.id.response);

        welcomeMsg = (EditText)findViewById(R.id.welcomemsg);

        buttonConnect.setOnClickListener(buttonConnectOnClickListener);

        buttonDiscon.setOnClickListener(buttonDisconnectOnCLickListener);

        //buttonSendMsg.setOnClickListener(sendMessage);

        buttonClear.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                textResponse.setText("");
            }
        });
    }

    OnClickListener buttonConnectOnClickListener = new OnClickListener() {

        @Override
        public void onClick(View arg0) {
      if(socketStatus)
          Toast.makeText(MainActivity.this,"Already talking to a Socket!! Disconnect and try again!", Toast.LENGTH_LONG).show();
      else {
          socket = null;
          String address = editTextAddress.getText().toString();
          int port = Integer.parseInt(editTextPort.getText().toString());
          String tMsg = welcomeMsg.getText().toString();

          if (address == null || port == 0)
              Toast.makeText(MainActivity.this, "Please enter valid address/port", Toast.LENGTH_LONG).show();

          else {
                           myClientTask = new MyClientTask(address,port,tMsg);
                          myClientTask.execute();

          } //else when no active socket conn. and credentials are validated.


      } //else when already active socket conn.
        }
    };

    OnClickListener buttonDisconnectOnCLickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            if (!socketStatus)
                Toast.makeText(MainActivity.this, "SOCKET Already Closed!!", Toast.LENGTH_SHORT).show();
            else {
                try {
                    onDisconnect();
                    if(myClientTask.isCancelled()) {
                        socket.close();
                        Toast.makeText(MainActivity.this, "Socket Closed!", Toast.LENGTH_SHORT).show();
                        socketStatus = false;
                    }
                    else
                    {
                        Toast.makeText(MainActivity.this, "Couldn't Disconnect! Pls try again!", Toast.LENGTH_SHORT).show();
                        socketStatus = true;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    Toast.makeText(MainActivity.this,e.toString(), Toast.LENGTH_SHORT).show();

                }
            }
        }
    };

//    OnClickListener sendMessage = new OnClickListener() {
//        @Override
//        public void onClick(View v) {
//            String msg = welcomeMsg.toString();
//            if(msg.equals(""))
//            {
//                Toast.makeText(MainActivity.this, "Message is empty!!!", Toast.LENGTH_SHORT).show();
//            }
//            else if(!socketStatus)
//            {
//                Toast.makeText(MainActivity.this, "Please Establish Socket Connection first!", Toast.LENGTH_SHORT).show();
//            }
//            else
//            {
//                MyClientTask myClientTask = new MyClientTask(editTextAddress
//                    .getText().toString(), Integer.parseInt(editTextPort
//                    .getText().toString()),
//                    msg);
//            myClientTask.execute();
//
//            }
//
//        }
//    };

    public void onDisconnect()
    {
        myClientTask.cancel(true);
    }

    public class MyClientTask extends AsyncTask<Void, String, Void> {

        String dstAddress;
        int dstPort;
        String response ="";
        String msgToServer;

        MyClientTask(String addr, int port, String msgTo) {
            dstAddress = addr;
            dstPort = port;
            msgToServer = msgTo;
            Log.w("MSG","Entering async task");
        }



        @Override
        protected Void doInBackground(Void... arg0) {


          //  DataOutputStream dataOutputStream = null;
            DataInputStream dataInputStream = null;

            try {
                socket = new Socket(dstAddress, dstPort);
                socketStatus = true;

               // dataOutputStream = new DataOutputStream(socket.getOutputStream());

//                if(msgToServer != null){
//                    dataOutputStream.writeUTF(msgToServer);
//                }
            }
            catch (UnknownHostException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
                response = "UnknownHostException: " + e.toString();
                socketStatus = false;
            }
            catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                response = "IOException: " + e.toString();
            }

            Log.w("MSG","Inside while loop for retrieving data");
           while(!isCancelled()){
               try {
                   dataInputStream = new DataInputStream(socket.getInputStream());
                   response = dataInputStream.readUTF();

                   if(!response.isEmpty())
                   {
                       publishProgress(response);
                       Log.w("Data:",response);
                   }

               } catch (IOException e) {
                   e.printStackTrace();
               }
           }


//                if (dataOutputStream != null) {
//                    try {
//                        dataOutputStream.close();
//                    } catch (IOException e) {
//                        // TODO Auto-generated catch block
//                        e.printStackTrace();
//                    }
//                }

                if (dataInputStream != null) {
                    try {
                        dataInputStream.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }

            try {
                Log.w("MSG","Stopping async task");
                socket.close();
                socketStatus = false;
            } catch (IOException e) {
                e.printStackTrace();
                socketStatus = true;
            }
            return null;
        }


        @Override
        protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);
            textResponse.setText(values[0]);
            Toast.makeText(MainActivity.this,"Server:"+values[0],Toast.LENGTH_LONG).show();
            Log.w("MSG","Updating with msg");
        }

        @Override
        protected void onPostExecute(Void result) {
            Log.w("MSG","On postExecute method..");
            textResponse.setText(response);
            super.onPostExecute(result);
        }

    }

}

UPDATE(16-12-15)我在doInBackground()下进行了以下更改。
最初,我使用DataInputStream,现在将其替换为BufferedReader。
在while循环部分下进行了更改,以不断检查套接字输入流。还添加了ESP8266代码以供引用。

现在,我可以接收从ESP8266发送的文本,但是只有通过CIPSEND cmd发送3或4条消息后,该文本才能到达。例如如果我发送“hi”,“hello”,“yo”,则在发送第三个单词后,我将所有单词一起接收为“hihelloyo”
我没有收到每封邮件,而是很晚才收到它。
我不确定到底是什么引起了这个问题。可能是缓冲区的大小?
如何解决呢?

修改后的代码:
     protected Void doInBackground(Void... arg0) {


          //  DataOutputStream dataOutputStream = null;
          //  DataInputStream dataInputStream = null;

            try {
                socket = new Socket(dstAddress, dstPort);
                socketStatus = true;
               // dataOutputStream = new DataOutputStream(socket.getOutputStream());

//                if(msgToServer != null){
//                    dataOutputStream.writeUTF(msgToServer);
//                }
            }
            catch (UnknownHostException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
                response = "UnknownHostException: " + e.toString();
                socketStatus = false;
            }
            catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                response = "IOException: " + e.toString();
            }


            Log.w("MSG","Inside while loop for retrieving data");

            while(!isCancelled() && socketStatus) {
                try {
//                  dataInputStream = new DataInputStream(socket.getInputStream());
//                      response = dataInputStream.readUTF();
                    BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    response = br.readLine();
                    if (!response.isEmpty()) {
                        publishProgress(response);
                        Log.w("Data:", response);
                    }


                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

ESP266代码
    #include <AltSoftSerial.h>
AltSoftSerial ESP8266 ;//(8,9)|Rx,Tx

int LED = 13;

boolean FAIL_8266 = false;

#define BUFFER_SIZE 128
char buffer[BUFFER_SIZE];

String ssid="\"SSID\"";
String pass="\"PASSWORD\"";

void clearESP8266SerialBuffer()
{
  Serial.println("= clearESP8266SerialBuffer() =");
  while (ESP8266.available() > 0) {
    char a = ESP8266.read();
    Serial.write(a);
  }
  Serial.println("==============================");
}



void sendHTTPResponse(int id, String content)
{
  String response;
  response = "HTTP/1.1 200 OK\r\n";
  response += "Content-Type: text/html; charset=UTF-8\r\n";
  response += "Content-Length: ";
  response += content.length();
  response += "\r\n";
  response +="Connection: close\r\n\r\n";
  response += content;

  String cmd = "AT+CIPSEND=";
  cmd += id;
  cmd += ",";
  cmd += response.length();

  Serial.println("--- AT+CIPSEND ---");
  sendESP8266Cmdln(cmd, 1000);

  Serial.println("--- data ---");
  sendESP8266Data(response, 1000);
}

boolean waitOKfromESP8266(int timeout)
{
  do{
    Serial.println("wait OK...");
    delay(1000);
    if(ESP8266.find("OK"))
    {
      return true;
    }

  }while((timeout--)>0);
  return false;
}

//Send command to ESP8266, assume OK, no error check
//wait some time and display respond
void sendESP8266Cmdln(String cmd, int waitTime)
{
  ESP8266.println(cmd);
  delay(waitTime);
  clearESP8266SerialBuffer();
}

//Basically same as sendESP8266Cmdln()
//But call ESP8266.print() instead of call ESP8266.println()
void sendESP8266Data(String data, int waitTime)
{
  ESP8266.print(data);
  delay(waitTime);
  clearESP8266SerialBuffer();
}

void adc()
{
  int ldr;

  for(int i=0;i<=3;i++)
  {
    ldr = analogRead(A0);
    sendESP8266Cmdln("AT+CIPSEND=0,5",1000);
    sendESP8266Cmdln(String(ldr),1000);
    delay(1000);
  }
}

void setup()
{
  Serial.begin(9600);
  ESP8266.begin(9600);
  pinMode(LED,OUTPUT);

  do{
  ESP8266.println("AT+RST");
    delay(1000);
    if(ESP8266.find("Ready"))
    {
      Serial.println("Module is ready");
      delay(1000);
      clearESP8266SerialBuffer();

      sendESP8266Cmdln("AT+CWMODE=1",1000);

      //Join Wifi network
      sendESP8266Cmdln("AT+CWJAP="+ssid+","+pass,6500);

      //Get and display my IP
      sendESP8266Cmdln("AT+CIFSR", 1000);

      //Set multi connections
      sendESP8266Cmdln("AT+CIPMUX=1", 1000);
      //Setup web server on port 80
      sendESP8266Cmdln("AT+CIPSERVER=1,3333",1000);

      Serial.println("Server setup finish");

      FAIL_8266 = false;
    }else{
      Serial.println("Module have no response.");
      delay(500);
      FAIL_8266 = true;
    }
  }while(FAIL_8266);

  digitalWrite(LED, HIGH);
  ESP8266.setTimeout(1000);
}
void loop() {

  // listen for communication from the ESP8266 and then write it to the serial monitor

     if(ESP8266.available()) // check if the esp is sending a message
  {
    String msg = ESP8266.readString();

    if(msg.substring(0,4)=="Link")
    Serial.println("Client connected!");

    else if(msg.substring(0,6)=="Unlink")
    Serial.println("Client Disconncected!!");


      else if(msg.substring(1,5)=="+IP")
      {
        Serial.println("Client says: "+msg.substring(9,14));
      }

      else
      {
       // Serial.println("Calling ADC.!");
        //adc();

       // Serial.println("Msg:"+msg.charAt(0)+msg.charAt(1)+msg.charAt(2)+msg.charAt(3));
       // Serial.println("Something recieved!: "+msg.substring(1,2));
        Serial.println("MSG:"+msg);
      }
  }

    // listen for user input and send it to the ESP8266
    if ( Serial.available() )       {  ESP8266.write( Serial.read() );  }
  }


//Clear and display Serial Buffer for ESP8266

更新(17-12-15):添加了图片以供引用
我的arduino串行窗口显示了AT + CIPSEND命令。
android - ESP8266 wifi服务器到android客户端-LMLPHP

手机上运行的应用程序的图片。
android - ESP8266 wifi服务器到android客户端-LMLPHP

最佳答案

关于此评论:



在上层应用层,来自TCPIP连接的数据以流的形式显示。将此流与定义明确的应用程序协议(protocol)(例如HTTP或telnet)结合使用,即可定义消息交换。在您的情况下,基本上Android方面不知道要接收多少数据。使用缓冲的阅读器后,您将得到缓冲的答案,而不是全部。

例如,在telnet协议(protocol)中,有控制命令。这样系统就可以继续工作了。

要解决您的情况:

  • 每条消息后关闭连接。 (这会减慢速度)
  • 实现基本的应用程序协议(protocol)。例如:实现一个消息框架:

  • 框架
    第一个字节:长度(此字节给出有效载荷的长度)
    2nd ... 255th字节:有效负载(这是实际消息)

    逻辑
    -发送方打包给出长度和有效负载的帧。
    -发送方发送数据
    ...
    -接收器查询可用字节。
    -当可用字节大于1时,仅接收1个字节,说它是'n'
    -'n'是整个帧的长度
    -从流中读取“n”个字节。如果EOF,则返回收到的内容。

    除此之外,您还可以实现控制命令。
    例如,您可能希望接收器关闭连接,以便您的框架可以是:

    字节1:长度
    字节2:命令(0 =无效,1 =关闭conn)
    字节3..n:有效负载

    逻辑
    -当接收器完成接收并且命令为1时,则关闭连接。

    关于android - ESP8266 wifi服务器到android客户端,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34274774/

    10-12 04:18