Winsock有两个主要的版本,Winsock1和Winsock2。Winsock2对Winsock1的基础上进行了更新或添加新的API函数,用函数名前的WSA前缀来区分版本。开发新应用程序请使用Winsock2,要包含头文件WiINSOCK2和导入库WS2_32.LIB。如果要使用Winsock1,要包含头文件WINSOCK1.H和导入库WSOCK52.LIB。
1.Winsock初始化
在使用Winsock函数之前,需要调用WSAStartup函数来加载Winsock库,如果没有,则会返回SOCKET_ERROR错误。WSAStartup的定义如下:
int WSAStartup(
WORD wVersionRequested,
LPWSADATA lpWSAData
);
- wVersionRequested:表示要加载的Winsock的版本。其中高字节表示次版本,低字节表示高版本。可以通过使用宏MAKEWORD(x,y)来方便设wVersionRequested值。
- lpWSAData:其是一个指向WSAData结构体的指针,WSAStartup函数使用相应的版本信息来填充该结构体。
WSAData结构体如下:
typedef struct WSAData
{
WORD wVersion;
WORD wHighVersion;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYSSTATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR* lpVendorInfo;
}WSADATA,*LPWSADATA;
- wVersion:表示WSAStartup函数加载的Winsock的版本。
- WHighVersion:表示现有Winsock的最高版本。
- szDescription和szSystemStatus:有特定Winsock来实现和设定,没有多大实际作用。
- iMaxSockets:表示同时打开的套接字数量。
- iMaxUdpDg:表示数据报的最大长度。
- lpVendorInfo:保留字段。
释放Winsock分配的资源,可以调用函数WSAClearup,定义如下:
int WSAClearup(void);
错误处理,可以通过调用WSAGetLastError函数来获取函数调用失败信息,其定义如下:
int WSAGetLastError(void);
也可以通过调用WSASetLastError函数来手动设置由WSAGetLastError获取的错误代码。
2.协议寻址
在Winsock中,使用结构体SOCKADDR_IN来设置IP地址和端口号信息,其结构如下:
struct sockaddr_in
{
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
- sin_family:设置为AF_INET,表示正在使用IP协议族。
- sin_port:设置为端口号。
- sin_addr:32位无符号整数型的IP地址,可以通过函数inet_addr将点分的IP地址转化为该类型。
- sin_zero:填充项。
将点分IP地址转化为32位无符号整数函数inet_addr,定义如下:
unsigned long inet_addr(
const char FAR * cp;
);
将主机字节顺序转化为网络字节顺序(大端形式,有意义数据在前)的4个API函数,定义如下:
u_long htonl(u_long hostlong);
int WSAHtonl(
SOCKET s;
u_long hostlong;
u_long FAR *lpnetlong;
);
u_short htons(u_short hostshort);
int WSAHtons(
SOCKET s;
u_short hostshort;
u_short FAR *lpnetshort;
);
- 其中hostlong为主机字节顺序的要转化的4个字节的数,而hostshort为主机字节顺序的要转化的2个字节的数。而lpnetlong和lpnetshort参数为传回的网络字节顺序的数。
将网络字节顺序转化为主机字节顺序的4个API函数,定义如下:
u_long ntohl(u_long hostlong);
int WSANtohl(
SOCKET s;
u_long hostlong;
u_long FAR *lpnetlong;
);
u_short ntohs(u_short hostshort);
int WSANtohs(
SOCKET s;
u_short hostshort;
u_short FAR *lpnetshort;
);
3.创建套接字
创建套接字有两个函数:socket和WSASocket,定义如下:
SOCKET socket(
int af;
int type;
int protocal;
);
- af:为协议的地址族。IP地址族为AF_INET。
- type:为套接字类型。使用TCP/IP创建套接字为SOCK_STREAM;使用UDP/IP创建套接字为SOCK_DGRAM。
- protocal:用于在给定的地址族和套接字类型具有多重入口时,对具体的传送做限定。其中TCP为IPPROTO_TCP,UDP为IPPRPTP_UDP。
为了控制套接字选项和套接字行为,有4个有用的函数:setsockopt、getsockopt、ioctlsocket和WSAIoctl。