您的位置:首页 > 其它

SOCKET学习第一阶段(上)

2009-11-12 01:45 330 查看
/*
22:28 2009-11-10

Author: byFeng
*/

在对学习SOCKET前段规划中,第一步是对SOCKET编程中要用到的函数进行一个系统的认识。
当然,由于我不是从零开始学习SOCKET,
对于一些函数只是简单的罗列或对以前用到时候没有注意到的一些参数作用进行记录。
对没有用过或是认为很重要但已经忘得差不多的会详细记录下来。
开始学习了:

1、WSAStartup
The Windows Sockets WSAStartup function initiates use of Ws2_32.dll by a process.
初始化套接字环境,本函数必须是应用程序或DLL调用的第一个Windows Sockets函数.
它允许应用程序或DLL指明Windows Sockets API的版本号及获得特定Windows Sockets实现的细节.
应用程序或DLL只能在一次成功的WSAStartup()调用之后才能调用进一步的Windows Sockets API函数.
int WSAStartup(
WORD wVersionRequested,
LPWSADATA lpWSAData
);

2、WSACleanup
The Windows Sockets WSACleanup function terminates use of the Ws2_32.dll.
清理套接字环境,和上面的WSAStartup相反,该函数是在程序不在对任何Windows Sockets函数调用后,用其来清
理套接字环境的
int WSACleanup (void);

3、SOCKET socket(int af,int type,int protocol);
建立套接字
参数af用于指定网络地址类型,一般取AF_INET,表示该套接字在Internet域中,进行通信。
参数type用于知道套接字的类型,若取SOCK_STREAM表示创建的套接字是流套接字,
而取SOCK_DGRAM创建数字报套接字。参数protocol用于指定网络协议,一般取0,表示默认为TCP/IP协议。
若套接字创建成功则该函数返回创建的套接字句柄SOCKET,否则产生INVALID_SOCKET错误。

4、int listen(SOCKET s,int backlog);
将套接字置入监听模式并准备接受连接请求。
其中,参数s是服务器端套接字,于指定正在等待连接的最大队列长度。
如无错误发生,listen函数返回0,失败则返回SOCKET_ERROR错误。

5、SOCKET accept( SOCKET s, struct sockaddr* addr, int* addrlen );
参数s同上,addr是一个有效的SOCKADDR_IN结构的地址,而addrlen是sockaddr_in结果的长度。
accept函数返回后,addr参数变量中会包含发出连接请求的那个客户机的IP地址信息,
而addrlen参数则指出该结构的长度,并返回一个新的套接字描述符,它对应于已经接受的那个客户机连接。

6、 int bind( SOCKET s, const struct sockaddr* name, int namlen );
绑定到本地,name中指定的IP应该是当前运行该程序机器的IP。

7、int connect( SOCKET s, const struct sockaddr FAR* name, int namelen );连接到服务器

8、 int send( SOCKET s, const char* buf, int len, int flags );
s是已建立连接的套接字描述字,参数buf是字符缓冲区,包含即将发送的数据,
参数len用于指定即将发送的缓冲区内的字符数。
flags可取的值有:0、MSG_DONTROUTE或MSG_OOB或这些标志的按位或运算。

9、int recv( SOCKET s, char* buf, int len, int flags );

s是准备接收数据的套接字,buf是即将收到数据的字符缓冲区,而len则是准备接受的字节数或buf缓冲的长度。
flags参数可以是0、MSG_PEEK或MSG_OOB或这些标志的按位“或”运算。

10、int shutdown( SOCKET s, int how );
其中,how参数用于描述禁止哪些操作,它可取的值有:
SD_RECEIVE、
SD_SEND或SD_BOTH。
如果是SD_RECEIVE,
就表示不允许再调用接收函数,
如果选择SD_SEND,表示不允许再调用发送函数,
如果是SD_BOTH
则表示取消连接两端的收发操作。
如果没有错误发生,shutdown()返回0,否则返回SOCKET_ERROR错误。

11、 int closesocket(SOCKET s );
s是要关闭的套接字描述字,再利用套接字执行调用就会失败。

2009-11-12 1:19:17 BY.Feng
12 int gethostname(char *name, size_t len)
这个函数,调用后,会将主机名保存在name里面。而len是name的大小。
该函数返回0表示成功,否则失败。

13、struct hostent *gethostbyname(const char *name);
hostent结构:
struct hostent {
char *h_name;//*h_name 表示的是主机的规范名
char **h_aliases;//h_aliases 表示的是主机的别名
int h_addrtype;//地址类型AF_INET,还是AF_INET6
int h_length;//IP地址占字节数
char **h_addr_list;//IP地址列表
};
char *h_name 表示的是主机的规范名。
例如 www.google.com 的规范名其实是 www.l.google.com
char **h_aliases 表示的是主机的别名。
www.google.com 就是google他自己的别名。
有的时候,有的主机可能有好几个别名,这些,其实都是为了易于用户记忆而为自己的网站多取的名字。
int h_addrtype 表示的是主机ip地址的类型,到底是ipv4(AF_INET),还是ipv6(AF_INET6)
int h_length 表示的是主机ip地址的长度
int **h_addr_lisst 表示的是主机的ip地址,注意,这个是以网络字节序存储的。
千万不要直接用printf带%s参数来打这个东西,会有问题的哇。
所以到真正需要打印出这个IP的话,需要调用inet_ntop()。
例子程序:

