PS:这几篇学习笔记都是在windows dev center上学习的东西,大部分是翻译。传送门:http://msdn.microsoft.com/en-us/library/windows/desktop/ms738545(v=vs.85).aspx#winsock.advanced_winsock_samples
1、winsock粗略介绍
winsock是windows平台下为网络套接字提供的一套标准。截图是winsock2的结构图:
在windows下,ws2_32.dll是Windows Sockets应用程序接口, 用于支持Internet和网络应用程序。因为ws2_32.dll需要在各种协议栈中通用,winsock的windows sockets2 Transport SPI接口使得ws2_32.dll不必关心下面一层的协议栈是什么,SPI为其归一了接口规范。而对上,winsock的windows sockets2 API接口又为实现winsock应用提供了接口。
2、服务端和客户端
socket网络应用的两种类型分别是服务端和客户端,创建的过程不一样,下面是他们的创建流程。
服务端:
- Initialize Winsock.(初始化winsock)
- Create a socket.(创建套接字)
- Bind the socket.(绑定套接字)
- Listen on the socket for a client.(监听套接字,等待客户端连接)
- Accept a connection from a client.(接受客户端连接)
- Receive and send data.(接受和发送数据或消息)
- Disconnect.(断开连接)
客户端:
- Initialize Winsock.(初始化winsock)
- Create a socket.(创建套接字)
- Connect to the server.(连接至服务端)
- Send and receive data.(发送和接受数据或消息)
- Disconnect.(断开连接)
3、使用与代码示例
3.1、创建一个基础的winsock应用
这一小节讲的是创建一个winsock应用时所应该include近来的头文件和链接库。代码如下:
C++:
#ifndef WIN32_LEAN_AND_MEAN#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
int main() {
return 0;
}
其中:
winsock2.h包含了winsock的APIs,包括各种函数,数据结构和变量定义;
ws2tcpip.h包含了Winsock 2 Protocol-Specific Annex文档里定义的为TCP/IP所使用的一些更新的函数和数据结构的定义;
iphlpapi.h包含了你所要使用的IP Helper的APIs的声明(这个头文件是可选的,但是如何有引用近来,就一定要放在引用winsock2.h那一行的后面);
#pragma comment(lib, "Ws2_32.lib")是在代码中写死让程序静态的去链接这个库,也可以通过IDE设置路径动态找到所需要的库;
前面三行宏定义的意思是,如果程序会引入winsock.h文件,则忽略这个文件,不让引入。这是因为由于历史原因windows.h文件中包含了为Windows Sockets 1.1版本所涉及的winsock.h文件,从而使得有些定义会跟为Windows Sockets 2.0设计的winsock2.h中的一些定义冲突,使用这个宏的话可以禁止winsock.h文件的引入,解决这样的冲突。
3.2、初始化Winsock
所有要调用其他winsock函数的应用或者dll都必须先初始化windows sockets DLL。使用的是WSAStartup函数。如下代码:
WSADATA wsaData;
int iResult;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
其中,对于WSAStartup函数:
第一个参数是调用都想要使用的版本号,是一个WORD类型的变量。这个变量的高字节指定了次版本号,低字节指定了主版本号,两个字节加到一起,就是你想要的Winsock库的版本号了。上述代码中的版本就是2.2。也可以直接用0X0202代替上面的MAKEWORD(2, 2);
第二个参数wsaData是一个WSADATA类型的数据结构实例,用于存储初始化winsock之后返回的信息,这些信息包括版本号,监听队列的大小,你能创建的最多的socket数目等。