win socket select的一个疑问
本帖最后由 keke_zkt 于 2013-02-27 10:48:43 编辑 网上找了一段程序 有几个地方不明白 请帮我解释一下
bool bReuseAddr=true;
iResult=setsockopt(sockServer,SOL_SOCKET,SO_REUSEADDR,(char *)&bReuseAddr,sizeof(bReuseAddr)); // 是允许套接口和一个已经允许使用的地址捆绑的意思吧 这里概念有点模糊 允许捆绑 是什么时候捆绑?
if(SOCKET_ERROR == iResult)
{
printf("Failed to set resueaddr socket!/r/n");
WSACleanup();
return;
}
iResult = bind(sockServer,(sockaddr *)&addrServer,sizeof(addrServer));// 是指的这里的捆绑吗?
if (SOCKET_ERROR == iResult)
{
printf("Failed to bind address!/r/n");
WSACleanup();
return;
}
if (0 != listen(sockServer,5))
{
printf("Failed to listen client!/r/n");
WSACleanup();
return;
}
UINT i = 0;
SOCKET sockAccept;
sockaddr_in addrAccept;
int iAcceptLen = sizeof(addrAccept);
char szDataBuff[INT_DATABUFFER_SIZE];
int iRecvSize;
sockaddr_in addrTemp;
int iTempLen;
fd_set fd;
FD_ZERO(&fd);
FD_SET(sockServer,&fd);
printf("Start server...\r\n");
while(1)
{
fd_set fdOld = fd;
iResult = select(0,&fdOld,NULL,NULL,/*&tm*/NULL);
if (0 <= iResult)
{
for(i = 0;i < fd.fd_count; i++)
{
if (FD_ISSET(fd.fd_array[i],&fdOld))
{
//如果socket是服务器,则接收连接 主要是这里不明白
if (fd.fd_array[i] == sockServer)// 这里不明白了 “如果socket是服务器,则接收连接”为什么?
{
memset(&addrAccept,0,sizeof(addrTemp));
sockAccept = accept(sockServer,(sockaddr *)&addrAccept,&iAcceptLen);
if (INVALID_SOCKET != sockAccept)
{
FD_SET(sockAccept,&fd);
printf("%s:%d has connected server!\r\n",inet_ntoa(addrAccept.sin_addr),
ntohs(addrAccept.sin_port));
}
}
else //非服务器,接收数据(因为fd是读数据集)
{
memset(szDataBuff,0,INT_DATABUFFER_SIZE);
iRecvSize = recv(fd.fd_array[i],szDataBuff,INT_DATABUFFER_SIZE,0);
memset(&addrTemp,0,sizeof(addrTemp));
iTempLen = sizeof(addrTemp);
getpeername(fd.fd_array[i],(sockaddr *)&addrTemp,&iTempLen);
if (SOCKET_ERROR == iRecvSize)
{
closesocket(fd.fd_array[i]);
FD_CLR(fd.fd_array[i],&fd);
i--;
printf("Failed to recv data ,%s:%d errorcode:%d.\r\n",
inet_ntoa(addrTemp.sin_addr),ntohs(addrTemp.sin_port),WSAGetLastError());
continue;
}
if (0 == iRecvSize)
{
//客户socket关闭
printf("%s:%d has closed!\r\n",inet_ntoa(addrTemp.sin_addr),
ntohs(addrTemp.sin_port));
closesocket(fd.fd_array[i]);
FD_CLR(fd.fd_array[i],&fd);
i--;
}
if (0 < iRecvSize)
{
//打印接收的数据
printf("recv %s:%d data:%s\r\n",inet_ntoa(addrTemp.sin_addr),
ntohs(addrTemp.sin_port),szDataBuff);
}
}
}
}
}
else if (SOCKET_ERROR == iResult)
{
//WSACleanup();
Sleep(100);
}
以下是不明白的地方
iResult=setsockopt(sockServer,SOL_SOCKET,SO_REUSEADDR,(char *)&bReuseAddr,sizeof(bReuseAddr)); // 是允许套接口和一个已经允许使用的地址捆绑的意思吧 这里概念有点模糊 允许捆绑 是什么时候捆绑?
iResult = bind(sockServer,(sockaddr *)&addrServer,sizeof(addrServer));// 是指的这里的捆绑吗?
//如果socket是服务器,则接收连接 主要是这里不明白
if (fd.fd_array[i] == sockServer)// 这里不明白了 “如果socket是服务器,则接收连接”为什么?
[解决办法]
SO_REUSEADDR是地址重用,这样,同一台机器上的两个套接字可以绑定到同一地址之上而不会出现错误,否则第二个绑定的套接字会失败。
接受连接,是从监听的套接字上去接受,这个套接字就是sockServer。
[解决办法]
1.SO_REUSEADDR如LZ理解,大致是这样,主要是程序出现异常后,重启可以马上重用该端口(一般情况要等TCP超时复位)
2.select可读,2种情况:
(1)监听socket(sockServer),表示有连接,可以accept
(2)客户端(sockAccept),表示有数据到来,可以recv
没有为什么的,就当是硬规定吧