2016-07-08 70 views
0

我想從我的Android應用程序中的TCP/IP數據包中提取確認編號。我將原始數據以字節形式存儲爲ByteBuffer讀取TCP確認編號

作爲一個例子,讓我們看看下面的TCP/IP分組:(這是字節的原始TCP數據)

140 174 20 102 249 178 241 231 **238 84 109 14** 128 24 1 91 240 54 0 0 1 1 8 10 0 43 86 97 209 144 51 108 0 0 35 

粗體字節表示確認號,但是當我嘗試將其轉換到intlong,我得到一個負數。這就是我最初在那裏abc試過了,d是代表應答號的4個字節:

this.ackNumber = ((a & 0xFF) << 24) + ((b & 0xFF) << 16) + ((c & 0xFF) << 8) + (d & 0xFF);

看到那之後,沒有工作,我試圖做一步一步來像這樣:

byte a = packet.get(); // -18 
byte b = packet.get(); // 84 
byte c = packet.get(); // 109 
byte d = packet.get(); // 14 

Log.e(TAG, "A: " + a + " B: " + b + " C: " + c + " D: " + d); 

int ia = a & 0xFF; // 238 
int ib = b & 0xFF; // 84 
int ic = c & 0xFF; // 109 
int id = d & 0xFF; // 14 

Log.e(TAG, "IA: " + ia + " IB: " + ib + " IC: " + ic + " ID: " + id); 

ia = ia << 24; // -301989888 
ib = ib << 16; // 5505024 
ic = ic << 8; // 27904 
id = id << 0; // 14 

Log.e(TAG, "LIA: " + ia + " LIB: " + ib + " LIC: " + ic + " LID: " + id); 

long la = (long)ia & 0x00000000FF000000; // -301989888 
long lb = ib & 0x00FF0000;    // 5505024 
long lc = ic & 0x0000FF00;    // 27904 
long ld = id & 0x000000FF;    // 14 

Log.e(TAG, "ALIA: " + la + " ALIB: " + lb + " ALIC: " + lc + " ALID: " + ld); 

此代碼仍返回不正確的數字。我究竟做錯了什麼?

編輯:

我設法由十六進制這樣之後增加的L簡單地得到正確的數字:

long la = (long)ia & 0x00000000FF000000L;

合併他們這樣兩種工作方式:

Log.e(TAG, "Ack: " + (la + lb + lc + ld) + " Ack: " + (la | lb | lc | ld));

+0

沒有理由爲什麼TCP序列號不能爲負數。這是一個。 – EJP

+0

序列號不能小於零。根據這個問題的答案http://stackoverflow.com/a/2672750/4893507當他們達到最大值時,他們重置爲0. – TychoTheTaco

+0

最大值是2^32-1,而不是2^31-1。 TCP序列號[佔據未簽名的32位空間](https://tools.ietf.org/html/rfc793#page-24)。這個以0x80000000開頭,所以*就Java'int'而言*是否定的。 – EJP

回答

0

如果你想要我將掩碼字節和移位字節寫入intlong,則應使用邏輯OR運算符|,而不是邏輯AND &

而且,使用int的版本將產生一個負數,因爲int s是用Java簽名的,而高位字節大於127,因此它的最高有效位設置爲1,這使得整個int爲負數-補充。