Chinaunix首页 | 论坛 | 博客
  • 博客访问: 424786
  • 博文数量: 47
  • 博客积分: 1669
  • 博客等级: 上尉
  • 技术积分: 585
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-04 23:27
文章分类

全部博文(47)

文章存档

2011年(23)

2010年(24)

分类: LINUX

2010-09-28 17:35:21

19.处理套接口的fcntl函数

#include
int fcntl(int fd, int cmd, … /* arg */);
返回:依赖于参数cmd—成功,-1—失败。

函数fcntl提供了如下关于网络编程的特性:

1.   非阻塞I/O:通过用F_SETFL命令设置O_NONBLOCK文件状态标志来设置套接口为非阻塞型。

2.   信号驱动I/O:用F_SETFL命令来设置O_ASYNC文件状态标志,这导致在套接口状态发生变化时内核生成信号SIGIO

3.   F_SETOWN命令设置套接口属主(进程ID或进程组ID),由它来接收信号SIGIOSIGURGSIGIO在设置套接口为信号驱动I/O型时生成,SIGURG在新的带外数据到达套接口时生成。

4.   F_GETOWN命令返回套接口的当前属主。

注意事项:

·  设置某个文件状态标志时,先取得当前标志,与新标志路逻辑或后再设置标志。

·  信号SIGIOSIGURG与其他信号不同之处在于,这两个信号只有在已使用命令F_SETOWN给套接口指派了属主后才会生成。F_SETOWN命令的整参数arg既可以是一个正整数,指明接收信号的进程ID,也可以是一个负整数,它的绝对值是接收信号的进程组ID

·  当一个新的套接口由函数socket创建时,他没有属主,但是当一个新的套接口从一个监听套接口创建时,套接口属主便由已连接套接口从监听套接口继承而来。


20.gethostbyname函数

#include
struct hostent *gethostbyname(const char *hostname);
返回:非空指针成功,空指针出错,同时设置h_errno

函数返回的非空指针指向的结构如下:
struct hostent {
    char *h_name; /*
规范主机名 */
    char **h_aliases; /*
别名列表 */
    int h_addrtype; /* AF_INET or AF_INET6 */
    int h_length; /*
地址长度 */
    char **h_addr_list; /* IPv4
IPv6地址结构列表 */
};
#define h_addr h_addr_list[0];

按照DNS的说法,gethostbyname执行一个对A记录的查询或对AAAA记录的查询,返回IPv4IPv6地址。

h_addr的定义是为了兼容,在新代码中不应使用。

返回的h_name称为主机的规范(canonical)名字。当返回IPv6地址时,h_addrtype被设置为AF_INET6,成员h_length被设置为16

gethostbyname的特殊之处在于:当发生错误时,他不设置errno,而是将全局整数h_errno设置为定义在头文件中的下列常值中的一个:

·  HOST_NOT_FOUND

·  TRY_AGAIN

·  NO_RECOVERY

·  NO_DATA(等同于NO_ADDRESS)。

有函数hstrerror(),它将h_errno的值作为唯一的参数,返回一个指向相应错误说明的const char *型指针。

 

DNS小常识:

DNS中的条目称为资源记录RRresource record),仅有少数几类RR会影响我们的名字与地址转换:

·  AA记录将主机名映射为32位的IPv4地址;

·  AAAAA”记录将主机名映射为128位的IPv6地址;

·  PTRPTR记录(称为指针记录)将IP地址映射为主机名;

·  MXMX记录指定一主机作为某主机的邮件交换器

·  CNAMECNAME代表“canonical name(规范名字),其常见的用法是为常用服务如ftpwww指派一个CNAME记录。


21.gethostbyname2函数

#include
struct hostent *gethostbyname2(const char *hostname, int family);
返回:非空指针成功,空指针出错,同时设置h_errno

该函数允许指定地址族,其他与gethostbyname相似。


22.gethostbyaddr函数

#include
struct hostent *gethostbyaddr(const char *addr, size_t len, int family);
返回:非空指针成功,空指针出错,同时设置h_error

函数根据一个二进制的IP地址并试图找出相应于此地址的主机名,我们关心的是规范主机名h_name

