关于socket编程中基本函数介绍

源自:http://blog.sina.com.cn/s/blog_a459dcf5010155nf.html

本文针对SOCKET编程中要用到的函数进行一个比较系统的介绍。

说明:在使用Socket时,需要在lib库中使用ws2_32.lib;

 

1、WSAStartup:初始化套接字环境,本函数必须是应用程序或DLL调用的第一个Windows Sockets函数.它允许应用程序或DLL指明Windows Sockets API的版本号及获得特定Windows Sockets实现的细节.应用程序或DLL只能在一次成功的WSAStartup()调用之后才能调用进一步的Windows Sockets API函数.

int WSAStartup(

  WORD wVersionRequested,  

  LPWSADATA lpWSAData  

);

下面给出WSAStartup函数在实际开发过程中的用法:

//begin 初始化网络环境

int err = WSAStartup(MAKEWORD(2, 2), &wsaData);

if ( err != 0)

{

    printf("WSAStartup failed with error: %d\n", err);

    return -1;

}//end

 

2、WSACleanup:清理套接字环境,和上面的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错误。

下面给出WSACleanup、socket函数在实际开发过程中的用法:

//begin socket 一个套接字

hTcpSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (INVALID_SOCKET == hTcpSocket)

{

MJS_LOG_ERROR("socket failed with error: \n");

WSACleanup();

return -1 ;

}//end

 

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 );连接到服务器

下面给出connect函数在实际开发过程中的用法:

int ServePort=20000;

char ServeIP[32]="192.168.1.200";

sockaddr_in addr;

addr.sin_family = AF_INET;

addr.sin_port = htons(ServePort);

addr.sin_addr.S_un.S_addr = inet_addr(ServeIP);

//连接服务器

if (connect(hTcpSocket, (sockaddr*)&addr, sizeof(sockaddr)) == -1)

{

    closesocket(hTcpSocket);

    printf("connect Tradesys failed with error%d,%s,%d: \n",ServePort,ServeIP,GetLastError());

    WSACleanup();

    return -1;

}

else

{

    printf("connect Tradesys sucessed,%d,%s: \n",ServePort,ServeIP);

}

 

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是要关闭的套接字描述字,再利用套接字执行调用就会失败。

 

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 表示的是主机的规范名。

char   **h_aliases 表示的是主机的别名。

int   h_addrtype 表示的是主机ip地址的类型,到底是ipv4(AF_INET),还是ipv6(AF_INET6)

int   h_length 表示的是主机ip地址的长度

int   **h_addr_lisst 表示的是主机的ip地址,注意,这个是以网络字节序存储的。

 

14、const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) ;

这个函数,是将类型为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地址结构转换成以“.” 间隔的诸如“a.b.c.d”的字符串形式。请注意inet_ntoa()返回的字符串存放在WINDOWS套接口实现所分配的内存中。应用程序不应假设该内存是如何分配的。在同一个线程的下一个WINDOWS套接口调用前,数据将保证是有效。

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

返回值:若无错误发生,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);

将一个无符号长整形数从网络字节顺序转换为主机字节顺序。

参数netlong:一个以网络字节顺序表达的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:标识一已连接套接口的描述字。

参数name:接收端地址的名字结构。 

参数namelen:一个指向名字结构的指针。 

getpeername()函数用于从端口s中获取与它捆绑的端口名,并把它存放在sockaddr类型的name结构中。 它适用于数据报或流类套接口。 返回值: 若无错误发生,getpeername()返回非零。否则的话,返回0,应用程序可通过WSAGetLastError()来获取相应的错误代码。 

 

23、int PASCAL FAR getsockname( SOCKET s, struct sockaddr FAR* name, int FAR* namelen); 获取一个套接口的本地名字。 

s:标识一个已捆绑套接口的描述字。 

name:接收套接口的地址(名字)。 

namelen:名字缓冲区长度。 

getsockname()函数用于获取一个套接口的名字。 它用于一个已捆绑或已连接套接口s,本地地址将被返回。 

本调用特别适用于如下情况:未调用bind()就调用了connect(),这时唯有getsockname()调用可以获知系统内定的本地地址。 在返回时,namelen参数包含了名字的实际字节数。 若一个套接口与INADDR_ANY捆绑,也就是说该套接口可以用任意主机的地址, 此时除非调用connect()或accept()来连接,否则getsockname()将不会返回主机IP地址的任何信息。 除非套接口被连接,WINDOWS套接口应用程序不应假设IP地址会从INADDR_ANY变成其他地址。 这是因为对于多个主机环境下,除非套接口被连接,否则该套接口所用的IP地址是不可知的。 返回值: 若无错误发生,getsockname()返回0。 否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。 

附:22、23函数中错误代码: 

WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。 

WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。 

WSAEFAULT:namelen参数不够大。 

WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。 

WSAENOTCONN 套接口未连接。 

WSAENOTSOCK:描述字不是一个套接口。

WSAEINVAL:套接口未用bind()捆绑。

 

24、int PASCAL FAR setsockopt( SOCKET s, int level, int optname, const char FAR* optval, int optlen); 

关于该函数的介绍请参考下面连接:http://blog.sina.com.cn/s/blog_a459dcf5010155nb.html

 

25、int PASCAL FAR getsockopt( SOCKET s, int level, int optname, char FAR* optval, int FAR* optlen); 

关于该函数的介绍请参考下面连接:http://blog.sina.com.cn/s/blog_a459dcf5010155nb.html

你可能感兴趣的:(socket编程)