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からデータを読む場合に、
何か決まったルールで文字列をやり取りするなら良いけど、
特に決まったルールが無く、汎用的に、相手が送ってきただろう、
すべてのデータをスマートに読み込む方法を模索中・・・。
結局答えは出ずに(相手がいかなる理由で残りのデータを送ってこなくなるか不明なので)、
ある程度待って、継続するデータが来ないならやめてしまう、、、しか無いかな・・・。
うーん。