为什么非阻塞套接字在 connect() 或 accept() 之前是可写的?
Why is nonblocking socket writable before connect() or accept()?
从最近的研究中,我了解到,如果你想做一个非阻塞套接字连接,你可以将你的套接字设置为非阻塞模式,然后在select()
将你的套接字添加到writefds
参数中。
那么,为什么在这个简化的示例中,select()
提前取消阻止并留下一个状态,说明我的未连接的套接字是可写的,而我甚至没有执行连接,更不用说让对等方接受连接了?
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
class SafeSocket
{
public:
/** Ctor.
* Creates a nonblocking socket at the specified IP in the AF_INET family and
* at a dynamic port.
*/
SafeSocket( const std::string& ip )
{
in_addr_t host_ip = inet_network( ip.c_str() );
if ( ( socket_ = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
{
std::cout << "socket() failed: " << errno << " " << strerror( errno )
<< std::endl;
socket_ = -1;
}
sockaddr_in si;
memset( &si, 0, sizeof( si ) );
si.sin_family = AF_INET;
si.sin_port = 0; // Dynamic port
si.sin_addr.s_addr = htonl( host_ip );
if ( bind( socket_, (sockaddr*)&si, sizeof si ) )
{
std::cout << "bind() failed: " << errno << " " << strerror( errno )
<< std::endl;
close( socket_ );
socket_ = -1;
}
// Make the socket do nonblocking connect().
int flags = fcntl( socket_, F_GETFL, 0 );
fcntl( socket_, F_SETFL, flags | O_NONBLOCK );
}
~SafeSocket()
{
if ( socket_ >= 0 )
{
shutdown( socket_, SHUT_RDWR );
close( socket_ );
}
}
operator int() const
{
return socket_;
}
private:
int socket_;
};
int main( int argc, char* argv[] )
{
SafeSocket s( "127.0.0.100" );
std::cout << "Created socket " << s << std::endl;
fd_set readFds;
fd_set writeFds;
FD_ZERO( &readFds );
FD_ZERO( &writeFds );
FD_SET( s, &writeFds );
timeval timeout = { 5, 0 };
if ( -1 == select( s+1, &readFds, &writeFds, NULL, &timeout ) )
{
std::cout << "select() failed: " << errno << " " << strerror( errno )
<< std::endl;
}
if ( FD_ISSET( s, &writeFds ) )
{
std::cout << s << " is writable!" << std::endl;
}
return 0;
}
输出:
>g++ --version
g++ (GCC) 4.8.3 20140911 (Red Hat 4.8.3-7)
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
>g++ -g main.cpp
>
>./a.out
Created socket 3
3 is writable!
>select()
告诉您套接字何时准备好执行下一个操作。 在这种情况下,它已准备好调用connect()
。
当然,在全新的套接字上调用select()
是不必要的。 大多数应用程序不会这样做。
相关文章:
- 当套接字连接断开时检测C/C++Unix
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- 如何通过套接字将文本文件的内容从服务器发送到客户端
- 如何在C/C++中用FD_set Unix设置套接字文件描述符
- 套接字读取后,我在缓冲区中看到意外输入
- 如何在CPP中创建应该在Windows和Linux上运行的套接字?
- 我可以与 python 服务器而不是 c++ 客户端建立 tcp/ip 套接字吗?
- 套接字连接"Operation not permitted"错误,甚至使用升压/平发器根.cpp
- WINAPI 注册应用程序重新启动时不清除打开的套接字
- C++ 套接字侦听器 accept() 在发布时不接受连接请求
- 为什么非阻塞套接字在 connect() 或 accept() 之前是可写的?
- C++ 套接字 accept() get 资源死锁避免了 epoll 的 errno
- C++ 套接字选择() 在 accept() 之前多次看到相同的连接
- 客户端套接字连接() 在服务器 accept() 超时后成功
- Windows 套接字 accept() 返回错误的值
- 套接字关闭后,c++linux accept()阻塞
- Winsock SO_REUSEADDR: accept()在连接时没有返回套接字
- 服务器和客户端套接字连接问题重新。send(), accept() 和多线程
- OOP 套接字不等待 accept()
- 套接字描述符在特定条件下从另一个线程关闭,当同一套接字上的accept()调用在Linux中进行时