我有一个粒子光子微控制器通过热点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();
}
答案 0 :(得分:-1)
TCP保证的是,当您发送消息时 - 它将以正确的顺序出现,即使在此过程中被TCP堆栈拆分(请参阅TCP段号,其用作指示拆分消息部分的指示)属于哪个,以及以什么顺序)。因此,在您的情况下,您使用的所有内容都是:
server.write(buffer,sizeof(buffer));
没有仪表缓冲区有多大(当然,在TCP协议的限制范围内)保证以正确的顺序到达并完成。
通过TCP逐个发送多个缓冲区将为您提供有保证的传递或错误通知(如果有),但不会提供发送的消息的顺序。在协议级别下,这些数据包将包含不同的Sequence Numbers,因此将按照堆栈首选的顺序单独处理接收器的TCP堆栈。
我看到两个相对简单的事情可以在这里完成: