if ((udp_sd = ::socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
return GetSockErrorMsg("Please setup TCP/IP(controlpanel->network)/r/n"), FALSE;
if (recv_flg != TRUE)
return TRUE;
if ((tcp_sd = ::socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
return GetSockErrorMsg("Please setup2 TCP/IP(controlpanel->network)/r/n"), FALSE;
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = local.addr;
addr.sin_port = local.portNo;
if (::bind(udp_sd, (LPSOCKADDR)&addr, sizeof(addr)) != 0)
return GetSockErrorMsg("bind()"), FALSE;
if (::bind(tcp_sd, (LPSOCKADDR)&addr, sizeof(addr)) != 0)
{
::closesocket(tcp_sd);
tcp_sd = INVALID_SOCKET;
GetSockErrorMsg("bind(tcp) error. Can't support file attach");
}
// This function controls the I/O mode of a socket.
// Set the socket I/O mode: In this case FIONBIO
// enables or disables the blocking mode for the
// socket based on the numerical value of iMode.
// If flg = FALSE, blocking is enabled;
// If flg = TRUE, non-blocking mode is enabled.
// 上面是MSDN上面的解释,也就是说设置为非阻塞模式
BOOL flg = TRUE;
if (::ioctlsocket(udp_sd, FIONBIO, (unsigned long *)&flg) != 0)
return GetSockErrorMsg("ioctlsocket(nonblock)"), FALSE;
if (IsAvailableTCP() && ::ioctlsocket(tcp_sd, FIONBIO, (unsigned long *)&flg) != 0)
return GetSockErrorMsg("ioctlsocket tcp(nonblock)"), FALSE;
// 设置UDP允许广播
flg = TRUE;
if (::setsockopt(udp_sd, SOL_SOCKET, SO_BROADCAST, (char *)&flg, sizeof(flg)) != 0)
return GetSockErrorMsg("setsockopt(broadcast)"), FALSE;
// Specifies the total per-socket buffer space reserved for sends.
// This is unrelated to SO_MAX_MSG_SIZE and does not necessarily
// correspond to the size of a TCP send window.
int buf_size = MAX_SOCKBUF, buf_minsize = MAX_SOCKBUF / 2;
if (::setsockopt(udp_sd, SOL_SOCKET, SO_SNDBUF, (char *)&buf_size, sizeof(int)) != 0
&& ::setsockopt(udp_sd, SOL_SOCKET, SO_SNDBUF, (char *)&buf_minsize, sizeof(int)) != 0)
GetSockErrorMsg("setsockopt(sendbuf)");
// Specifies the total per-socket buffer space reserved for receives.
// This is unrelated to SO_MAX_MSG_SIZE and does not necessarily
// correspond to the size of the TCP receive window.
buf_size = MAX_SOCKBUF, buf_minsize = MAX_SOCKBUF / 2;
if (::setsockopt(udp_sd, SOL_SOCKET, SO_RCVBUF, (char *)&buf_size, sizeof(int)) != 0
&& ::setsockopt(udp_sd, SOL_SOCKET, SO_RCVBUF, (char *)&buf_minsize, sizeof(int)) != 0)
GetSockErrorMsg("setsockopt(recvbuf)");
// Allows the socket to be bound to an address that is already in use.
// (See bind.) Not applicable on ATM sockets.
// 这个套接字选项通知内核,如果端口忙,但TCP状态位于 TIME_WAIT ,可以重用端口。
// 如果端口忙,而TCP状态位于其他状态,重用端口时依旧得到一个错误信息,指明"地址已经使用中"。
// 如果你的服务程序停止后想立即重启,而新套接字依旧使用同一端口,此时 SO_REUSEADDR 选项非常有用。
// 必须意识到,此时任何非期望数据到达,都可能导致服务程序反应混乱,不过这只是一种可能,事实上很不可能。
//一个套接字由相关五元组构成,协议、本地地址、本地端口、远程地址、远程端口。
// SO_REUSEADDR 仅仅表示可以重用本地本地地址、本地端口,整个相关五元组还是唯一确定的。
// 所以,重启后的服务程序有可能收到非期望数据。必须慎重使用 SO_REUSEADDR 选项。
flg = TRUE; // REUSE ADDR
if (IsAvailableTCP() && ::setsockopt(tcp_sd, SOL_SOCKET, SO_REUSEADDR, (char *)&flg, sizeof(flg)) != 0)
GetSockErrorMsg("setsockopt tcp(reuseaddr)");
if (IsAvailableTCP() && ::listen(tcp_sd, 5) != 0)
return FALSE;
return TRUE;
}