一、网络编程的相关函数
1、WSAStartup函数
通过WSAStartup函数来加载套接字库,有两个功能:一是加载套接字库,
一是进行套接字库的版本协商,也就是确定使用的socket版本。
int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);
参数: wVersionRequested: 用来指定准备加载的Winsock库的版本。
高位字节指定所需要的Winsock库的副版本,
而低位字节则是主版本。通常版本号为:
2.1,其中2是主版本号,1是副版本号。
可以利用MAKEWORD(x,y)宏(其中x是
高位字节,y是地位字节)方便地获得
wVersionRequested的正确值。
lpWSAData: 这是一个返回值,指向WSADATA结构的指针,
WSAStartup函数用其加载的库版本有关的信息
填在这个结够中。WSADATA的结构的定义如下:
typedef struct WSAData{
WORD wVersion;
WORD wHighVersion;
char szDesription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
}WSADATA,*LPWSADATA;
WSAStartup函数把SWAData结构中的第一个字段wVersion
设置为打算使用的Winsock版本。wHighVersion
字段容纳的是现有的Winsock库的最高版本。记住,
这两个字段中,高位字节代表的是Winsock副版本,
而低位字节代表的则是Winsock主版本。
szDescription和szSystemStatus这两个字段由特
定的Winsock实施方案设定,事实上并没有用。
不要使用下面这两个字段:iMaxSockets和iMaxUdpDg,
它们是假定同时最多可打开多少套接字和数据报的最大长度。
然而,要知道数据报的最大长度应该通过WSAEnumProtocols
函数来查询协议信息。同时最多打开套接字的数目不是固定
的,很大程度上和可用物理内存的多少有关。
最后,lpVendorInfo字段是为Winsock实施方案有关的指定厂
商信息预留的,任何一个Win32平台上都没有使用这个字段。
对于每一个WSAStartup函数的成功调用,在最后都对应一个
WSACleanUp调用,以便释放为该应用程序分配资源,终止对
WinSock动态库的使用。
2、socket函数
SOCKET socket(int af,int type,int protocol);
参数: af: 指定地址族,对于TCP/IP协议的套接字,它只能是AF_INET;
type: 指定Socket类型,对于1.1版本的Socket,它只支持两种类型的套接字,
SOCK_STREAM指定产生流式套接字,SOCK_DGRAM产生数据报套接字;
protocol: 与特定的地址家族相关的协议,如果指定为0,那么系统就会根据地址
格式和套接字类型,自动选择一个合适的协议。
3、bind函数
int bind(SOCKET s,const struct sockaddr FAR *name,int namelen);
参数: s: 指定要绑定的套接字;
name: 指定了该套接字的本地地址信息,
是一个指向sockaddr结构的指针变量,
结构如下:
struct sockaddr {
u_short sa_family; 指定地址家族,对于TCP/IP协议的套接字,必须设置为AF_INET;
char sa_data[14];}; 表示一块内存分配区,起到占位作用,该区域中指定与协议相关的
具体地址信息。
在基于TCP/IP的socket编辑过程中,可用用来sockaddr_in结构替换sockaddr,
struct sockaddr_in{
short sin_family; 表示地址族,对于IP地址,将一直是AF_INET
unsigned short sin_port; 指定的是将要分配给套接字的端口。
struct in_add sin_addr; 给出套接字的主机IP地址
char sin_zero[8];}; 只是一个填充数,如果函数成功返回0,如果失败
返回SOCKET_ERROR.
struct in_addr {
union {
struct{u_char s_b1,s_b2,s_b3,s_b4;} S_sun_b;
struct{u_short s_w1,s_w2;}S_un_w;
u_long S_addr;
}S_un;
}
4、inet_addr和inet_ntoa函数
unsigned long inet_addr( const char FAR *cp);
需要一个字符串作为参数,该字符串指定了以点分十进制格式表示的IP地址(192.168.0.16).
函数返回一个适合分配给S_addr的u_long类型的数值。
char FAR * inet_ntoa(struct in_addr in);
它接收一个in_addr结构体类型的参数并返回一个以点分十进制格式表示的IP地址字符串。
5、listen函数
int listen(SOCKET s, int backlog);
参数: s: 套接字描述符,
backlog: 等待连接队列的最大长度。
6、accept函数
SOCKET accept(SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen);
参数: s: 套接字描述符,该套接字已经通过listen函数将其设置为监听状态。
addr: 指向一个缓冲区的指针,该缓冲区用来接收连接实体的地址,也就是当客
户端向服务器发起连接,服务器端接收这个连接时,
保持发起连接的这个客户端的IP地址信息和端口信息;
addrlen: 一个返回值,指向一个整型的指针,返回包含地址信息的长度。
7、send函数
int send(SOCKET s, const char FAR * buf,int len, int flags);
参数: s: 一个以建立连接的套接字。
buf: 指向一个缓冲区,该缓冲区包含将要传递的数据;
len: 是缓冲区的长度。
flags: 设定的值将影响函数的行为。一般将其设置为0即可。
8、recv函数
int recv(SOCKET s,char FAR* buf,int len,int flags);
参数: s: 建立连接之后准备接收数据的那个套接字。
buf: 一个指向缓冲区的指针,用来保存接收的数据。
len: 缓冲区的长度。
flags: 通过设置这个值可用影响这些函数调用的行为。
9、connect函数
int connect(SOCKET s,const struct sockaddr FAR* name, int namelen);
参数: s: 将在其上建立连接的那个套接字。
name: 设定连接的服务器端地址信息。
namelen: 指定服务器地址的长度。
10、recvfrom函数
int recvfrom(SOCKET s,char FAR* buf,int len,int flags,struct sockaddr FAR* from,int FAR* fromlen);
参数: s: 准备接收数据的
buf: 指向缓冲区的指针,该缓冲区用来接收数据;
len: 是缓冲区的长度
flags: 影响函数调用的行为
from: 一个指向地址结构的指针,主要是用来接收发送数据方的地址信息。
fromlen: 是一个整数指针,in/out参数,调用前给一个初始值,调用后,这个值
返回地址结构的大小。
11、sendto函数
int sendto(SOCKET s,const char FAR* buf,int len,int flags,const struct sockaddr FAR * to,int tolen);
参数: s: 是一个(可能已建立连接)的套接字描述符。
buf: 一个指向缓冲区的指针,该缓冲区包含将要发送的数据。
len: 指定缓冲区中数据的长度。
flags: 影响函数调用的行为。
to: 一个可选的指针,指定目标套接字的地址。
tolen: 是参数to中指定的地址的长度。
12、htons和htonl函数
htons函数将把一个u_short类型的值从主机字节顺序转换为TCP/IP网络字节顺序。
u_short htons(u_short hostshort); 一个以主机字节顺序表示的16位数值。
htonl函数将把一个u_long类型的值从主机字节顺序转换为TCP/IP网络字节顺序。
u_long htonl(u_long hostlong); hostlong是一个以主机字节顺序表示的32位数值。