参数addr不是char *类型,而是一个真正指向含有IPv4IPv6地址的结构in_addrin6_addr的指针;len是该结构的大小,对于IPv44,对于IPv616family或为AF_INET或为AF_INET6

按照DNS的说法,该函数查询PTR记录。


23.uname函数

#include
int uname(struct utsname *name);
返回:非负值成功,-1—失败。

返回当前主机的名字,存放在如下的结构里:
#define UTS_NAMESIZE 16
#define UTS_NODESIZE 256
struct utsname {
    char sysname[UTS_NAMESIZE];
    char nodename[UTS_NODESIZE];
    char release[UTS_NAMESIZE];
    char version[UTS_NAMESIZE];
    char machine[UTS_NAMESIZE];
};

该函数经常与gethostbyname一起用来确定本机的IP地址:先调用uname获得主机名字,然后调用gethostbyname得到所有的IP地址。

获得本机IP地址的另一个方法是ioctl的命令SIOCGIFCONF


24.gethostname函数

#include
int gethostname(char *name, size_t namelen);
返回:0—成功,-1—失败。

返回当前主机的名字。name是指向主机名存储位置的指针,namelen是此数组的大小,如果有空间,主机名以空字符结束。

主机名的最大大小通常是头文件定义的常值MAXHOSTNAMELEN


25.getservbyname函数

#include
struct servent *getservbyname(const char *servname, const char *protoname);
返回:非空指针成功,空指针失败。

函数返回如下结构的指针:
struct servent {
    char *s_name;
    char **s_aliases;
    int s_port;
    char *s_proto;
};

服务名servname必须指定,如果还指定了协议(protoname为非空指针),则结果表项必须有匹配的记录。如果没有指定协议名而服务支持多个协议,则返回哪个端口是依赖于实现的。

结构中的端口号是以网络字节序返回的,所以在将它存储在套接口地址结构时,绝对不能调用htons


26.getservbyport函数

#include
struct servent *getservbyport(int port, const char *protname);
返回:非空指针成功,空指针出错。

port必须为网络字节序。例如:
sptr = getservbyport(htons(53), “udp”);


27.recvsend

#include
ssize_t recv(int sockfd, void *buf, size_t nbytes, int flags);
ssize_t send(int sockfd, void *buf, size_t nbytes, int flags);
返回:成功返回读入或写出的字节数,出错返回-1

前三个参数与readwrite相同,参数flags的值或为0,或由以下的一个或多个常值逻辑或构成:

flags

描述

recv

send

 

 

 

 

MSG_DONTROUTE

不查路由表

 

y

MSG_DONTWAIT

本操作不阻塞

y

y

MSG_OOB

发送或接收带外数据

y

y

MSG_PEEK

查看外来的消息

y

 

MSG_WAITALL

等待所有数据

y

 

下面说明每个标志的作用:

·  MSG_DONTROUTE:这个标志告诉内核目的主机在直接连接的本地网络上,不要查路由表。这是对提供这种特性的SO_DONTROUTE套接口选项的补充。该标志可以对单个输出操作提供这种特性,而套接口选项则针对某个套接口上的所有输出操作。

·  MSG_DONTWAIT:这个标志将单个I/O操作设为非阻塞方式,而不需要在套接口上打开非阻塞标志,执行I/O操作,然后关闭阻塞标志。

·  MSG_OOB:用send时,这个标志指明发送的是带外数据,用recv时,该标志指明要读的是带外数据而不是一般数据。

·  MSG_PEEK:这个标志可以让我们查看可读的数据,在recvrecvfrom后系统不会将这些数据丢弃。

·  MSG_WAITALL:由4.3BSD Reno引入,他告诉内核在没有读到请求的字节数之前不使读操作返回。如果系统支持这个标志,则可以去掉readn函数。即使设定了该标志,如果发生如下情况:(1)捕获了一个信号;(2)连接被终止;(3)在套接口上发生错误,这个函数返回的字节数仍会比请求的少。


28.readvwritev

#include
ssize_t readv(int filedes, const struct iovec *iov, int iovcnt);
ssize_t writev(int filedes, const struct iovec *iov, int iovcnt);
返回:读到或写出的字节数,出错返回-1

readvwritev可以让我们在一个函数调用中读或写多个缓冲区,这些操作被称为分散读和集中写。

