====================================================================================================================================
开发环境:windows
开发工具:VC6.0
=======================================================================================================
1.windows下网络编程初始化----WSAStartup函数
int WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData );
(1)wVersionRequested:一个WORD(双字节)型数值,在最高版本的Windows Sockets支持调用者使用,高阶字节指定小版本(修订本)号,低位字节指定主版本号;
(2)lpWSAData 指向WSADATA数据结构的指针,用来接收Windows Sockets实现的细节。
为了在应用程序当中调用任何一个Winsock API函数,首先第一件事情就是必须通过WSAStartup函数完成对Winsock服务的初始化,因此需要调用WSAStartup函数。使用Socket的程序在使用Socket之前必须调用WSAStartup函数。
该函数的第一个参数指明程序请求使用的Socket版本,其中高位字节指明副版本、低位字节指明主版本;操作系统利用第二个参数返回请求的Socket的版本信息。当一个应用程序调用WSAStartup函数时,操作系统根据请求的Socket版本来搜索相应的Socket库,然后绑定找到的Socket库到该应用程序中。以后应用程序就可以调用所请求的Socket库中的其它Socket函数了。
下面是在socket编程中调用WSAStartup函数加载socket动态链接库(dll)的例子
// 加载socket动态链接库(dll)
WORD wVersionRequested;
WSADATA wsaData; // 这结构是用于接收Wjndows Socket的结构信息的
int err;
wVersionRequested = MAKEWORD( 1, 1 ); // 请求1.1版本的WinSock库
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return -1; // 返回值为零的时候是表示成功申请WSAStartup
}
if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {
// 检查这个低字节是不是1,高字节是不是1以确定是否我们所请求的1.1版本
// 否则的话,调用WSACleanup()清除信息,结束函数
WSACleanup( );
return -1;
}
2.创建套接字socket结构体
SOCKET socket(
int af,
int type,
int protocol
);
// 第一个参数,指定地址簇(TCP/IP只能是AF_INET,也可写成PF_INET)
// 第二个,选择套接字的类型 SOCK_STREAM 使用TCP协议
// SOCK_DRAM 使用UDP协议
//第三个,特定地址家族相关协议(0为自动
套接字与本地地址绑定bind函数
int bind(
SOCKET s,
const struct sockaddr* name,
int namelen
);
// 第一个参数,指定需要绑定的套接字;
// 第二个参数,指定该套接字的本地地址信息,该地址结构会随所用的网络协议的不同而不同
// 第三个参数,指定该网络协议地址的长度
在TCP/IP会使用sockaddr_in结构体代替sockaddr结构体,方便代替地址信息
truct sockaddr_in{
short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
har sin_zero[8];
};
// sin_family表示地址族,对于IP地址,sin_family成员将一直是AF_INET。
// sin_port指定将要分配给套接字的端口。
// sin_addr给出套接字的主机IP地址,下面是in_addr结构体
struct in_addr {
<span style="white-space:pre"> </span>union {
{ 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;
};
// sin_zero[8]给出填充数,让sockaddr_in与sockaddr结构的长度一样。
// 将IP地址指定为INADDR_ANY,允许套接字向任何分配给本地机器的IP地址发送或接收数据。
// 如果想只让套接字使用多个IP中的一个地址,可指定实际地址,用inet_addr()函数。
3.基于TCP/IP协议socket编程常用函数
由于TCP/IP协议是一个面向连接的协议,需要客户端向服务器端发送请求,服务器接受请求建立连接后双方才可以实现通信
(1)监听函数listen
int listen(SOCKET s, int backlog);
// 第一个参数指定需要设置的套接字,第二个参数为(等待连接队列的最大长度)
(2)客户端发出请求函数connect
int connect( SOCKET s, const struct sockaddr* name, int namelen);
// 第一个参数:需要进行连接操作的套接字
// 第二个参数:设定所需要连接的地址信息
// 第三个参数:地址的长度
(3)服务器端接收请求函数accept
SOCKET accept( SOCKET s, struct sockaddr* addr, int* addrlen);
// 第一个参数,接收一个处于监听状态下的套接字
// 第二个参数,sockaddr用于保存客户端地址的信息
// 第三个参数,用于指定这个地址的长度
// 返回的是向与这个监听状态下的套接字通信的套接字
(4)发送数据函数send
int send( SOCKET s, const char* buf, int len, int flags);
// 第一个参数,需要发送信息的套接字,
// 第二个参数,包含了需要被传送的数据,
// 第三个参数是buffer的数据长度,
// 第四个参数,一些传送参数的设置
(5)接收数据函数recv
int recv( SOCKET s, char* buf, int len, int flags);
// 第一个参数,建立连接后的套接字,
// 第二个参数,接收数据
// 第三个参数,接收数据的长度,
// 第四个参数,一些传送参数的设置
4.基于UDP协议socket编程函数
由于UDP协议是一个非连接的协议,并不需要向TCP/IP协议一样建立,可以直接进行通信
(1)发送数据函数sento
int sendto(
SOCKET s,
const char FAR *buf,
int len,
int flags,
const struct sockaddr FAR *to,
int tolen
);
//第一个参数,需要发送的数据的套接字
//第二个参数,存储发送的数据的数组
//第三个参数,发送数据的长度
//第四个参数, 标志位,一般为0
//第五个参数,发送数据的目标地址
//第六个参数, 目标地址的长度,一般为sizeof(SOCKADDR)
(2)接收数据函数recvfrom
int recvfrom(
SOCKET s,
char FAR* buf,
int len,
int flags,
struct sockaddr FAR *from,
int FAR *fromlen
);
//第一个参数,需要接收的数据的套接字
//第二个参数,存储接收的数据的数组
//第三个参数,接收数据的长度
//第四个参数, 标志位,一般为0
//第五个参数,接收数据的源地址
//第六个参数, 源地址的长度,一般为sizeof(SOCKADDR)
5.其他常用函数
(1)htonl() 将主机的无符号长整形数转换成网络字节顺序。
#include <winsock.h>
u_long PASCAL FAR htonl( u_long hostlong);
hostlong:主机字节顺序表达的32位数。注释:本函数将一个32位数从主机字节顺序转换成网络字节顺序。
返回值:htonl()返回一个网络字节顺序的值。
(2)htons() 将主机的无符号短整形数转换成网络字节顺序。
#include <winsock.h>
u_short PASCAL FAR htons( u_short hostshort);
hostshort:主机字节顺序表达的16位数。注释:本函数将一个16位数从主机字节顺序转换成网络字节顺序。
返回值:htons()返回一个网络字节顺序的值。
(3)inet_addr():将一个点间隔地址转换成一个in_addr。
#include <winsock.h>
unsigned long PASCAL FAR inet_addr( const struct FAR* cp);
cp:一个以Internet标准“.”间隔的字符串。注释:本函数解释cp参数中的字符串,这个字符串用Internet的“.”间隔格式表示一个数字的Internet地址。返回值可用作Internet地址。所有Internet地址以网络字节顺序返回(字节从左到右排列)。
返回值:若无错误发生,inet_addr()返回一个无符号长整型数,其中以适当字节顺序存放Internet地址。如果传入的字符串不是一个合法的Internet地址,如“a.b.c.d”地址中任一项超过255,那么inet_addr()返回INADDR_NONE。
(4)inet_ntoa():将网络地址转换成“.”点隔的字符串格式。
#include <winsock.h>
char FAR* PASCAL FAR inet_ntoa( struct in_addr in);
in:一个表示Internet主机地址的结构。
注释: 本函数将一个用in参数所表示的Internet地址结构转换成以“.” 间隔的诸如“a.b.c.d”的字符串形式。请注意inet_ntoa()返回的字符串存放在WINDOWS套接口实现所分配的内存中。应用程序不应假设该内存是如何分配的。在同一个线程的下一个WINDOWS套接口调用前,数据将保证是有效。
返回值:若无错误发生,inet_ntoa()返回一个字符指针。否则的话,返回NULL。其中的数据应在下一个WINDOWS套接口调用前复制出来。