Chinaunix首页 | 论坛 | 博客
  • 博客访问: 307093
  • 博文数量: 76
  • 博客积分: 1662
  • 博客等级: 上尉
  • 技术积分: 764
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-25 17:04
个人简介

辛勤的鸟儿总能找到虫子....

文章分类

全部博文(76)

文章存档

2017年(1)

2013年(4)

2012年(5)

2011年(4)

2010年(32)

2009年(23)

2008年(7)

分类: C/C++

2010-10-11 13:12:08

Unix网络API

索引:

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

14.

15.

16.

17.

18.

19.

20.

21.

22.

23.

24.

25.

26.

27.

28.

29.

30.

31.

 

 


1.字节序函数

#include

uint16_t htons(uint16_t host16bitvalue);

uint32_t htonl(uint32_t host32bitvalue);

返回:网络字节序值

 

uint16_t ntohs(uint16_t net16bitvalue);

uint32_t ntohl(uint32_t net32bitvalue);

返回:主机字节序值

一个测试本机字节序的程序,可参见见unpv12eintro/byteorder.c


2.字节操作函数

#include

void bzero(void *dest, size_t nbytes);

void bcopy(const void *src, void *dest, size_t nbytes);

int bcmp(const void *ptr1, const void *ptr2, size_t nbytes);

返回:0—相等,非0—不相等

 

#include

void *memset(void *dest, int c, size_t len);

void *memcpy(void *dest, void *src, size_t nbytes);

int memcmp(const void *ptr1, const void *ptr2, size_t nbytes);

返回:0—相同,>0<0—不相同;进行比较操作时,假定两个不相等的字节均为无符号字符(unsigned char)。


3.地址转换函数

#include

int inet_aton(const char *strptr, struct in_addr *addrptr);

返回:1—串有效,0—串有错。 Ascii to net

 

in_addr_t inet_addr(const char *strptr);

返回:若成功,返回32为二进制的网络字节序地址;若有错,则返回INADDR_NONE

char *inet_ntoa(struct in_addr inaddr);

返回:指向点分十进制数串的指针。

int inet_pton(int family, const char *strptr, void *addrptr);

返回:1—成功;0—输入不是有效的表达格式,-1—出错。

const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);

返回:指向结果的指针成功,NULL—失败。

说明:

·  inet_aton函数的指针若为空,则函数仍然执行输入串的有效性检查,但不存储任何结果。

·  inet_addr的缺陷:出错返回值INADDR_NONE等于255.255.255.255IPv4的有限广播地址),所以该函数不能处理此地址。
尽量使用inet_aton,不使用inet_addr

·  inet_ntoa函数的执行结果放在静态内存中,是不可重入的。

·  参数family可以是AF_INET,也可以是AF_INET6,若参数family不被支持,则出错,errno置为EAFNOSUPPORT

·  指针addrptr是结构指针。

·  len指定目标的大小,避免缓冲区溢出。如果len太小,则返回一个空指针,errno置为ENOSPC。为有助于规定该大小,有如下定义:

#include

#define INET_ADDRSTRLEN 16 /*fro IPv4 dotted-decimal */

#define INET6_ADDRSTRLEN 46 /*for IPv6 hex string */

·  inet_ntop函数的参数strptr不能为空指针,成功时,此指针即是函数的返回值。

实现IPv4版本的inet_ptoninet_ntop的程序,参见:unpv12elibfree/inet_pton_ipv4.clibfree/inet_ntop_ipv4.c


4.readnwritenreadline

函数原型如下:

ssize_t readn(int filedes, void *buff, size_t nbytes);

ssize-t writen(int filedes, void *buff, size_t nbytes);

ssize_t readline(int filedes, void *buff, size_t maxlen);

返回:读写字节数,-1—出错。

 

实现程序见:unpv12elib/readn.clib/writen.clib/readline1.clib/readline.c


5.测试描述符类型

#include

int isfdtype( int fd, int fdtype);

返回:1—是指定类型,0—不是指定类型,-1—出错。

 

要测试是否为套接口描述子,fdtype应设为S_IFSOCK

该函数的一个实现程序,参见unpv12elib/isfdtype.c


6.socket函数

#include

int socket(int family, int type, int protocol);

返回:非负描述字成功,-1—出错。

 

family指定协议族,有如下取值:

·  AF_INET     IPv4协议

·  AF_INET6    IPv6协议

·  AF_LOCAL    Unix域协议

·  AF_ROUTE    路由套接口

·  AF_KEY      密钥套接口

type指定套接口类型:

·  SOCK_STREAM    字节流套接口

·  SOCK_DGRAM     数据报套接口

·  SOCK_RAW       原始套接口

protocol一般设为0,除非用在原始套接口上。

 

并非所有familytype的组合都是有效的。

AF_LOCAL等于早期的AF_UNIX


7.connect函数

#include

int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);

返回:0—成功,-1—出错。

 

sockfdsocket函数返回的套接口描述字,servaddraddrlen是指向服务器的套接口地址结构指针和结构大小。

在调用connect之前不必非得调用bind函数。

如果是TCP,则connect激发TCP的三路握手过程,在阻塞情况下,只有在连接建立成功或出错时该函数才返回,

出错情况:

·  没有收到SYN分节的响应,在规定时间内经过重发仍无效,则返回ETIMEDOUT

·  如果对SYN分节的响应是RST,表示服务器在指定端口上没有相应的服务,返回ECONNREFUSED

·  如果发出 SYN在中间路由器上引发一个目的地不可达ICMP错误,在规定时间内经过重发仍无效,则返回EHOSTUNREACHENETUNREACH错误。

