我正在使用ADB端口转发通过TCP在台式机和Android手机之间进行通信。
为避免半开问题,我必须实现握手协议。这是因为,当客户端(桌面)使用ADB端口转发的源端口调用connect()
时,即使服务器未准备好,它也总是成功。因此握手是通过以下方式实现的:
connect()
accept()
fromserver
select()
进行复用并避免阻塞;如果失败或没有活动,则返回到#1 select()
进行复用并避免阻塞;如果失败或没有任何活动,则返回到#2 问题是,无论我如何调整select()
的超时,在客户端或服务器端()上始终会出现死锁情况,其中recv()没有任何内容或与select()等待)毫无结果。
桌面客户端
char rpl[16] = {'\0'};
auto nBytesToRecv = strlen("fromserver");
auto nBytesRecved = -1;
// multiplex recv thru select()
auto timeout = 1000; // milliseconds
Result res = Receive(rpl, nBytesToRecv, &nBytesRecved, timeout);
if (res != SUCCESS) {
return res;
}
if(strcmp(rpl, "fromserver")) {
ERROR("handshake mismatch: expected fromserver, got %s", rpl);
return FAIL;
}
DEBUG("handshake half way.");
char req[16];
sprintf(req, "fromclient");
auto nBytesToSend = strlen(req);
auto nBytesSent = -1;
res = Send(req, nBytesToSend, &nBytesSent);
if (res != SUCCESS) {
return res;
}
DEBUG("handshake succeeded.");
return SUCCESS;
android服务器
char rpl[16];
sprintf(rpl, "fromserver");
auto nBytesToSend = strlen(rpl); // contains \0;
auto nBytesSent = 0;
Result res = Send(rpl, nBytesToSend, &nBytesSent);
if (res != SUCCESS) {
return res;
}
DEBUG("handshake half way.");
char req[16] = {'\0'};
auto nBytesToRecv = strlen("fromclient");
MamInt32 nBytesRecved = 0;
res = Receive(req, (MamInt32)nBytesToRecv, &nBytesRecved, {1, 0});
if (res != SUCCESS) {
return res;
}
if(strcmp(req, "fromclient")) {
ERROR("handshake mismatch: expected fromclient, got %s", req);
return FAIL;
}
DEBUG("handshake succeeded.");
此处使用的Send()
和Receive()
只是send()
和recv()
的薄包装。他们仅在发送或接收内容时返回SUCCESS
。
这种握手是否正确?如果通用协议还可以,该如何避免死锁?