iovec结构定义如下:
struct iovec {
    void *iov_base; /* starting address of buffer */
    size_t iov_len; /* size of buffer */
};

在具体的实现中对iovec结构数组的元素个数有限制,4.3BSD最多允许1024个,而Solaris2.5上限是16Posix.1g要求定义一个常值IOV_MAX,而且它的值不小于16

readvwritev可用于任何描述字。writev是一个原子操作,可以避免多次写引发的Nagle算法。


29.readmsgwritemsg

#include
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
ssize_t sendmsg(int sockfd, struct msghdr *msg, int flags);
返回:成功时为读入或写出的字节数,出错时为-1

这两个函数是最通用的套接口I/O函数,可以用recvmsg代替readreadvrecvrecvfrom,同样,各种输出函数都可以用sendmsg代替。

参数msghdr结构的定义如下:
struct msghdr {
    void *msg_name; /* protocol address */
    socklen_t msg_namelen; /* size of protocol address */
    struct iovec *msg_iov; /* scatter/gather array */
    size_t msg_iovlen; /* elements in msg_iov */
    void *msg_control; /* ancillary data; must be aligned for a cmsghdr structure */
    socklen_t msg_controllen; /* length of ancillary data */
    int msg_flags; /* flags returned by recvmsg() */
};

该结构源自4.3BSD Reno,也是Posix.1g中所说明的,有些系统仍使用一种老的msghdr结构,此种结构中没有msg_flags成员,而且 msg_controlmsg_controllen成员分别被叫做msg_accrightsmsg_accrightslen。老系统中支持的唯一一种辅助数据形式是文件描述字(称为访问权限)的传递。

msg_namemsg_namelen成员用于未经连接的套接口,他们与 recvfromsendto的第五和第六个参数类似:msg_name指向一个套接口地址结构,如果不需要指明协议地址,msg_name应被设置为空指针,msg_namelensendmsg是一个值,而对recvmsg是一个值-结果参数。

msg_iovmsg_iovlen成员指明输入或输出的缓冲区数组。

msg_controlmsg_controllen指明可选的辅助数据的位置和大小,msg_controllenrecvmsg是一个值-结果参数。

msg_flags只用于revmsg,调用recvmsg时,flags参数被拷贝到msg_flags成员,而且内核用这个值进行接收处理,接着它的值会根据recvmsg的结果而更新,sendmsg会忽略msg_flags成员,因为它在进行输出处理时使用flags参数。

内核检查的flags和返回的msg_flags如下表所示:

标志

send flags
sendto flags

sendmsg flags
中检查

recv flags
recvfrom flags

recvmsg flags
中检查

recvmsg msg_flags
中返回

 

 

 

 

MSG_DONTROUTE

y

 

 

MSG_DONTWAIT

y

y

 

MSG_PEEK

 

y

 

MSG_WAITALL

 

y

 

MSG_EOR

y

 

y

MSG_OOB

y

y

y

MSG_BCAST

 

 

y

MSG_MCAST

 

 

y

MSG_TRUNC

 

 

y

MSG_CTRUNC

 

 

y

前四个标志只检查不返回,下两个标志既检查又返回,最后四个只返回。返回的六个标志含义如下:

·  MSG_BCAST:当收到的数据报是一个链路层的广播或其目的IP地址为广播地址时,将返回此标志。

·  MSG_MCAST:当收到的数据报是链路层的多播时,将返回该标志。

·  MSG_TRUNC:这个标志在数据报被截断时返回。

·  MSG_CTRUNC:这个标志在辅助数据被截断时返回。

·  MSG_EOR:如果返回的数据不是一个逻辑记录的结尾,该标志被清位,反之则置位。TCP不使用这个标志,因为它是一种字节流协议。

·  MSG_OOB:这个标志不是为TCP的带外数据返回的,它用于其他协议族(譬如OSI协议等)。

具体的实现可能会在msg_flags中返回一些输入的flags的标志,所以我们应该只检查那些感兴趣的标志的值。

 

管理员在2009年8月13日编辑了该文章文章。
-->
阅读(1779) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-09-29 12:55:12

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com

chinaunix网友2010-09-29 12:55:01

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com