通过adb端口转发为TCP实现自定义握手

时间:2020-06-23 08:03:43

标签: android c++ networking tcp deadlock

我正在使用ADB端口转发通过TCP在台式机和Android手机之间进行通信。

问题

为避免半开问题,我必须实现握手协议。这是因为,当客户端(桌面)使用ADB端口转发的源端口调用connect()时,即使服务器未准备好,它也总是成功。因此握手是通过以下方式实现的:

  1. 客户致电connect()
  2. 服务器调用accept()
  3. 服务器发送欢迎消息fromserver
  4. client recv()的欢迎词,用select()进行复用并避免阻塞;如果失败或没有活动,则返回到#1
  5. 客户端send()答案
  6. server recv()答案,用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

问题

这种握手是否正确?如果通用协议还可以,该如何避免死锁?

0 个答案:

没有答案