Windows的网络编程-之一-WinSock基础

对于多字节数据在内存中有两种存储方式:

Little-endian:低字节在前,高字节在后;

Big-endian:高字节在前,低字节在后

网络协议在处理多字节整数时,采用的是高端字节序,在编程时一定要考虑主机字节顺序与网络字节顺序的相互转换。

1      WinSock基本

1.1     加载/卸载WinSock库

如果装载Winsock1,那么必须include<Winsock1.h>,同时建立与Wsock32.lib的链接关系。

如果装载Winsock2,那么必须include<Winsock2.h>,同时建立与Ws_32.lib的链接关系。

在调用一个Winsock函数之前,必须先加载一个Winsock的动态链接库:

intWSAStartup( WORD wVersionRequested, LPWSADATA lpWSAData )

参数wVersionRequested是Winsock的版本号,最新版本是2.2。高位字节指定副版本,低位字节指定主版本,可用宏MAKEWORD(x,y)(其中,x是高位字节,y是低位字节)。如果需要Winsock2.2,指定0x0202或使用宏MAKEWORD(2,2)。

WSAStartup加载的Winsock库的信息存放到参数lpWSAData指向的结构体WSADATA中,可以设置为NULL。

卸载Winsock库:

intWSACleanup(void);

注意:每次调用WSAStartup( ),都需要调用相应的WSACleanup()。

1.2     SOCKET介绍

Win32中套接字不同于文件描述符,是一个独立的类型SOCKET,由两个函数建立的:

SOCKETWSASocket( int af,    int type,       intprotocol,

LPWSAPROTOCOL_INFOlpProtocolInfo,

GROUP g,   DWORD dwFlags    );

SOCKETsocket(    int af,    int type,       int protocol  );

参数af是协议的地址家族;参数type是协议的套接字类型;参数protocol指定了协议字段。

 

协议

地址家族

 

套接字类型

协议字段

IP

AF_INET

TCP

SOCK_STREAM

IPPROTO_IP

UDP

SOCK_DGRAM

IPPROTO_UDP

Raw sockets

SOCK_RAW

IPPROTO_RAW

IPPROTO_ICMP

 

参数g始终为0,因为目前尚无支持套接字组的Winsock版本。

参数dwFlags可以指定标志:WSA_FLAG_OVERLAPPED(默认设置)

参数lpProtocolInfo用来指定创建套接字的类型,可以设置为NULL。

1.3     WinSock的地址信息

Winsock通过sockaddr_in结构来指定IP地址和服务端口信息:

structsockaddr

{

unsigned short sa_family;      /* 地址协议族,一般为AF_INET*/

char sa_data[14];                    /* 14字节的协议地址,包含该socket的IP地址和端口号 */

};

另外还有一种结构类型sockaddr_in:

structsockaddr_in

{

short int sin_family;              /* 地址族 */

unsigned short int sin_port;  /* 网络字节顺序的端口号*/

struct in_addr sin_addr;       /* IP地址 */

unsigned char sin_zero[8];   /* 填充0 以保持与结构sockaddr同样大小 */

};

sockaddr_in结构使用更为方便,sockaddr_in.sin_zero应该用bzero( )或memset( )将其置为0。sockaddr_in的指针和sockaddr的指针可以通用。

structin_addr

{

unsigned long s_addr;            /* 网络字节顺序的IP地址*/

};

可以将s_addr指定为htonl( INADDR_ANY ),表示的是由系统自己指定IP地址。

在选择端口sin_port时,必须特别小心:

1.0~1023由IANA控制,是为固定服务保留的;

2.1024~49151是IANA列出来的、已注册的端口,供普通用户的普通用户进程或程序使用;

3.49152~65535是动态或私用端口,IANA这些端口上没有注册服务,可自由使用。

1.4     地址格式转换函数

inet_addr( )可以把一个点式IP地址转换成一个网络字节顺序的IP地址:

unsignedlong inet_addr( const char FAR *cp );

 

inet_nota( )可以把一个网络字节顺序的IP地址转换成一个点式IP地址:

char*FAR inet_ntoa( struct in_addr in );

1.5     网络字节顺序转换函数

主机字节顺序---->网络字节顺序:

u_longhtonl(     u_long hostlong );

intWSAHtonl(   SOCKET s, u_long hostlong,    u_long*lpnetlong );

u_shorthtons(   u_short hostshort );

intWSAHtons( SOCKET s,  u_short hostshort, u_short* lpnetshort );

网络字节顺序---->主机字节顺序:

u_longntohl(      u_long netlong   );

intWSANtohl(  SOCKET s,  u_long netlong,      u_long* lphostlong   );

u_shortntohs(   u_short netshort );

intWSANtohs( SOCKET s,  u_short netshort,   u_short* lphostshort );

1.6     名字解析

structhostent

{

char FAR* h_name;                            // 主机名

char FAR FAR ** h_aliases;        // 主机别名数组

short h_addrtype;                         // 主机地址类型

short h_length;                              // 主机地址长度(字节)

char FAR FAR ** h_addr_list;   // 主机地址数组,其中的地址是网络字节顺序。

}

1.6.1   主机名---->主机地址

structhostent * FAR gethostbyname( const char* name );

HANDLEWSAAsyncGetHostByName( HWND hWnd,  unsigned int wMsg,

const char* name,    char* buf,   int buflen );

WSAAsyncGetHostByNameAPI( )是gethostbyname( )的异步版,在结束时利用Windows消息向应用程序发出通知:

参数name可以是主机名,也可以是点式IP地址。

参数bWnd指定异步请求结束时,收到消息的窗口句柄。

参数wMsg是异步请求结束时,收到的窗口消息。

参数buf指向接收hostent数据的存储区。

参数buflen指定buf存储区的大小,推荐使用MAXGETHOSTSTRUCT。

1.6.2   主机地址---->主机名

structHOSTENT* FAR gethostbyaddr( const char* addr, int len, int type );

HANDLEWSAAsyncGetHostByAddr(  HWND hWnd, unsignedint wMsg, const char* addr,

int len,  int type,  char* buf,  int buflen );

WSAAsyncGetHostByAddrAPI( )是gethostbyaddr( )的异步版,在结束时利用Windows消息向应用程序发出通知:

参数addr是指向主机地址的指针,该主机地址按照网络字节顺序。

参数len指定参数addr的字节长度。

参数type为AF_INET。

1.7     获取Winsock函数的错误代码

intWSAGetLastError(void);

发生错误之后调用WSAGetLastError( ),就会返回发生错误的完整代码。

1.8     套接字的状态


套接字的初始状态都是CLOSED


MSL代表Maximum Segment Lifetime


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值