般来说 碰到的第一个结构体是 WSADATA
wVersion 是Socket现存版本号
wHighVersion 是支持的最高版本号
szDescription 以字符形式存储socket信息
szSystemStatus 以字符形式存储客户需求信息
iMaxSockets 单个进程所能创建的socket最大数
lpVendorInfo 一般超出了winsock的范围
结构体 SYSTEM_INFO
在这里我们只用到dwNumberOfProcessors其表示为系统可识别的cpu数
使用系统函数GetSystemInfo()得到系统信息
WSAStartup(
IN WORD wVersionRequested,
OUT LPWSADATA lpWSAData
);函数登场了
从参数声明就可以看出其中wVersionRequested是一个输入字段WORD 长为双八位,可以使用MAKEWORD(2,2)或者0x202来传入参数,当主版本号和副版本号不一定都为2但是对于现在的win2003来说可以肯定为2,2.
lpWSAData 为传出参数 ,需要传入一个声明过的参数指针,以便他初始化,当然他的结构是WSADATA
因为我的网络通讯程序是建立在高并发的基础上的所以CreateIoCompletionPort这个函数就不得不说了
这个函数具有两种作用:
1、创建完成端口
2、进行socket和完成端口的绑定
结构体addrinfo
ai_flags
AI_PASSIVE当此标志置位时,表示调用者将在bind()函数调用中使用返回的地址结构。当此标志不置位时,表示将在connect()函数调用中使用。
当节点名位NULL,且此标志置位,则返回的地址将是通配地址。
如果节点名NULL,且此标志不置位,则返回的地址将是回环地址。
AI_CANNONAME当此标志置位时,在函数所返回的第一个addrinfo结构中的ai_cannoname成员中,应该包含一个以空字符结尾的字符串,字符串的内容是节点名的正规名。
AI_NUMERICHOST当此标志置位时,此标志表示调用中的节点名必须是一个数字地址字符串。
ai_family
AF_INET IPv4
AF_INET6 IPv6
AF_UNSPEC 协议无关
ai_socktype
SOCK_STREAM 流 TCP
SOCK_DGRAM 数据报 UDP
ai_protocol
IPPROTO_IP 0 IP协议
IPPROTO_IPV4 4 IPv4
IPPROTO_IPV6 41 IPv6
IPPROTO_UDP 17 UDP
IPPROTO_TCP 6 TCP
ai_addrlen 记录 ai_addr 信息的长度 一般为16字节
ai_canonname 节点名
ai_addr 记录sockaddr结构体的指针
ai_next 下一个addrinfo结构体指针
下面就是getaddrinfo函数
WINSOCK_API_LINKAGE
INT
WSAAPI
getaddrinfo(
__in_opt PCSTR pNodeName,
__in_opt PCSTR pServiceName,
__in_opt const ADDRINFOA * pHints,
__deref_out PADDRINFOA * ppResult
);
它的作用就是通过设置ip端口号、传入一个设置了一个了一部分数据的addrinfo结构体指针,返回一个addrinfo结构体
函数WSASocket用于创建一个与指定传送服务提供者捆绑的套接口
WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED)
AF_INET IPV4地址结构,
SOCK_STREAM TCP,
IPPROTO_IP IP协议,
定义所创建套接口的特性 如果非零前三项被忽略
套接口组的描述字,
套接口属性描述 异步重叠方式
setsockopt() 函数
int PASCAL FAR setsockopt( SOCKET s, int level, int optname, const char FAR* optval, int optlen);
s 标识一个套接口的描述字。
level 选项定义的层次;目前仅支持SOL_SOCKET和IPPROTO_TCP层次。
optname 需设置的选项。
optval 指针,指向存放选项值的缓冲区。
optlen optval缓冲区的长度。
1.设置调用closesocket()后,仍可继续重用该socket。调用closesocket()一般不会立即关闭socket,而经历TIME_WAIT的过程。
BOOL bReuseaddr = TRUE;
setsockopt( s, SOL_SOCKET, SO_REUSEADDR, ( const char* )&bReuseaddr, sizeof( BOOL ) );
2. 如果要已经处于连接状态的soket在调用closesocket()后强制关闭,不经历TIME_WAIT的过程:
BOOL bDontLinger = FALSE;
setsockopt( s, SOL_SOCKET, SO_DONTLINGER, ( const char* )&bDontLinger, sizeof( BOOL ) );
3.在send(),recv()过程中有时由于网络状况等原因,收发不能预期进行,可以设置收发时限:
int nNetTimeout = 1000; //1秒
//发送时限
setsockopt( socket, SOL_SOCKET, SO_SNDTIMEO, ( char * )&nNetTimeout, sizeof( int ) );
//接收时限
setsockopt( socket, SOL_S0CKET, SO_RCVTIMEO, ( char * )&nNetTimeout, sizeof( int ) );
4.在send()的时候,返回的是实际发送出去的字节(同步)或发送到socket缓冲区的字节(异步);系统默认的状态发送和接收一次为8688字节(约为8.5K);在实际的过程中如果发送或是接收的数据量比较大,可以设置socket缓冲区,避免send(),recv()不断的循环收发:
// 接收缓冲区
int nRecvBuf = 32 * 1024; //设置为32K
setsockopt( s, SOL_SOCKET, SO_RCVBUF, ( const char* )&nRecvBuf, sizeof( int ) );
//发送缓冲区
int nSendBuf = 32*1024; //设置为32K
setsockopt( s, SOL_SOCKET, SO_SNDBUF, ( const char* )&nSendBuf, sizeof( int ) );
5.在发送数据的时,不执行由系统缓冲区到socket缓冲区的拷贝,以提高程序的性能:
int nZero = 0;
setsockopt( socket, SOL_S0CKET, SO_SNDBUF, ( char * )&nZero, sizeof( nZero ) );
6.在接收数据时,不执行将socket缓冲区的内容拷贝到系统缓冲区:
int nZero = 0;
setsockopt( s, SOL_SOCKET, SO_RCVBUF, ( char * )&nZero, sizeof( int ) );
7.一般在发送UDP数据报的时候,希望该socket发送的数据具有广播特性:
BOOL bBroadcast = TRUE;
setsockopt( s, SOL_SOCKET, SO_BROADCAST, ( const char* )&bBroadcast, sizeof( BOOL ) );
8.在client连接服务器过程中,如果处于非阻塞模式下的socket在connect()的过程中可以设置connect()延时,直到accpet()被调用(此设置只有在非阻塞的过程中有显著的作用,在阻塞的函数调用中作用不大)
BOOL bConditionalAccept = TRUE;
setsockopt( s, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, ( const char* )&bConditionalAccept, sizeof( BOOL ) );
9.如果在发送数据的过程中send()没有完成,还有数据没发送,而调用了closesocket(),以前一般采取的措施是shutdown(s,SD_BOTH),但是数据将会丢失。某些具体程序要求待未发送完的数据发送出去后再关闭socket,可通过设置让程序满足要求:
struct linger {
u_short l_onoff;
u_short l_linger;
};
linger m_sLinger;
m_sLinger.l_onoff = 1; //在调用closesocket()时还有数据未发送完,允许等待
// 若m_sLinger.l_onoff=0;则调用closesocket()后强制关闭
m_sLinger.l_linger = 5; //设置等待时间为5秒
setsockopt( s, SOL_SOCKET, SO_LINGER, ( const char* )&m_sLinger, sizeof( linger ) );
SO_BROADCAST BOOL 允许套接口传送广播信息。
SO_DEBUG BOOL 记录调试信息。
SO_DONTLINER BOOL 不要因为数据未发送就阻塞关闭操作。设置本选项相当于将SO_LINGER的l_onoff元素置为零。
SO_DONTROUTE BOOL 禁止选径;直接传送。
SO_KEEPALIVE BOOL 发送“保持活动”包。
SO_LINGER struct linger FAR* 如关闭时有未发送数据,则逗留。
SO_OOBINLINE BOOL 在常规数据流中接收带外数据。
SO_RCVBUF int 为接收确定缓冲区大小。
SO_REUSEADDR BOOL 允许套接口和一个已在使用中的地址捆绑(参见bind())。
SO_SNDBUF int 指定发送缓冲区大小。
TCP_NODELAY BOOL 禁止发送合并的Nagle算法。
TCP_NODELAY是唯一使用IPPROTO_TCP层的选项,其他所有选项都使用SOL_SOCKET层。
bind()
只是把IP地址绑定到socket上
listen()函数是设置socket在接入时系统允许等待的最大用户连接数,在winsock中系统默认最大为200、最小5,所以超出界限的设置是没有意义的。