我似乎遇到了select
的问题。
while(!sendqueue.empty())
{
if(!atms_connection.connected)
{
//print error message
goto RECONNECT;
}
//select new
FD_ZERO(&wfds);
FD_SET(atms_connection.socket, &wfds);
tv.tv_sec = 1;
tv.tv_usec = 0;
retval = select(atms_connection.socket + 1, NULL, &wfds, NULL, &tv);
if (retval == -1) {
printf("Select failed\n");
break;
}
else if (retval) {
printf("Sent a Message.\n");
}
else {
//printf("retval value is %d\n",retval);
printf("Server buffer is full, try again...\n");
break;
}
n = write(atms_connection.socket, sendqueue.front().c_str(), sendqueue.front().length());
}
该函数属于一个线程,当它获取锁时,使用select()清除队列并在循环中写入套接字,直到队列为空。
第一次线程获得锁定select()
很好,但是第二次获取锁定并输入while时它总是返回0.
为了记录,它过去一段时间以来一直很好用,从那时起我就没有改变过代码。
答案 0 :(得分:5)
超时时选择返回0。以下行指定超时为1秒。
tv.tv_sec = 1;
通常,套接字已准备好进行写入,而select将立即返回。但是,如果套接字输出缓冲区中没有空间用于新数据,则select不会将此套接字标记为准备写入。
例如,当连接的另一端未调用recv/read
时,可能会发生这种情况。未确认数据的数量增加,缓冲区最终变满。由于超时非常小,因此select经常返回值为0。
答案 1 :(得分:0)
除了已经提到的内容之外,选择api本身只会告诉描述符是否准备就绪。它可以用于读取或写入,具体取决于所选择的操作。
在您的情况下,“发送的消息”打印似乎给出了实际写入数据的错觉,但事实并非如此。 您必须对描述符进行写入调用,该描述符将从select中返回。
Select不会神奇地自己读取或写入缓冲区。如果您是侦听服务器,则在选择调用成功返回后调用accept或read。如果您是一个客户端并打算编写(就像您的情况一样),您需要进行显式的write()或send()调用。