//***************************************
// [11/11/2009 --BY.Feng]
//***************************************
#include "winsock2.h"
#include "stdio.h"
#pragma comment(lib,"ws2_32.lib")

int main()
{
int nRet = 0;
char hostname[128] = {0};

WSADATA wsaData;
WSAStartup(MAKEWORD(0x2,0x0),&wsaData);//初始化套接字环境
nRet = gethostname(hostname,128);//获得本机名
strcpy(hostname,"www.baidu.com");
HOSTENT* hPtr = gethostbyname(hostname);//获得目标主机名
if (hPtr == NULL || nRet != 0)
{
printf("%d/n",WSAGetLastError());
return 0;
}
char** ppr = NULL;
printf("official name: %s,h_aliases: %s,h_Length: %d/n",hPtr->h_name,hPtr->h_aliases,hPtr->h_length);
switch(hPtr->h_addrtype)
{
case AF_INET:
case AF_INET6:
ppr = hPtr->h_addr_list;
while (*ppr != NULL)
{
printf("Address: %s/n",inet_ntoa(*(in_addr*)ppr[0]));
++ppr;
}

}

HOSTENT* hRomote;
// hRomote = (HOSTENT*)malloc(sizeof(hRomote));
int addr = inet_addr("202.108.22.43");
hRomote = gethostbyaddr((char*)&addr,4,AF_INET);//查询目标主机信息
if (hRomote == NULL)
{
printf("Can't Connect Peer!");
return 0;
}

ppr = NULL;
printf("official name: %s,h_aliases: %s,h_Length: %d/n",hRomote->h_name,
hRomote->h_aliases,hRomote->h_length);
switch(hRomote->h_addrtype)
{
case AF_INET:
case AF_INET6:
ppr = hRomote->h_addr_list;
while (*ppr != NULL)
{
printf("Address: %s/n",inet_ntoa(*(in_addr*)ppr[0]));
++ppr;
}

}
WSACleanup();//退出时要调用

return 0;
}
14、const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) ;
在Windows中没这个函数吧。
这个函数,是将类型为af的网络地址结构src,转换成主机序的字符串形式,存放在长度为cnt的字符串中。
这个函数,其实就是返回指向dst的一个指针。如果函数调用错误,返回值是NULL。

15、struct hostent FAR *PASCAL FAR gethostbyaddr(const char
   FAR * addr, int len, int type);
   addr:指向网络字节顺序地址的指针。
   len: 地址的长度,在PF_INET类型地址中为4。
   type:指地址类型AF_INET、IF_INET6

16、inet_ntoa( char FAR* PASCAL FAR inet_ntoa( struct in_addr in);
将网络地址转换成“.”点隔的字符串格式。

in:一个表示Internet主机地址的结构。

注释:
本函数将一个用in参数所表示的Internet地址结构转换成以“.” 间隔的诸如“a.b.c.d”的字符串形式。
请注意inet_ntoa()返回的字符串存放在WINDOWS套接口实现所分配的内存中。
应用程序不应假设该内存是如何分配的。
在同一个线程的下一个WINDOWS套接口调用前,数据将保证是有效。
返回值:
若无错误发生,inet_ntoa()返回一个字符指针。否则的话,返回NVLL。
其中的数据应在下一个WINDOWS套接口调用前复制出来。
上面这几个函数对于完成简单的连接操作是可以胜任的,但是在真正的使用过程中,将会用到更多的函数。

17、unsigned long inet_addr( const char FAR *cp);
将点格式的IP地址转换为无符号类型存储。

18、u_short PASCAL FAR htons( u_short hostshort);
作用是将主机的无符号短整形数转换成网络字节顺序。

19、 u_short PASCAL FAR ntohs( u_short netshort);

20、u_long PASCAL FAR htonl( u_long hostlong);
本函数将一个32位数从主机字节顺序转换成网络字节顺序。
//将主机的unsigned long值转化为网络字节顺序(32位),使用函数htonl()
//参数hostlong标识主机字节顺序的数字,函数返回一个网络字节顺序的数字
#include <winsock.h>
#include <stdio.h>
#pragma comment (lib,"ws2_32.lib")

void main()
{
u_long a = 0x12345678;
u_long b = htonl(a);
printf("%u/n",a);
printf("%x/n",a);
printf("%u/n",b);
printf("%x/n",b);
}

21、u_long PASCAL FAR ntohl( u_long netlong);
ntohl()
  简述:
  将一个无符号长整形数从网络字节顺序转换为主机字节顺序。
  #include <winsock.h>
  u_long PASCAL FAR ntohl( u_long netlong);
  netlong:一个以网络字节顺序表达的32位数。
  注释:
  本函数将一个32位数由网络字节顺序转换为主机字节顺序。
  返回值:
  ntohl()返回一个以主机字节顺序表达的数。
//将32位网络字节转换为主机字节,使用函数ntohl()
//定义如下 u_long ntohl(u_long netlong);
#include <WINSOCK2.H>
#include <stdio.h>
#pragma comment(lib,"ws2_32.lib")
void main()
{
u_long a = 0x12345678;
u_long b = ntohl(a);
printf("%u/n",a);
printf("%x/n",a);
printf("%u/n",b);
printf("%x/n",b);
}

22、 int PASCAL FAR getpeername( SOCKET s, struct sockaddr FAR* name,
int FAR* namelen);
s [in]
A descriptor identifying a connected socket.

name [out]
The SOCKADDR structure that receives the address of the peer.

namelen [in, out]
A pointer to the size, in bytes, of the name parameter.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: