在上一篇中,我说了网络的基础知识以及Winsock2的开启方法,这一篇,我们来说说socket的基本函数
1。创建Socket:socket()函数
SOCKET WSAAPI socket( _In_ int af, _In_ int type, _In_ int protocol );
af:地址族
AF_UNSPEC:未指定的地址族。 AF_INET:Internet 协议版本 4 (IPv4) 系列地址。 AF_IPX:IPX/SPX 的地址族。如果安装 NWLink IPX/SPX NetBIOS 兼容传输协议,只支持此地址族。在 Windows Vista 及更高版本不支持此地址族。 AF_APPLETALK:AppleTalk 的地址族。如果安装 AppleTalk 协议,只支持此地址族。在 Windows Vista 及更高版本不支持此地址族。 AF_NETBIOS:NetBIOS 的地址族。如果安装的 Windows 套接字提供程序 NetBIOS,只支持此地址族。NetBIOS 的 Windows 套接字提供程序都支持 32 位版本的 Windows。此提供程序是默认安装的 32 位版本的 Windows 上。NetBIOS 的 Windows 套接字提供程序不支持在 64 位 windows 版本。NetBIOS 的 Windows 套接字提供程序只支持其中的类型参数设置为 SOCK_DGRAM 的套接字。NetBIOS 的 Windows 套接字提供程序是没有直接关连的 NetBIOS 的编程接口。在 Windows Vista 中,Windows Server 2008,及更高版本上不支持 NetBIOS 的编程接口。 AF_INET6:互联网协议版本 6 (IPv6) 地址家庭。 AF_IRDA:红外数据协会 (IrDA) 的地址族。如果计算机上有一个红外端口和安装驱动程序仅支持此地址族。 AF_BTH:蓝牙的地址族。如果计算机有一个蓝牙适配器和驱动程序安装在 Windows XP SP2 或更高版本支持此地址族。
type:套接字类型(Winsock2版本)
SOCK_STREAM:测序、 可靠、 双向、 基于连接的字节流提供 OOB 数据传输机制的套接字类型。此套接字类型使用传输控制协议 (TCP) 互联网地址族 (AF_INET 或 AF_INET6)。 SOCK_DGRAM:支持无连接的、 不可靠的固定 (通常很小) 的最大长度的缓冲区的数据报套接字类型。此套接字类型使用用户数据报协议 (UDP) 互联网地址族 (AF_INET 或 AF_INET6)。 SOCK_RAW:提供允许应用程序操纵下的上层协议头的原始套接字的套接字类型。要操纵 IPv4 标头,必须在套接字上设置 IP_HDRINCL 套接字选项。要操纵 IPv6 标头,必须在套接字上设置 IPV6_HDRINCL 套接字选项。 SOCK_RDM:提供可靠的消息数据报套接字类型。这种类型的一个例子是实用通用多播 (PGM) 多播的协议实现在 Windows 中,经常被称为可靠多播的编程。如果安装可靠的多播协议,只支持此类型的值。 SOCK_SEQPACKET:提供基于数据报的伪流数据包的套接字类型。
protocol:要使用协议
IPPROTO_ICMP:Internet控制报文协议 (ICMP)。af 参数是 AF_UNSPEC、 AF_INET 或 AF_INET6,type为 SOCK_RAW。在 Windows XP 上及更高版本支持此协议值。 IPPROTO_IGMP:Internet组管理协议 (IGMP)。af 参数是 AF_UNSPEC、 AF_INET 或 AF_INET6,type为 SOCK_RAW。在 Windows XP 上及更高版本支持此协议值。 BTHPROTO_RFCOMM:蓝牙射频通信 (蓝牙 RFCOMM) 协议。af 参数 AF_BTH,type是 SOCK_STREAM。在 Windows XP SP2 或更高版本支持此协议值。 IPPROTO_TCP:传输控制协议 (TCP)。这是一个可能的值,af 参数是 AF_INET 或 AF_INET6,type参数是 SOCK_STREAM。 IPPROTO_UDP:用户数据报协议 (UDP)。这是一个可能的值,当 af 参数是 AF_INET 或 AF_INET6,type参数是 SOCK_DGRAM。 IPPROTO_ICMPV6:Internet控制报文协议版本 6 (ICMPv6)。这是一个可能的值,af 参数是 AF_UNSPEC、 AF_INET 或 AF_INET6,type为 SOCK_RAW。在 Windows XP 上及更高版本支持此协议值。 IPPROTO_RM:可靠组播 PGM 协议。这是一个可能的值,af 参数是 AF_INET,类型参数是 SOCK_RDM。在 Windows SDK 发布的 Windows Vista 及更高版本,也被称为 IPPROTO_PGM。此协议值仅支持安装了可靠的多播协议的设备。
返回值:如果没有出现错误,套接字返回引用新的套接字描述符。否则为返回值为 INVALID_SOCKET,并且可以通过调用 WSAGetLastError 检索特定的错误代码。
2。字节序转换:
u_short WSAAPI htons( _In_ u_short hostshort );
hostshort:16位整数值
返回值:网络字节序整数
u_long WSAAPI htonl( _In_ u_long hostlong );
hostshort:32位整数值
返回值:网络字节序整数
unsigned __int64 __inline htonll( unsigned __int64 value );
value:64位整数值
返回值:网络字节序整数
u_short WSAAPI ntohs( _In_ u_short netshort );
netshort:网络字节序16位整数
返回值:本机字节序
u_long WSAAPI ntohl( _In_ u_long netlong );
netshort:网络字节序32位整数
返回值:本机字节序
u_long __inline ntohll( unsigned __int64 value );
value:网络字节序64位整数
返回值:本机字节序
3。sockaddr、sockaddr_in结构
struct sockaddr { ushort sa_family; char sa_data[14]; }; struct sockaddr_in { short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero[8]; };
这两个结构等价,但一般用后者
sin_family:地址族
sin_port:端口号
sin_addr:一个in_addr结构
typedef struct in_addr { union { struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b; struct { u_short s_w1,s_w2; } S_un_w; u_long S_addr; } S_un; } IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR;S_un_b:IPv4 地址格式设置为四个 u_chars。
S_un_w:IPv4 地址格式设置为两个 u_shorts。
S_addr:IPv4 地址的格式为 u_long。
而如果是IPv6要用这个结构:
struct sockaddr_in6 { short sin6_family; u_short sin6_port; u_long sin6_flowinfo; struct in6_addr sin6_addr; u_long sin6_scope_id; }; typedef struct sockaddr_in6 SOCKADDR_IN6; typedef struct sockaddr_in6 *PSOCKADDR_IN6; typedef struct sockaddr_in6 FAR *LPSOCKADDR_IN6; struct sockaddr_in6_old { short sin6_family; u_short sin6_port; u_long sin6_flowinfo; struct in6_addr sin6_addr; };
4。inet_addr函数
unsigned long inet_addr( _In_ const char *cp );
cp:使用”.“分割的十进制IPv4地址。
返回值:如果没有出现错误,则 inet_addr 函数返回二进制表示的互联网地址的无符号长整型值。
5。inet_ntoa函数
char* FAR inet_ntoa( _In_ struct in_addr in );
in:in_addr 结构,它表示互联网主机地址。
返回值:inet_ntoa 如果没有出现错误,返回在静态缓冲区中的使用”.“分割的十进制IPv4地址。否则返回 NULL。
6。bind函数
int bind( _In_ SOCKET s, _In_ const struct sockaddr *name, _In_ int namelen );
s:套接字描述符
name:sockaddr、sockaddr_in结构的指针,表示要将socket绑定到的地址。
namelen:长度
返回值:如果没有出现错误,将绑定并返回零。否则返回 SOCKET_ERROR,并且可以通过调用 WSAGetLastError 检索特定的错误代码。
7。listen函数
int listen( _In_ SOCKET s, _In_ int backlog );
s:套接字描述符
backlog:挂起连接队列的最大长度。如果设置为SOMAXCONN,基础服务提供程序负责套接字s将设置积压为合理的最大值。
返回值:如果没有出现错误,返回零。否则为返回值为 SOCKET_ERROR,并且可以通过调用 WSAGetLastError 检索特定的错误代码。
8。accept函数
SOCKET accept( _In_ SOCKET s, _Out_ struct sockaddr *addr, _Inout_ int *addrlen );
s:套接字描述符
addr:指向一个缓冲区,接收连接实体的地址,称为通信层。地址参数的确切格式由成立时的接近于结构从套接字创建的地址族决定。
addrlen:接收长度
返回值:如果没有出现错误,接受返回值的类型是一个新的套接字的描述符的套接字。此返回值是用于作出实际连接的套接字的句柄。否则为返回值为 INVALID_SOCKET,并且可以通过调用 WSAGetLastError 检索特定的错误代码。
9。send函数
int send( _In_ SOCKET s, _In_ const char *buf, _In_ int len, _In_ int flags );
s:套接字描述符
buf:缓冲区,要发送的数据
len:数据长度
flags:标志,一般为0,也可以是:MSG_DONTROUTE:指定的数据应该不会受到路由。MSG_OOB:发送 OOB 数据。
10。recv函数
int recv( _In_ SOCKET s, _Out_ char *buf, _In_ int len, _In_ int flags );
s:套接字描述符
buf:缓冲区,用于存储要接收的数据
len:buf缓冲区长度
flags:标志,一般为0
返回值:如果没有出现错误,recv 返回接收的字节数和 buf 参数指向的缓冲区将包含此收到的数据。如果连接已正常关闭,则返回值为零。否则返回值为 SOCKET_ERROR,并且可以通过调用 WSAGetLastError 检索特定的错误代码。
11。connect函数
int connect( _In_ SOCKET s, _In_ const struct sockaddr *name, _In_ int namelen );
s:套接字描述符
name:sockaddr、sockaddr_in结构的指针,表示要连接的地址。
namelen:长度
返回值:如果没有出现错误,连接返回零。否则为它返回 SOCKET_ERROR,并且可以通过调用 WSAGetLastError 检索特定的错误代码。
12。select函数
int select( _In_ int nfds, _Inout_ fd_set *readfds, _Inout_ fd_set *writefds, _Inout_ fd_set *exceptfds, _In_ const struct timeval *timeout );
nfds:将忽略。Nfds 参数是只是为了与伯克利套接字的兼容性。
readfds:可选的指针,指向一组等待可读性检查的套接口。
typedef struct fd_set { u_int fd_count; SOCKET fd_array[FD_SETSIZE]; } fd_set;fd_count:集合中的套接字的数目。
fd_array:套接字集合的数组
writefds:可选的指针,指向一组等待可写性检查的套接口。
exceptfds:可选的指针,指向一组等待错误检查的套接口。
timeout:选择等待的最长时间提供的 TIMEVAL 结构形式。
typedef struct timeval { long tv_sec; long tv_usec; } timeval;tv_sec:时间间隔,以秒为单位。
tv_usec:以微秒为单位的时间间隔。
返回值:返回处于就绪状态并且已经包含在fd_set结构中的描述字总数;如果超时返回0;否则的话,返回SOCKET_ERROR,可通过WSAGetLastError获取错误代码。
13。closesocket函数
int closesocket( _In_ SOCKET s );
s:套接字描述符
返回值:如果没有出现错误,接字返回零。否则为返回值为 SOCKET_ERROR,并且可以通过调用 WSAGetLastError 检索特定的错误代码。