Chinaunix首页 | 论坛 | 博客
  • 博客访问: 986212
  • 博文数量: 200
  • 博客积分: 5011
  • 博客等级: 大校
  • 技术积分: 2479
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-27 15:07
文章分类

全部博文(200)

文章存档

2009年(12)

2008年(190)

我的朋友

分类:

2008-11-11 19:39:35

这个Listen应该是为了实现server而做的,基本流程:
1. getaddr得到地址信息
2. socket建立socket
3. bind帮定到socket上
4. listen开始监听
5. 将socket交给thread去处理
code:
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;
}

阅读(3124) | 评论(0) | 转发(2) |
0

上一篇:delete this的讨论

下一篇:linux manpage

给主人留下些什么吧!~~