ano*_*non 10 c++ sockets linux network-programming
或者我是否必须在应用程序级别实现它?
几周前我在实施VoIP服务器时也遇到了同样的问题.花了好几天后,我可以想出一个解决方案.正如许多其他人所提到的那样,没有任何直接的系统调用来完成这项工作.代替,
ACK带有TCP_INFO选项的数据包后收到了.ACK,请等待几毫秒再检查一下.这可能会持续到超时为止.您必须将其实现为send()调用的包装函数.你需要tcp_info结构来自<netinet/tcp.h>.它是用于保存有关tcp连接的信息的数据结构.
这是伪代码
int blockingSend(const char *msg, int msglen, int timeout) {
std::lock_guard<std::mutex> lock(write_mutx);
int sent = send(sock_fd, msg, msglen, 0);
tcp_info info;
auto expireAt = chrono::system_clock::now() + chrono::milliseconds(timeout);
do {
this_thread::sleep_for(milliseconds(50));
getsockopt(sock_fd,SOL_TCP, TCP_INFO, (void *) &info, sizeof(info));
//wait till all packets acknowledged or time expires
} while (info.tcpi_unacked > 0 && expireAt > system_clock::now());
if(info.tcpi_unacked>0) {
cerr << "no of unacked packets :" << info.tcpi_unacked << endl;
return -1;
}
return sent;
}
Run Code Online (Sandbox Code Playgroud)
此tcpi_unacked成员保存未确认连接的数据包数.如果您在send()调用后不久读取它,它将包含未分组数据包的数量,该数量等于发送的数据包数量.随着时间的推移,未打包的数量将减少到零.因此,您需要定期检查其值,tcpi_unacked直到达到零.如果连接是半开的,你将永远不会ACK在导致无限循环时收到s.对于这种情况,您可能需要添加上面实现的超时机制.
尽管很久以前就提出过这个问题,但这个答案可能会帮助那些遇到同样问题的人.我必须提一下,除了这个解决方案,这个问题可能有更准确的解决方案.因为我是系统编程和C/C++的新手,所以我可以想出来.
小智 6
TCP通常要求您在应用程序级别同步接收方和发送方.SO_SNDBUF调整或TCP_NODELAY单独组合不可能完全解决问题.这是因为在send()阻止之前可以"飞行"的数据量或多或少等于以下总和:
CWIN)和接收窗口(RWIN)大小而变化.当TCP在慢启动,拥塞避免,快速恢复和快速重传模式之间转换时,TCP发送器不断地将拥塞窗口大小调整到网络状况.和,ACK,但应用程序尚未看到.换句话说,在接收器停止从套接字读取数据之后,send()只会在以下情况下阻塞:
ACK,ACK编辑的数据发送到拥塞或接收窗口限制,并且TCP中使用的算法的目标是创建流动的字节流而不是数据包序列的效果.一般来说,它试图尽可能地隐藏传输量化为数据包的事实,而大多数套接字API反映了这一点.这样做的一个原因是套接字可能根本不在顶级TCP(或甚至IP)上实现:考虑使用相同API的Unix域套接字.
尝试依赖TCP的底层实现细节来实现应用程序行为通常是不可取的.坚持在应用层同步.
如果在您正在进行同步的情况下延迟是一个问题,您可能还想了解Nagle算法和延迟之间的交互,ACK这会在某些情况下引入不必要的延迟.
为什么不直接使用阻塞套接字呢?
这可能有点过时,但这里有一些关于阻塞/非阻塞和重叠 IO 的解释。
http://support.microsoft.com/kb/181611
顺便说一句,如果我们知道您使用的是哪种语言和操作系统,这将有助于更好地显示代码片段。
| 归档时间: |
|
| 查看次数: |
9832 次 |
| 最近记录: |