我想设置函数connect的超时值,但我收到此错误:"正在进行操作"
我的代码:
if ((he = gethostbyname(authdefhost)) == NULL) {
snprintf(errbuf, CERRBUFSIZ - 1, "cannot resolve %s: %s\n", authdefhost, hstrerror(h_errno));
return -1;
}
sin.sin_family = AF_INET;
memcpy(&sin.sin_addr, he->h_addr_list[0], sizeof(struct in_addr));
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
snprintf(errbuf, CERRBUFSIZ - 1, "cannot create client socket: %s\n", strerror(errno));
return -1;
}
if ((fcntl(sd, F_SETFL, O_NONBLOCK) < 0))
printf("error on setting socket flags.");
if (connect(sd, (void *) & sin, sizeof(sin)) == -1) {
snprintf(errbuf, CERRBUFSIZ - 1, "cannot connect to server …Run Code Online (Sandbox Code Playgroud) 我在理解Linux中套接字的工作方面遇到了一些问题.
setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(int));
write = write(sockfd, buf, len);
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,写入被缓冲,发送超时没有任何意义(当用户空间缓冲区被复制到内核缓冲区时,写入系统调用将立即返回).发送缓冲区大小是更重要的参数,但发送超时似乎没有什么值得的.但我当然错了,因为我已经看到了很多使用SO_SNDTIMEO的代码.假设接收器非常慢,用户空间代码如何使用SO_SNDTIMEO超时?
我做了一些搜索,似乎无法找到我正在寻找的答案,我能找到的唯一答案是使用select来查看套接字是否已经超时,这就是我已经在做的事情.
我想知道的是,无论如何要改变connect()超时之前的时间长度?我目前正在使用select()哪个返回errnoset,EINPROGRESS直到最终返回ETIMEDOUT.无论如何我可以改变这种ETIMEDOUT情况发生之前的时间吗?目前它发生在大约60秒后.我已经尝试调整传递给select()调用的超时值,但这只会影响超时之前的select()时间.
如何检测 TCP 连接中的死链接?当有人拉扯网线、关闭网络接口、打开 WiFi 或者像我这样......拔掉电源时,就会发生死链接。
Keep-alive 只对客户端有效,对服务器无效。
服务器只是接收数据,从不发送,因此使用 TCP_USER_TIMEOUT 将不起作用,因为发送 q 将始终为空。
我不想实现速度损失的应用层协议原因。(不再是零拷贝)
有效的一件事是发送 oob 数据,但因为你不应该再使用它了......
在下面编写的测试之后,您将看到客户端连接将在预期的短时间内关闭。 但是服务器会认为它已连接,永远......到目前为止等了3小时......
到目前为止,我在 3.13(Kubuntu) 和 3.18(OpenWrt) Linux 内核上对此进行了测试。这是一个错误吗?到目前为止,我已经阅读了很多 tcp/socket 编程书籍......根本没有帮助。请伙计们我需要你的帮助:)
我正在使用异步/非阻塞 io (epoll),因此发送和 rcv 超时也不起作用。
UPDATE2:现在有 x64/x86 的剪切源
添加:我以为我可以通过 epoll 事件捕获错误。
但是如果发生错误,我是否需要询问套接字?
#define MAX_EVENTS 64
#define CON_RETRY_TIMEOUT 10 /* time to wait in sec until next connect attempt */
#define CON_TIMEOUT 10 /* time in sec after which stop trying to connect */
#define CON_IDLE 10 /* time in sec after which …Run Code Online (Sandbox Code Playgroud) 使用阻塞winsockets时是否可以设置超时接受函数?就像我们可以通过setsockopt来recv和发送函数一样?
似乎不可能,但我想确保.
我使用TCP Keep-Alive选项来检测死连接.它适用于使用读取套接字的连接:
setsockopt(mysock,...) // set various keep alive options
epoll_ctl(ep,mysock,{EPOLLIN|EPOLERR|EPOLLHUP},)
epoll_wait -> (exits after several seconds when remove host disconnects cable)
Run Code Online (Sandbox Code Playgroud)
Epoll等待在套接字上使用EPOLLIN | EPOLLHUP退出而没有问题.
但是,如果我尝试向socket写入很多东西,直到我得到EAGAIN然后轮询读取和写入,我在断开电缆时没有出错:
setsockopt(mysock,...) // set various keep alive options
while(send() != EAGAIN)
;
epoll_ctl(ep,mysock,{EPOLLIN|EPOLLOUT|EPOLERR|EPOLLHUP},)
epoll_wait -> --- Never exits!!!! even when the cable of the remove host is disconnected!!!
Run Code Online (Sandbox Code Playgroud)
编辑:附加信息
当我监控与wireshark的通信时,在第一种情况下(读取)我会在几秒钟内得到一次ack请求.但在第二种情况下,我根本检测不到.
在服务器停止运行后,TCP keepalive(小超时)是否阻止客户端挂起recv?
场景:
服务器和客户端在不同的机器上运行
在客户端休眠期间,服务器已关闭,现在:
设置KEEPALIVE选项:
void TCPclient::setkeepalive()
{
int optval;
socklen_t optlen = sizeof(optval);
/* Check the status for the keepalive option */
if(getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen) < 0) {
throw std::string("getsockopt");
}
optval = 1;
optlen = sizeof(optval);
if(setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) {
close(s);
exit(EXIT_FAILURE);
}
optval = 2;
if (setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &optval, optlen) < 0) {
throw …Run Code Online (Sandbox Code Playgroud)