注意:如果connect失败,则套接口将不能再使用,必须关闭,不能对此套接口再调用函数connect


8.bind函数

#include

int bind(int sockfd, const struct sockaddr *maddr, socklen_t addrlen);

返回:0—成功,-1—出错。

 

进程可以把一个特定的IP地址捆绑到他的套接口上,但此IP地址必须是主机的一个接口。

对于IPv4,通配地址是INADDR_ANY,其值一般为0;使用方法如下:

struct sockaddr_in servaddr;

servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

对于IPv6,方法如下:

struct sockaddr_in6 serv;

serv.sin6_addr = in6addr_any; (系统分配变量in6addr_any并将其初始化为常值IN6ADDR_ANY_INIT。)

如果让内核选择临时端口,注意的是bind并不返回所选的断口值,要得到一个端口,必须使用getsockname函数。

bind失败的常见错误是EADDRINUSE(地址已使用)。


9.listen函数

#include

int listen(int sockfd, int backlog);

返回:0—成功,-1—出错。

 

listen把未连接的套接口转化为被动套接口,指示内核应接受指向此套接口的连接请求。第二个参数规定了内核为此套接口排队的最大连接数。

参数backlog曾经规定为监听套接口上的未完成连接队列和已完成连接队列总和的最大值,但各个系统的定义方法都不尽相同;历史上常把backlog置为5,但对于繁忙的服务器是不够的;backlog的设置没有一个通用的方法,依情况而定,但不要设为0


10.accept函数

#include

int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);

返回:非负描述字—OK-1—出错。

 

accept从已完成连接队列头返回下一个连接,若已完成连接队列为空,则进程睡眠(套接口为阻塞方式时)。

参数cliaddraddrlen返回连接对方的协议地址,其中addrlen是值-结果参数,调用前addrlen所指的整数值要置为cliaddr所指的套接口结构的长度,返回时由内核修改。

accept成功执行后,返回一个连接套接口描述字。

如果对客户的协议地址没有兴趣,可以把cliaddraddrlen置为空指针。


11.close函数

#include

int close(int sockfd);

返回:0—OK-1—出错。

 

TCP套接口的close缺省功能是将套接口做上已关闭标记,并立即返回到进程。这个套接口描述字不能再为进程使用,但TCP将试着发送已排队待发的任何数据,然后按正常的TCP连接终止序列进行操作。

close把描述字的访问计数减1,当访问计数仍大于0时,close并不会引发TCP的四分组连接终止序列。若确实要发一个FIN,可以用函数shutdown


12.getsocknamegetpeername

#include

int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);

int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);

返回:0—OK-1—出错。

 

getsockname函数返回与套接口关联的本地协议地址。

getpeername函数返回与套接口关联的远程协议地址。

addrlen是值-结果参数。

使用场合:

·  在不调用bindTCP客户,当connect成功返回后,getsockname返回分配给此连接的本地IP地址和本地端口号;

·  在以端口号为0调用bind后,使用getsockname返回内核分配的本地端口号;

·  getsockname可用来获取某套接口的地址族;

·  在捆绑了通配IP地址的TCP服务器上,当连接建立后,可以使用getsockname获得分配给此连接的本地IP地址;

·  当一个服务器调用exec启动后,他获得客户身份的唯一途径是调用getpeername函数。


13.select函数

#include

#include

int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout);

返回:准备好描述字的正数目,0—超时,-1—出错。

 

结构timeval的定义:

struct timeval {

long tv_sec; /* seconds */

    long tv_usec; /* microseconds */

};

timeout取值的三种情况:

·  永远等下去:仅在有一个描述字准备好I/O时才返回,设置timeout为空指针;

·  等待固定时间:在有一个描述字准备好I/O时返回,但不超过由timeout参数所指定的秒数和微秒数;

·  根本不等待:检查描述字后立即返回,将timeout中的秒数和微秒数都设置为0

在等待过程中,若进程捕获了信号并从信号处理程序返回,等待一般被中断,为了可移植性,必须准备好select返回EINTR错误。

timeout的值在返回时并不会被select修改(const标志)。

readsetwritesetexceptset指定我们要让内核测试读、写和异常条件所需的描述字。

当前支持的异常条件有两个:

1.   套接口带外数据的到达;

2.   控制状态信息的存在,可从一个已置为分组方式的伪终端主端读到。

描述字集的使用:

数据类型:fd_set

void FD_ZERO(fd_set *fdset);

void FD_SET(int fd, fd_set *fdset);

void FD_CLR(int fd, fd_set *fdset);

void FD_ISSET(int fd, fd_set *fdset);

 

参数maxfdp1指定被测试的描述字个数,它的值是要被测试的最大描述字加1。描述字012maxfdp1-1都被测试。

readsetwritesetexceptset是值-结果参数,select修改三者所指的描述字集。所以,每次调用select时,我们都要将所有描述字集中关心的位置为1

套接口准备好读的条件:

·  套接口接收缓冲区中的数据字节数大于等于套接口接收缓冲区低潮限度的当前值。对这样的套接口的读操作将不阻塞并返回一个大于0的值(即准备好读入的数据量)。可以用套接口选项SO_RCVLOWAT来设置低潮限度,对于TCPUDP,缺省值为1

·  连接的读这一半关闭(接收了FINTCP连接)。对这样的套接口读操作将不阻塞并且返回0(即文件结束符

阅读(937) | 评论(0) | 转发(0) |
0

上一篇:php与正则表达式

下一篇:linux经典书籍

给主人留下些什么吧!~~