1
1

More than 5 years have passed since last update.

sockfdとrecv

Posted at
a.cpp

int send_recv_msg(int sockfd, std::string sendmsg, std::string &recvmsg) {
    recvmsg = "";
    if (send(sockfd, sendmsg.c_str(), sendmsg.size(), MSG_NOSIGNAL) == -1) {
        syslog(LOG_INFO, "send fail. %s", strerror(errno));
        return 1;
    }
    fd_set read_set_master;
    FD_ZERO(&read_set_master);
    FD_SET(sockfd, &read_set_master);
    struct timeval waitval;
    waitval.tv_sec = 10;
    waitval.tv_usec = 0;
    fd_set read_set;
    memcpy(&read_set, &read_set_master, sizeof(read_set_master));
    int r = select(sockfd + 1, &read_set, nullptr, nullptr, &waitval);
    if (r == 0) {
        syslog(LOG_INFO, "select timeout.");
        return 1;
    } else if (r < 0) {
        syslog(LOG_INFO, "select fail. %s", strerror(errno));
        return 1;
    } else if (FD_ISSET(sockfd, &read_set)) {
        int non_recv_count = 0;
        while (1) {
            char buf[4096] = "";
            ssize_t ret = recv(sockfd, buf, 4096, 0);
            if (ret == 0) {
                ++non_recv_count;
                if (non_recv_count > 3) {
                    // 3回連続でrecvの結果が0なら、もうデータは無い、で良いかな・・・。
                    //syslog(LOG_INFO, "non recv data. recv end.");
                    return 0;
                }
            } else if (ret < 0) {
                syslog(LOG_INFO, "recv fail. %s", strerror(errno));
                return 1;
            } else {
                // データ受信できたが、まだデータが続くかもしれない・・・。
                non_recv_count = 0;
                buf[ret] = '\0';
                recvmsg += buf;
                waitval.tv_sec = 0;
                waitval.tv_usec = 0;
            }
            waitval.tv_sec = 0;
            waitval.tv_usec = 100000; // 100000usec = 100msec待ってみる・・・。
            memcpy(&read_set, &read_set_master, sizeof(read_set_master));
            // まだ読める状態かを見る。もし読めるようなら、続けて読む。
            r = select(sockfd + 1, &read_set, nullptr, nullptr, &waitval);
            if (r > 0 && FD_ISSET(sockfd, &read_set)) {
                // もう1回読み込む
            } else {
                // もう読める内容が無さそう。
                //syslog(LOG_INFO, "select timeout. recv end.");
                return 0;
            }
        }
    }
    // 知らないfd?
    syslog(LOG_INFO, "unknown sockfd hit.");
    return 1;
}

ソケットで、sockfdからデータを読む場合に、
何か決まったルールで文字列をやり取りするなら良いけど、
特に決まったルールが無く、汎用的に、相手が送ってきただろう、
すべてのデータをスマートに読み込む方法を模索中・・・。

結局答えは出ずに(相手がいかなる理由で残りのデータを送ってこなくなるか不明なので)、
ある程度待って、継続するデータが来ないならやめてしまう、、、しか無いかな・・・。
うーん。

1
1
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1