Android TCP连接无法接收数据包

时间:2016-08-10 12:48:50

标签: android tcp wifi microcontroller

我有一个粒子光子微控制器通过热点WiFi网络将TCP数据包发送到Android手机。微控制器充当服务器,手机充当客户端。

然而,尽管通过tcp传输了信息,但是电话却无法接收到一些(但不是全部)数据包。我的理解是,这不会发生 - 我错了,还是我能做些什么来纠正这个?

微控制器代码:

// This #include statement was automatically added by the Particle IDE.
#include "databuffer5.h"

// This #include statement was automatically added by the Particle IDE.
#include "databuffer7.h"





const unsigned int localPort = 10000;
IPAddress remoteIP(a, b, c, d);
// An TCP instance to let us send and receive packets over wifi
TCPServer server = TCPServer(localPort);
TCPClient client;

// UDP Port used for two way communication


short msg_count = 0;

const int adcPin = A0; 


int byteBuffer;

unsigned long loopTimer;

const int packetSize = 40;  //number of bytes in packet - 10 ints with 4 bytes each
byte buffer[packetSize]; 

int j = 0;
int dataCount = 0;  //dummy data that increments every loop point, to measure packet contiuity 
                    //(creates a line with slope 1 as data)





void setup() {
  // start the UDP
  server.begin();


  // Print your device IP Address via serial
  Serial.begin(9600);
  Serial.println(WiFi.localIP()); 
  //Serial.println(System.ticksPerMicrosecond());   //returns 120, ie 120MHz


}



void loop() 
{
  if (client.connected())
  {
    loopTimer = millis();  //mark start time of loop

      for (int i = 0; i < 10; i++)
      {



          //for testing connection
          byteBuffer = i+j*10;

          buffer[i*4]   = ( (byteBuffer  >> 24) & 0xFF);     //take upper 8 bits  
          buffer[i*4+1] = ( (byteBuffer  >> 16) & 0xFF);     //take middle upper 8 bits  
          buffer[i*4+2] = ( (byteBuffer  >> 8 ) & 0xFF);     //take middle lower 8 bits 
          buffer[i*4+3] = (  byteBuffer         & 0xFF);     //take lower 8 bits
          dataCount++;

          if (i != 9) 
          {
              while(millis() < (loopTimer+10*(i+1)));  //ie do nothing for 10 ms (time is in ms, want to delay by exactly 10ms for each loop)

                                                        //goal here is to sample every 10ms, by delaying for the remaining time 
                                                        //dont delay here for the last sample, as the udp packet will take time
                                                        //delay after instead
          }

      }


      server.write(buffer, sizeof(buffer)); //using sizeof on a byte array so dont need to scale (ie scaling factor is 1)
      j++; 
      if (j < 0){j = 0;}
      while(millis() < (loopTimer+10*10));  //delay till 100ms after loops started
   }
   else 
   {
       client = server.available();
   }
}

Android(客户端)代码:

async_udp = new AsyncTask<Void, int[], Void>() {
            @Override
            protected Void doInBackground(Void... params) {


                byte b1[];
                b1 = new byte[100];

                while (serverActive) {
                    Socket socket = null;   //previously this was DatagramSocket (UDP) - no Socket (TCP)
                    try {
                        //DatagramSocket s = new DatagramSocket(server_port, server_ip);
                        socket = new Socket(server_ip, server_port);
                        socket.setPerformancePreferences(1, 2, 2);

                        InputStream socketStream = socket.getInputStream();



                        DatagramPacket p1 = new DatagramPacket(b1, b1.length);


                        ByteBuffer wrapped;
                        int data[] = new int[10+1];  //first number for message data, second is for the message number

                        while (serverActive)   //TODO include shutdown function
                        {
                            while (socketStream.available() < 39){}

                            socketStream.read(b1, 0, 40);

                            //packet structure is a char containing message number, and 10  shorts (2 bytes) containing data points (between 0 and 4096)


                            wrapped = ByteBuffer.wrap(Arrays.copyOfRange(b1, 0, 40)); // extract 40 bytes to convert to 10 ints
                            for (int i = 0; i < 10; i++) {
                                data[i] = wrapped.getInt();
                            }


                            String str = data.toString();

                            server_port = p1.getPort();
                            server_ip = p1.getAddress();


                            String str_msg = "RECEIVED FROM CLIENT IP =" + server_ip + " port=" + server_port + " message no = " + b1[0] +
                                    " data=" + str;  //first character is message number


                            statusText = str_msg;
                            publishProgress(data);

                        }
                        socketStream.close();
                        socket.close();

                    } catch (SocketException e) {
                        if (socket != null) {}

                        //status.append("Error creating socket");
                        statusText = (" Error creating socket");   //this doesn't work!
                    } catch (IOException e) {
                        //status.append("Error recieving packet");
                        statusText = (" Error receiving packet");  //this doesn't work!
                    }
                    try{
                    Thread.sleep(100, 0);  //sleep for 10ms if no wifi lock is found, to stop battery being silly
                    } catch(Exception e){
                        e.printStackTrace();
                    }
                }

                return null;
            }

            protected void onProgressUpdate(int[]... data1)
            {
                super.onProgressUpdate(data1);
                int data[] = data1[0];

                //send data to graph

                for (int i = 0; i < 9; i++)
                {
                    series.appendData(new DataPoint(lastDataX++, data[i]), false, graphPointsMax);
                    //append 9 points to graph, but only redraw the grpah on the 10th
                }
                series.appendData(new DataPoint(lastDataX++, data[9]), true, graphPointsMax);



            }

        };

        if (Build.VERSION.SDK_INT >= 11)
        {
            async_udp.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        }
        else
        {
            async_udp.execute();
        }

1 个答案:

答案 0 :(得分:-1)

TCP保证的是,当您发送消息时 - 它将以正确的顺序出现,即使在此过程中被TCP堆栈拆分(请参阅TCP段号,其用作指示拆分消息部分的指示)属于哪个,以及以什么顺序)。因此,在您的情况下,您使用的所有内容都是:

  

server.write(buffer,sizeof(buffer));

没有仪表缓冲区有多大(当然,在TCP协议的限制范围内)保证以正确的顺序到达并完成。

通过TCP逐个发送多个缓冲区将为您提供有保证的传递或错误通知(如果有),但不会提供发送的消息的顺序。在协议级别下,这些数据包将包含不同的Sequence Numbers,因此将按照堆栈首选的顺序单独处理接收器的TCP堆栈。

我看到两个相对简单的事情可以在这里完成:

  1. 尝试尽你所能(尽管不是真正的实用方法)
  2. 每次发送缓冲区时,都会引入计数器并递增。将计数器与缓冲区一起放入并检查接收方的优先级(电话,在您的情况下)。