本系列使用的教材是Windows网络与通信程序设计
第一章 Winsock编程接口
1.1Winsock库
使用Winsock库前应该包含头文件#include<winsock2.h>,同时链接到
WS2_32.DLL库中#pragma comment(lib,"WS2_32"),在创建MFC时的向导
中可以勾选
1.1.1 Winsock库的装入和释放
Winsock库的加载函数
int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSADatat);
*第一个参数指定要加载的版本号
一般都使用的是Winsock2版本因此该参数可以使用
wVersion = MAKEWORD(2,2)
*第二个参数是一个输出参数,类型为结构体指针,包含了Winsock库的
基本信息,我们主要使用的是它的wVersion成员,它是库文件建议使用
的版本号,可以这样检测:
*返回值:函数成功返回0,如果不成功可以使用WSAGetLastError查看
出错原因
if(LOBYTE(wsaData.wVersion)!=2 ||
HIBYTE(wsaData.wVersion)!=2)
{
WSACleanup();
return false;
}
Winsock的卸载函数
int WSACleanup(void);
1.1.2 Winsock的寻址方式和字节顺序
Winsock中,通过SOCKADDR_IN结构指定IP地址和端口号
struct sockaddr_in{
....
};部分成员可以通过以下函数获取
*将字符串转化为32为IP地址
unsigned long inet_addr(const char* cp);
*将32位IP地址转化成字符串
char* inet_ntoa(struct in_addr in)
Winsock中字节顺序的转换函数,一般使用
* 将本地字节序转化为网络字节序
u_short htons(u_short hostshort);
* 将网络字节序转化为本地字节序
u_short ntohs(u_short netshort);
*例子如果是本地套接字通信可以使用:
sockaddr_in sockAddr;
sockAddr.sin_family = AF_INET; //设置通信协议族
sockAddr.sin_port = htons(6002);//设置端口号
sockAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
// 设置IP地址
1.2 Winsock的TCP编程流程
1.2.1套接字的创建和关闭
套接字的创建
SOCKET socket(int af, int type, int protocol)
*af : af必须等于AF_INET
*type : 用于指定套接字类型包括SOCK_STREAM(流套接字)S、
SOCK_DGRAM(数据报套接字)、SOCK_RAW(原始套接字)
*protocol : 一般指定为0
*返回值:成功返回套接字句柄,失败返回-1
套接字的关闭
int closesocket(SOCKET s);
* s: 套接字句柄
1.2.2 绑定套接字到指定的IP地址和端口号(仅用于服务端)
套接字绑定函数
int bind(SOCKET s,const struct sockaddr* name, int namelen)
*s : 套接字句柄
*name:要关联的本地地址,示例如下
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(6002);
sin.sin_addr.S_un.S_addr = INADDR_ANY;
*namelen: name的长度
*返回值:出错返回SOCKET_ERROR
1.2.3 监听套接字(服务端)
监听函数
int listen(SOCKET s,int backlog)
*s : 套接字句柄
*backlog:监听队列中尚未连接的连接请求的最大数量
如果当前的连接请求已满,后来的连接请求将收到WSAECONNREFUSED错误
1.2.4 接受连接请求(服务端)
接受连接请求函数
SOCKET accept(SOCKET s,struct sockaddr* addr, int* addrlen)
* s : 套接字句柄(正在被监听的套接字句柄)
* addr : 输出参数,用于获取客户端的IP地址和端口信息
* addrlen: addr 的大小
*返回值:成功返回一个SOCKET套接字句柄,这个SOCKET是和客户端相联系
的,可以用来进行通信操作
1.2.5 请求连接函数(客户端)
int connect(SOCKET s,const struct sockaddr FAR* name,int namelen)
*s :套接字句柄(客户端)
*name: 服务端的IP地址和端口号信息
*namelen:name的大小
1.2.6 收发数据
数据发送函数
int send(SOCKET s, const char FAR * buf,int len, int flags)
*s : 通信套接字
*buf :要发送内容的缓冲区地址
*len :缓冲区大小
*flags : 阻塞/非阻塞模式 ,通常设置为0
返回值:成功返回实际发送的字节数,失败返回-1
数据接收函数
int recv(SOCKET s,char FAR * buf,int len, int flag);
参数与send相似,这里的buf是准备用于接收信息的内存地址