分类:
2012-12-18 13:57:56
原文地址:CSocket的listen()函数的分析 作者:osama123
int CSocket::Listen(int family, int port /*=0*/)
{
//node是一个socket的初始状态
if (m_state != none)
return EALREADY;
if (port < 0 || port > 65535)
return EINVAL;
#ifdef __WXMSW__ //这是windows下的代码
if (!getaddrinfo)
{
m_fd = socket(AF_INET, SOCK_STREAM, 0);
if (m_fd == -1)
return ConvertMSWErrorCode(WSAGetLastError());
SetNonblocking(m_fd);
struct sockaddr_in addr = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
int res = bind(m_fd, (sockaddr *)&addr, sizeof(addr));
if (res)
{
res = WSAGetLastError();
closesocket(m_fd);
m_fd = -1;
return ConvertMSWErrorCode(res);
}
}
else
#endif
{
//getaddrinfo用来获取一个地址信息,然后我们才能用它来创建socket
//其中,hints用来制定你要获取什么类型的地址信息,如family, socket_type等
struct addrinfo hints = {0};
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
//PASSIVE表明我们要被动接受别人的连接请求,所谓我们在调用getaddrinfo时就不用
//制定nodename
hints.ai_flags = AI_PASSIVE;
#ifdef AI_NUMERICSERV
// Some systems like Windows or OS X don't know AI_NUMERICSERV.
hints.ai_flags |= AI_NUMERICSERV;
#endif
//我们只制定port,即对应了getaddrinfo的servicename
char portstring[6];
sprintf(portstring, "%d", port);
struct addrinfo* addressList = 0;
//得到的所有的地址信息都存在addrlessList指向的链表里面
int res = getaddrinfo(0, portstring, &hints, &addressList);
if (res)
{
#ifdef __WXMSW__
return ConvertMSWErrorCode(res);
#else
return res;
#endif
}
//下面要用得到的地址去建立socket,然后帮定在该地址上,然后监听
//只要有一个地址成功的建立了socket我们就不再创建其他的地址对应的socket了
for (struct addrinfo* addr = addressList; addr; addr = addr->ai_next)
{
m_fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
#ifdef __WXMSW__
res = ConvertMSWErrorCode(WSAGetLastError());
#else
res = errno;
#endif
if (m_fd == -1)
continue;
SetNonblocking(m_fd);
//帮定
res = bind(m_fd, addr->ai_addr, addr->ai_addrlen);
//如果成功就跳出循环
if (!res)
break;
#ifdef __WXMSW__
res = ConvertMSWErrorCode(WSAGetLastError());
closesocket(m_fd);
#else
res = errno;
close(m_fd);
#endif
m_fd = -1;
}
freeaddrinfo(addressList);
if (m_fd == -1)
return res;
}
//这里,我们就要开始监听了,我们的pending queue大小为一,表明最多只允许1个连接
//请求处于pending状态,当我们调用accept后,才会将pending queue中的连接请求处理
int res = listen(m_fd, 1);
if (res)
{
#ifdef __WXMSW__
res = ConvertMSWErrorCode(res);
closesocket(m_fd);
#else
close(m_fd);
#endif
m_fd = -1;
return res;
}
m_state = listening;
m_pSocketThread = new CSocketThread();
m_pSocketThread->SetSocket(this);
m_pSocketThread->m_waiting = WAIT_ACCEPT;
//让一个线程去管理这个socket。start()函数会调用该thread的Entry()函数,即线程
//的执行体
m_pSocketThread->Start();
return 0;
}