1)Socket设置
使用socket,通常需要对其进行一些属性设置,如:阻塞与非阻塞、接收与发送缓存等。
设置非阻塞模式:
Windows示例代码:
unsigned long value = !bBlock;
int ret;
if ( bBlock )
{
ret = WSAEventSelect(so, 0, 0);
if ( ret == SOCKET_ERROR )
{
//do something
}
}
ret = ioctlsocket(so, FIONBIO, (unsigned long*)&value);
if ( ret == SOCKET_ERROR )
{
//do something
}
Linux示例代码:
int flags;
/**
* no block
*/
if ( (flags = fcntl(so, F_GETFL, 0)) == -1 )
{
//do something
}
if ( !bBlock )
{
flags |= O_NONBLOCK;
}
else
{
flags &= (~O_NONBLOCK);
}
if ( fcntl(so, F_SETFL, flags) == -1 )
{
//do something
}
设置发送与接收超时:
if ( setsockopt(so, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout)) < 0 )
{
//do something
}
if ( setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) < 0 )
{
//do something
}
当然也可以通过getsockopt获得相应的值。
设置发送与接收缓存:
if ( setsockopt(so, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(uint32_t)) < 0 )
{
//do something
}
if ( setsockopt(so, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(uint32_t)) < 0 )
{
//do something
}
当然也可以通过getsockopt获得相应的值。
2) 判断socket可读、可写
//判断可读示例代码:
do
{
rval = select(fd + 1, &fdin, NULL, NULL, ptv);
if ( rval >= 0 )
{
break;
}
else
{
#ifndef _WIN32
if ( errno == EINTR )
{
continue;
}
#endif
return -1;
}
} while (1);
if ( rval > 0 && FD_ISSET(fd, &fdin) )
{
return 1;
}
3)Socket的接收与发送
接收示例代码:
do
{
int recvRet = recv(so, (char*)buffer, len, 0);
if ( recvRet > 0 )
{
*bytesRet = recvRet;
return 0;
}
else if ( recvRet == 0 )
{
//net close
return 1;
}
else
{
#ifndef _WIN32
if ( errno == EINTR )
{
continue;
}
#endif
if ( TCP_BLOCKS )
{
return 2; //EWOULDBLOCK
}
// recv failed
return 3;
}
} while (1);
发送示例代码:
do
{
int sendRet = send(so, (char*)buffer, len, 0);
if ( sendRet > 0 )
{
*bytesRet = sendRet;
return 0;
}
else
{
#ifndef _WIN32
if ( errno == EINTR )
{
continue;
}
#endif
if ( TCP_BLOCKS ) //EWOULDBLOCK
{
return 1;
}
//send fail
return 2;
}
} while (1);