android dhcp 服务器,安卓通过DHCP协议获取IP地址的过程
安卓通过DHCP协议的DORA Discovery发现 Offer提供 Request请求 Ack确认 获取IP地址的过程
安卓N之前 5.0 6.0通过 android_net_utils_runDhcp 方法运行 /system/bin/dhcpcd 获取ip地址
安卓N之后 N不要了runDhcpcd(),而是通过DhcpClient
DhcpClient是通过framework发送dhcpcd协议的UDP请求包直接去拿IP,不再使用开源的dhcpcd
google还用了一个状态机 IpManager 来管理dhcpcd成功还是失败等状态,
将ip赋值给IpConfiguration和LinkProperties传递到上层的framework
/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java
// 当WifiStateMachine状态机进入状态ObtainingIpState时 获取IP地址
class ObtainingIpState extends State {
@Override
public void enter() {
mIpManager.startProvisioning(IpManager.ProvisioningConfiguration prov); //启动获取IP地址
}
}
ObtainingIpState所在状态机
/frameworks/base/services/net/java/android/net/ip/IpManager.java
class StartedState extends State {} IpManager中的三个状态机
class StoppedState extends State {}
class StoppingState extends State {}
public void startProvisioning(ProvisioningConfiguration req) {
getNetworkInterface();
mCallback.setNeighborDiscoveryOffload(true);
// 给初始化的状态机 StoppedState 发送消息CMD_START
sendMessage(CMD_START, new ProvisioningConfiguration(req));
}
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
========================================================================
class StoppedState extends State {
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
…..
case CMD_START:
mConfiguration = (ProvisioningConfiguration) msg.obj;
// 接收到 CMD_START 会进行状态的切换,调用 StartedState的enter()方法
transitionTo(mStartedState);
break;
…..
}
==========================================
class StartedState extends State {
void enter(){
if(startIPv4()) // 状态 StartedState 的enter 进入方法,调用startIPv4()函数
private boolean startIPv4() {
// If we have a StaticIpConfiguration attempt to apply it and handle the result accordingly.
if (mConfiguration.mStaticIpConfig != null) { // 如果有静态IP
if (setIPv4Address(mConfiguration.mStaticIpConfig.ipAddress)) {
handleIPv4Success(new DhcpResults(mConfiguration.mStaticIpConfig));
} else {
if (VDBG) { Log.d(mTag, "onProvisioningFailure()"); }
recordMetric(IpManagerEvent.PROVISIONING_FAIL);
mCallback.onProvisioningFailure(new LinkProperties(mLinkProperties));
return false;
}
} else {
// Start DHCPv4. 创建DhcpClient
mDhcpClient = DhcpClient.makeDhcpClient(mContext, IpManager.this, mInterfaceName);
mDhcpClient.registerForPreDhcpNotification(); // mRegisteredForPreDhcpNotification = true
//接收前面发过来的mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP);跟着跳转到DhcpInitState:
mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP); // 发送CMD_START_DHCP消息
if (mConfiguration.mProvisioningTimeoutMs > 0) {
final long alarmTime = SystemClock.elapsedRealtime() +
mConfiguration.mProvisioningTimeoutMs;
mProvisioningTimeoutAlarm.schedule(alarmTime); // 在36秒后启动timeout超时操作
}
}
return true;
}
private boolean setIPv4Address(LinkAddress address) {
final InterfaceConfiguration ifcg = new InterfaceConfiguration();
ifcg.setLinkAddress(address);
try {
final INetworkManagementService mNwService.setInterfaceConfig(mInterfaceName, ifcg);
if (VDBG) Log.d(mTag, "IPv4 configuration succeeded");
} catch (IllegalStateException | RemoteException e) {
Log.e(mTag, "IPv4 configuration failed: ", e);
return false;
}
return true;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
==========================================
//接收前面发过来的mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP);跟着跳转到 DhcpInitState:
mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP); // 发送CMD_START_DHCP消息
/frameworks/base/services/net/java/android/net/dhcp/DhcpClient.java
class DhcpInitState extends PacketRetransmittingState {
public DhcpInitState() {
super();
}
1
2
3
4
5
1
2
3
4
5
//进入状态时启动一次startNewTransaction
//DORA Discover发现 Offer提供 Request请求 ACK确认 开始Discovery 发现?
@Override
public void enter() {
super.enter(); // 调用父类的 enter 方法中
startNewTransaction();
}
protected boolean sendPacket() {
return sendDiscoverPacket(); // 发送 DiscoverPacket 发现包
}
protected void receivePacket(DhcpPacket packet) {
if (!isValidPacket(packet)) return;
if (!(packet instanceof DhcpOfferPacket)) return;
mOffer = packet.toDhcpResults();
if (mOffer != null) {
Log.d(TAG, "Got pending lease: " + mOffer);
transitionTo(mDhcpRequestingState); // 接收到了 Offer包 接下来发送 Request 请求包
}
}
}
private void startNewTransaction() {
mTransactionId = mRandom.nextInt(); // 传输包的id号?
mTransactionStartMillis = SystemClock.elapsedRealtime();
}
PacketRetransmittingState
abstract class PacketRetransmittingState extends LoggingState {
private int mTimer;
protected int mTimeout = 0;
@Override
public void enter() {
super.enter();
initTimer();
maybeInitTimeout();
sendMessage(CMD_KICK); // 发送消息 CMD_KICK
}
@Override
public boolean processMessage(Message message) {
super.processMessage(message);
switch (message.what) {
case CMD_KICK:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 调用了 sendPacket()抽象方法 所以就是之前的DhcpInitState的具体的实现 sendPacket()
sendPacket();
scheduleKick();
return HANDLED;
case CMD_RECEIVED_PACKET:
receivePacket((DhcpPacket) message.obj);
return HANDLED;
case CMD_TIMEOUT:
timeout();
return HANDLED;
default:
return NOT_HANDLED;
}
}
public void exit() {
mKickAlarm.cancel();
mTimeoutAlarm.cancel();
}
}
abstract protected boolean sendPacket();
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
abstract protected void receivePacket(DhcpPacket packet);
class DhcpInitState extends PacketRetransmittingState {
protected boolean sendPacket() {
return sendDiscoverPacket(); // 发送 DiscoverPacket 发现包
}
private boolean sendDiscoverPacket() {
ByteBuffer packet = DhcpPacket.buildDiscoverPacket(
DhcpPacket.ENCAP_L2, mTransactionId, getSecs(), mHwAddr,
DO_UNICAST, REQUESTED_PARAMS); // 创建 ByteBuffer的UDP包
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
return transmitPacket(packet, “DHCPDISCOVER”, DhcpPacket.ENCAP_L2, INADDR_BROADCAST); // 发送
}
}
private boolean transmitPacket(ByteBuffer buf, String description, int encap, Inet4Address to) {
try {
if (encap == DhcpPacket.ENCAP_L2) {
if (DBG) Log.d(TAG, "Broadcasting " + description);
// 送这里发送出去
Os.sendto(mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr);
} else if (encap == DhcpPacket.ENCAP_BOOTP && to.equals(INADDR_BROADCAST)) {
if (DBG) Log.d(TAG, "Broadcasting " + description);
// N.B.: We only need this codepath because DhcpRequestPacket
// hardcodes the source IP address to 0.0.0.0. We could reuse
// the packet socket if this ever changes.
Os.sendto(mUdpSock, buf, 0, to, DhcpPacket.DHCP_SERVER);
} else {
if (DBG) Log.d(TAG, String.format("Unicasting %s to %s",description, Os.getpeername(mUdpSock)));
Os.write(mUdpSock, buf);
}
} catch(ErrnoException|IOException e) {
Log.e(TAG, "Can't send packet: ", e);
return false;
}
return true;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
==================================================================
另外一边有一个接收线程ReceiveThread run(),一直在收dhcp server的的数据包。
class ReceiveThread extends Thread {
private final byte[] mPacket = new byte[DhcpPacket.MAX_LENGTH];
private volatile boolean mStopped = false;
public void halt() {
mStopped = true;
closeSockets(); // Interrupts the read() call the thread is blocked in.
}
@Override
public void run() {
if (DBG) Log.d(TAG, "Receive thread started");
while (!mStopped) {
int length = 0; // Or compiler can't tell it's initialized if a parse error occurs.
try {
//读取DHCP服务发出的OFFER提交包
length = Os.read(mPacketSock 【FileDescriptor】, mPacket, 0, mPacket.length);
DhcpPacket packet = null;
packet = DhcpPacket.decodeFullPacket(mPacket, length, DhcpPacket.ENCAP_L2);
if (DBG) Log.d(TAG, "Received packet: " + packet);
sendMessage(CMD_RECEIVED_PACKET, packet); // 发送接收到消息 CMD_RECEIVED_PACKET
} catch (IOException|ErrnoException e) {
if (!mStopped) {
Log.e(TAG, "Read error", e);
DhcpErrorEvent.logReceiveError(mIfaceName);
}
} catch (DhcpPacket.ParseException e) {
Log.e(TAG, "Can't parse packet: " + e.getMessage());
if (PACKET_DBG) {
Log.d(TAG, HexDump.dumpHexString(mPacket, 0, length));
}
DhcpErrorEvent.logParseError(mIfaceName, e.errorCode);
}
}
if (DBG) Log.d(TAG, "Receive thread stopped");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
}
abstract class PacketRetransmittingState extends LoggingState {
@Override
public boolean processMessage(Message message) {
super.processMessage(message);
switch (message.what) {
case CMD_RECEIVED_PACKET:
receivePacket((DhcpPacket) message.obj); // 调用子类具体实现的receivePacket 方法
return HANDLED;
default:
return NOT_HANDLED;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class DhcpInitState extends PacketRetransmittingState {
class DhcpInitState extends PacketRetransmittingState {
protected void receivePacket(DhcpPacket packet) { // 完成 DORA 中的 Offer的阶段
if (!isValidPacket(packet)) return;
if (!(packet instanceof DhcpOfferPacket)) return;
mOffer = packet.toDhcpResults();
if (mOffer != null) {
Log.d(TAG, "Got pending lease: " + mOffer);
// 接收到了来自DHCP服务器的OFFER包,切换状态到 DhcpRequestingState 并进入到 enter() 方法
transitionTo(mDhcpRequestingState);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
1
2
3
4
5
6
7
8
9
10
11
12
13
14
}
===================================================================
class DhcpRequestingState extends PacketRetransmittingState { // 进入到父类的enter 方法
public DhcpRequestingState() {
mTimeout = DHCP_TIMEOUT_MS / 2;
}
public void enter() {// 进入到父类的enter 方法
super.enter();
initTimer();
maybeInitTimeout();
sendMessage(CMD_KICK); // 再次发送 CMD_KICK 消息
}
public boolean processMessage(Message message) {
super.processMessage(message);
switch (message.what) {
case CMD_KICK: // 收到 CMD_KICK 消息
sendPacket(); // 发送包方法,此时调用的是具体子类 DhcpRequestingState的发送方法
scheduleKick();
return HANDLED;
default:
return NOT_HANDLED;
}
}
// 发送请求 完成 DORA中的 Request的阶段
// 此时 继续在接收线程中等待接收来自服务器的ACK DHCP数据包
protected boolean sendPacket() {
return sendRequestPacket(
INADDR_ANY, // ciaddr
(Inet4Address) mOffer.ipAddress.getAddress(), // DHCP_REQUESTED_IP
(Inet4Address) mOffer.serverAddress, // DHCP_SERVER_IDENTIFIER
INADDR_BROADCAST); // packet destination address
}
protected void receivePacket(DhcpPacket packet) {
if (!isValidPacket(packet)) return;
if ((packet instanceof DhcpAckPacket)) {
DhcpResults results = packet.toDhcpResults();
if (results != null) {
setDhcpLeaseExpiry(packet);
acceptDhcpResults(results, "Confirmed");
transitionTo(mConfiguringInterfaceState);
}
} else if (packet instanceof DhcpNakPacket) {
// TODO: Wait a while before returning into INIT state.
Log.d(TAG, "Received NAK, returning to INIT");
mOffer = null;
transitionTo(mDhcpInitState);
}
}
private boolean sendRequestPacket(
Inet4Address clientAddress, Inet4Address requestedAddress,
Inet4Address serverAddress, Inet4Address to) {
// TODO: should we use the transaction ID from the server?
final int encap = INADDR_ANY.equals(clientAddress)
? DhcpPacket.ENCAP_L2 : DhcpPacket.ENCAP_BOOTP;
ByteBuffer packet = DhcpPacket.buildRequestPacket(
encap, mTransactionId, getSecs(), clientAddress,
DO_UNICAST, mHwAddr, requestedAddress,
serverAddress, REQUESTED_PARAMS, null);
String serverStr = (serverAddress != null) ? serverAddress.getHostAddress() : null;
String description = "DHCPREQUEST ciaddr=" + clientAddress.getHostAddress() +
" request=" + requestedAddress.getHostAddress() +
" serverid=" + serverStr;
return transmitPacket(packet, description, encap, to); // 发送数据包
}
return transmitPacket(packet, "DHCPDISCOVER", DhcpPacket.ENCAP_L2, INADDR_BROADCAST); // 发送
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
}
private boolean transmitPacket(ByteBuffer buf, String description, int encap, Inet4Address to) {
try {
if (encap == DhcpPacket.ENCAP_L2) {
if (DBG) Log.d(TAG, "Broadcasting " + description);
// 送这里发送出去 真正发送
Os.sendto(mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr);
} else if (encap == DhcpPacket.ENCAP_BOOTP && to.equals(INADDR_BROADCAST)) {
if (DBG) Log.d(TAG, "Broadcasting " + description);
// N.B.: We only need this codepath because DhcpRequestPacket
// hardcodes the source IP address to 0.0.0.0. We could reuse
// the packet socket if this ever changes.
Os.sendto(mUdpSock, buf, 0, to, DhcpPacket.DHCP_SERVER);
} else {
if (DBG) Log.d(TAG, String.format("Unicasting %s to %s",description, Os.getpeername(mUdpSock)));
Os.write(mUdpSock, buf);
}
} catch(ErrnoException|IOException e) {
Log.e(TAG, "Can't send packet: ", e);
return false;
}
return true;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
另外一边有一个接收线程ReceiveThread run(),一直在收dhcp server的的数据包。
class ReceiveThread extends Thread {
private final byte[] mPacket = new byte[DhcpPacket.MAX_LENGTH];
private volatile boolean mStopped = false;
public void halt() {
mStopped = true;
closeSockets(); // Interrupts the read() call the thread is blocked in.
}
@Override
public void run() {
if (DBG) Log.d(TAG, "Receive thread started");
while (!mStopped) {
int length = 0; // Or compiler can't tell it's initialized if a parse error occurs.
try {
//读取DHCP服务发出的ACK确认包
length = Os.read(mPacketSock 【FileDescriptor】, mPacket, 0, mPacket.length);
DhcpPacket packet = null;
packet = DhcpPacket.decodeFullPacket(mPacket, length, DhcpPacket.ENCAP_L2);
if (DBG) Log.d(TAG, "Received packet: " + packet);
// 发送接收到消息 CMD_RECEIVED_PACKET 此时处理的状态是 DhcpRequestingState
sendMessage(CMD_RECEIVED_PACKET, packet);
} catch (IOException|ErrnoException e) {
if (!mStopped) {
Log.e(TAG, "Read error", e);
DhcpErrorEvent.logReceiveError(mIfaceName);
}
} catch (DhcpPacket.ParseException e) {
Log.e(TAG, "Can't parse packet: " + e.getMessage());
if (PACKET_DBG) {
Log.d(TAG, HexDump.dumpHexString(mPacket, 0, length));
}
DhcpErrorEvent.logParseError(mIfaceName, e.errorCode);
}
}
if (DBG) Log.d(TAG, "Receive thread stopped");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
}
// 处理消息 CMD_RECEIVED_PACKET 对应的数据包是 ACK数据包 UDP
class DhcpRequestingState extends PacketRetransmittingState {
public boolean processMessage(Message message) {
super.processMessage(message);
switch (message.what) {
case CMD_RECEIVED_PACKET:
receivePacket((DhcpPacket) message.obj); //DhcpRequestingState处理接收到的数据包
return HANDLED;
default:
return NOT_HANDLED;
}
}
protected void receivePacket(DhcpPacket packet) {
if (!isValidPacket(packet)) return;
if ((packet instanceof DhcpAckPacket)) {
DhcpResults results = packet.toDhcpResults();
if (results != null) {
setDhcpLeaseExpiry(packet);
//这里会调用notifySuccess,发送CMD去通知IpManager说,IP拿到了 分析 acceptDhcpResults
acceptDhcpResults(results, "Confirmed"); // 分叉
//进入新的状态 ConfiguringInterfaceState enter方法
transitionTo(mConfiguringInterfaceState);
}
} else if (packet instanceof DhcpNakPacket) { // 收到的是NACK 解决数据包的话
// TODO: Wait a while before returning into INIT state.
Log.d(TAG, "Received NAK, returning to INIT");
mOffer = null;
transitionTo(mDhcpInitState);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
}
//这里会调用notifySuccess,发送CMD去通知IpManager说,IP拿到了 分析 acceptDhcpResults
acceptDhcpResults(results, “Confirmed”);
private void acceptDhcpResults(DhcpResults results, String msg) {
mDhcpLease = results;
mOffer = null;
Log.d(TAG, msg + " lease: " + mDhcpLease);
notifySuccess(); // 通知成功拿到IP地址了
}
private void notifySuccess() {
mController【StateMachine】.sendMessage( CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, new DhcpResults(mDhcpLease));
}
class StartedState extends State {
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case DhcpClient.CMD_POST_DHCP_ACTION:
stopDhcpAction();
switch (msg.arg1) {
case DhcpClient.DHCP_SUCCESS:
handleIPv4Success((DhcpResults) msg.obj); // 处理 handleIPv4Success IPV4地址
break;
case DhcpClient.DHCP_FAILURE:
handleIPv4Failure();
break;
default:
Log.e(mTag, "Unknown CMD_POST_DHCP_ACTION status:" + msg.arg1);
}
break;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
}
private void handleIPv4Success(DhcpResults dhcpResults) {
mDhcpResults = new DhcpResults(dhcpResults);
final LinkProperties newLp = assembleLinkProperties();
final ProvisioningChange delta = setLinkProperties(newLp);
if (VDBG) {
Log.d(mTag, "onNewDhcpResults(" + Objects.toString(dhcpResults) + ")");
}
mCallback.onNewDhcpResults(dhcpResults);
dispatchCallback(delta, newLp); //这里分发dhcpResults 把IPv4地址发出去
}
private void dispatchCallback(ProvisioningChange delta, LinkProperties newLp) {
switch (delta) {
case GAINED_PROVISIONING:
if (VDBG) { Log.d(mTag, "onProvisioningSuccess()"); }
recordMetric(IpManagerEvent.PROVISIONING_OK);
mCallback.onProvisioningSuccess(newLp); // 回调
break;
}
}
dispatchCallback 的结果最后会作用到 WaitForProvisioningCallback
public static class WaitForProvisioningCallback extends Callback {
private LinkProperties mCallbackLinkProperties;
public LinkProperties waitForProvisioning() {
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {}
return mCallbackLinkProperties;
}
}
@Override
public void onProvisioningSuccess(LinkProperties newLp) { // 回调
synchronized (this) {
mCallbackLinkProperties = newLp; // 把当前的IPv4保存起来
notify();
}
}
@Override
public void onProvisioningFailure(LinkProperties newLp) {
synchronized (this) {
mCallbackLinkProperties = null;
notify();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
} acceptDhcpResults 分析到此为止 开始分析新的状态
//进入新的状态 ConfiguringInterfaceState enter方法
ConfiguringInterfaceState
@Override
public boolean processMessage(Message message) {
super.processMessage(message);
switch (message.what) {
case EVENT_LINKADDRESS_CONFIGURED:
transitionTo(mDhcpBoundState);
return HANDLED;
default:
return NOT_HANDLED;
}
}
}
========================
class StartedState extends State {
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case DhcpClient.CMD_CONFIGURE_LINKADDRESS: {
final LinkAddress ipAddress = (LinkAddress) msg.obj;
if (setIPv4Address(ipAddress)) { // 设置 IPv4地址
mDhcpClient.sendMessage(DhcpClient.EVENT_LINKADDRESS_CONFIGURED);
} else {
Log.e(mTag, "Failed to set IPv4 address!");
dispatchCallback(ProvisioningChange.LOST_PROVISIONING,
new LinkProperties(mLinkProperties));
transitionTo(mStoppingState);
}
break;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
=========================================
// 回到开头的 setIPv4Address 至此获得了IP地址
private boolean setIPv4Address(LinkAddress address) {
final InterfaceConfiguration ifcg = new InterfaceConfiguration();
ifcg.setLinkAddress(address);
try {
final INetworkManagementService mNwService.setInterfaceConfig(mInterfaceName, ifcg);
if (VDBG) Log.d(mTag, “IPv4 configuration succeeded”);
} catch (IllegalStateException | RemoteException e) {
Log.e(mTag, “IPv4 configuration failed: “, e);
return false;
}
return true;
}
final Command cmd = new Command("interface", "setcfg", iface,
linkAddr.getAddress().getHostAddress(),
linkAddr.getPrefixLength());
for (String flag : cfg.getFlags()) {
cmd.appendArg(flag);
}
try {
mConnector.execute(cmd); // 执行命令
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
}
android dhcp 服务器,安卓通过DHCP协议获取IP地址的过程相关推荐
- centos7安装dhcp服务器并由客户端动态获取IP地址
主机架构: 角色 ip地址 网关 dhcp服务器 192.168.8.81 192.168.8.1 客户机1 动态获取 192.168.8.81 客户机2 192.168.8.99 192.168.8 ...
- DHCP自动获取IP地址的过程(自动获取ip地址的过程)
我们电脑(或者W5500)在自动获取IP地址的过程(通过DHCP请求获取IP的过程),电脑是客户端,路由器是DHCP客户端. 1.DHCP的请求的总过程 1.1在 DHCP请求的过程中,包括 4 个主 ...
- DHCP客户端获取IP地址的过程
dhclient -r eth0 ##清除一下ip dhclient eth0 ##使用dhcp自动获取ip ip a ##查看ip 补充相关命令行知识 DHCP租约过程就是DHCP客户机动态获取IP ...
- Windows server DHCP服务器为多个VLAN分配IP地址
网络拓扑 一.DHCP服务器配置(Windows2008) 1.在DHCP服务器上建立三个作用域 2.DHCP服务器路由设定 在不同的IP地址段的路由选项设定对应VLAN的网关地址,那么不同VLAN就 ...
- centos7修改ip地址自动获取_南京课工场IT培训:如何搭建DHCP服务器及自动获取IP地址及相关操作...
DHCP服务相关理论知识 DHCP服务分为以下三点, IP地址(例:192.168.1.0) 子网掩码(例:255.255.255.0) 网关 DHCP服务的好处: 减少管理员的工作量 避免输入错误的 ...
- 搭建局域网,通过DHCP实现电脑自动获取IP地址
完成这项实验需要在华为研发的ensp中进行 DHCP:动态主机配置协议 --同一分发管理ip地址 在一个广播域中,设置一台DHCP的服务器,之后需要ip地址的终端设备通过广播寻找到dhcp的服务器后 ...
- 系统dhcp服务器设置方法,dhcp服务器设置方法
导读:DHCP服务器是一台安装其专用的操作系统的计算机,它的操作系统是Windows 2000 ,DHCP服务器必须同意TCP协议的安装,还需要其他一些内容例如默认网关的设置,DHCP是一个提供服务的 ...
- 计算机自动获取IP地址流程详解
计算机自动获取IP地址流程详解 你知道吗? 我们在日常生活中直接插上网线接口就可以直接上网,不需要拨号上网也不需要设置IP地址.那么我们在日常是怎么获得IP地址的呢? 这里就需要介绍一种服务是由Int ...
- dhcp服务器1(dhcp原理,arp协议原理)
一.dhcp工作原理 dhcp(Dynamic Host configuration Protocol,动态主机配置协议 )是一个局域网的 网络协议,它主要是通过客户端发送广播数据包给整个物理网段内的 ...
最新文章
- MySQL 调优基础:Linux内存管理 Linux文件系统 Linux 磁盘IO Linux网络
- CF908G New Year and Original Order
- vs编译idl文件_Unity中 .asmdef文件的作用
- mysql 触发器判断不插入数据_mysql关于触发器怎么判断数据存在时更新不存在时添加呢!...
- 2017-2018-2 20155327 《信息安全系统设计基础》第2周学习总结
- eclipse 更换主题
- OpenCV之邻域运算之最值滤波
- [html] h5页面如何传递参数给小程序?
- 外贸个人自建站有哪些比较友好的收款方式?
- 百度网盘内容提取网站
- C语言 怎样定义函数
- axios报错Error: Request body larger than maxBodyLength limit
- SCCM 2016安装部署
- Java学习方法——类的构造方法
- Unity同时接入微信和支付宝支付 Android篇(aar包和jar包)
- Mac系统-重置MySQL登陆密码
- Kafka教程(安装/配置/开发/面试题)
- AWS Boto3 使用介绍(一)
- C语言逗号表达式赋值、野指针成因、用户标识符、字符串赋值的几个概念
- 日志分析工具mysqldumpslow
热门文章
- 开发平台的Oauth2.0
- 有什么比较好的bug管理工具?5款热门工具推荐
- ARM寄存器R13/R14/R15
- android 不能试用switch
- 【二阶魔方还原】第十次OJ的总结
- UG10.0 win10安装问题 This application has unexpectly quit.
- 计算机在测控技术与仪器中的应用,浅谈智能化技术在测控技术与仪器中的应用...
- 以流量计建立的远程抄表系统问题
- Stable Diffusion 2.0 上线,却痛失黄暴图片生成能力
- c语言计算器取百分数,简易计算器的代码--------我终于可以编40行以上的代码了...