Chinaunix首页 | 论坛 | 博客
  • 博客访问: 334228
  • 博文数量: 214
  • 博客积分: 4258
  • 博客等级: 上校
  • 技术积分: 2021
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-02 09:16
个人简介

http://blog.csdn.net/ly21st http://ly21st.blog.chinaunix.net

文章分类

全部博文(214)

文章存档

2018年(16)

2015年(1)

2014年(2)

2012年(22)

2011年(173)

分类: LINUX

2011-09-19 19:37:02

7.1 概述

获取和设置影响套接口的选项:

1)函数getsockoptsetsockopt

2)函数fcntl

3)函数ioctl

7.3 检查选项是否受支持并获取缺省值

/* include checkopts1 */

/* *INDENT-OFF* */

#include       "unp.h"

#include                   /* for TCP_xxx defines */

 

union val {

  int                           i_val;

  long                        l_val;

  struct linger             linger_val;

  struct timeval   timeval_val;

} val;

 

static char    *sock_str_flag(union val *, int);

static char    *sock_str_int(union val *, int);

static char    *sock_str_linger(union val *, int);

static char    *sock_str_timeval(union val *, int);

 

struct sock_opts {

  const char          *opt_str;

  int             opt_level;

  int             opt_name;

  char   *(*opt_val_str)(union val *, int);

} sock_opts[] = {

       { "SO_BROADCAST",            SOL_SOCKET,  SO_BROADCAST,   sock_str_flag },

       { "SO_DEBUG",                SOL_SOCKET,  SO_DEBUG,              sock_str_flag },

       { "SO_DONTROUTE",            SOL_SOCKET,  SO_DONTROUTE,   sock_str_flag },

       { "SO_ERROR",                SOL_SOCKET,  SO_ERROR,              sock_str_int },

       { "SO_KEEPALIVE",        SOL_SOCKET,  SO_KEEPALIVE,      sock_str_flag },

       { "SO_LINGER",               SOL_SOCKET,  SO_LINGER,             sock_str_linger },

       { "SO_OOBINLINE",              SOL_SOCKET,  SO_OOBINLINE,     sock_str_flag },

       { "SO_RCVBUF",                    SOL_SOCKET,  SO_RCVBUF,           sock_str_int },

       { "SO_SNDBUF",                    SOL_SOCKET,  SO_SNDBUF,           sock_str_int },

       { "SO_RCVLOWAT",              SOL_SOCKET,  SO_RCVLOWAT,     sock_str_int },

       { "SO_SNDLOWAT",              SOL_SOCKET,  SO_SNDLOWAT,     sock_str_int },

       { "SO_RCVTIMEO",        SOL_SOCKET,  SO_RCVTIMEO,       sock_str_timeval },

       { "SO_SNDTIMEO",        SOL_SOCKET,  SO_SNDTIMEO,       sock_str_timeval },

       { "SO_REUSEADDR",             SOL_SOCKET,  SO_REUSEADDR,    sock_str_flag },

#ifdef     SO_REUSEPORT

       { "SO_REUSEPORT",              SOL_SOCKET,  SO_REUSEPORT,     sock_str_flag },

#else

       { "SO_REUSEPORT",              0,                  0,                         NULL },

#endif

       { "SO_TYPE",                   SOL_SOCKET,  SO_TYPE,          sock_str_int },

       { "SO_USELOOPBACK",              SOL_SOCKET,  SO_USELOOPBACK,     sock_str_flag },

       { "IP_TOS",                       IPPROTO_IP,     IP_TOS,                     sock_str_int },

       { "IP_TTL",                        IPPROTO_IP,     IP_TTL,               sock_str_int },

#ifdef     IPV6_DONTFRAG

       { "IPV6_DONTFRAG",           IPPROTO_IPV6,IPV6_DONTFRAG,   sock_str_flag },

#else

       { "IPV6_DONTFRAG",           0,                  0,                         NULL },

#endif

#ifdef     IPV6_UNICAST_HOPS

       { "IPV6_UNICAST_HOPS",   IPPROTO_IPV6,IPV6_UNICAST_HOPS,sock_str_int },

#else

       { "IPV6_UNICAST_HOPS",   0,                  0,                         NULL },

#endif

#ifdef     IPV6_V6ONLY

       { "IPV6_V6ONLY",          IPPROTO_IPV6,IPV6_V6ONLY, sock_str_flag },

#else

       { "IPV6_V6ONLY",          0,                  0,                         NULL },

#endif

       { "TCP_MAXSEG",                 IPPROTO_TCP,TCP_MAXSEG,          sock_str_int },

       { "TCP_NODELAY",        IPPROTO_TCP,TCP_NODELAY,       sock_str_flag },

#ifdef     SCTP_AUTOCLOSE

       { "SCTP_AUTOCLOSE",        IPPROTO_SCTP,SCTP_AUTOCLOSE,sock_str_int },

#else

       { "SCTP_AUTOCLOSE",        0,                  0,                         NULL },

#endif

#ifdef     SCTP_MAXBURST

       { "SCTP_MAXBURST",          IPPROTO_SCTP,SCTP_MAXBURST,       sock_str_int },

#else

       { "SCTP_MAXBURST",          0,                  0,                         NULL },

#endif

#ifdef     SCTP_MAXSEG

       { "SCTP_MAXSEG",        IPPROTO_SCTP,SCTP_MAXSEG,     sock_str_int },

#else

       { "SCTP_MAXSEG",        0,                  0,                         NULL },

#endif

#ifdef     SCTP_NODELAY

       { "SCTP_NODELAY",             IPPROTO_SCTP,SCTP_NODELAY,   sock_str_flag },

#else

       { "SCTP_NODELAY",             0,                  0,                         NULL },

#endif

       { NULL,                                   0,                  0,                         NULL }

};

/* *INDENT-ON* */

/* end checkopts1 */

 

/* include checkopts2 */

int

main(int argc, char **argv)

{

       int                               fd;

       socklen_t                     len;

       struct sock_opts  *ptr;

 

       fd = Socket(AF_INET,SOCK_STREAM,0);   //added by liyuan

 

       for (ptr = sock_opts; ptr->opt_str != NULL; ptr++) {

              printf("%s: ", ptr->opt_str);

              if (ptr->opt_val_str == NULL)

                     printf("(undefined)\n");

              else {

                     switch(ptr->opt_level) {

                     case SOL_SOCKET:

                     case IPPROTO_IP:

                     case IPPROTO_TCP:

                            fd = Socket(AF_INET, SOCK_STREAM, 0);

                            break;

#ifdef      IPV6

                     case IPPROTO_IPV6:

                            fd = Socket(AF_INET6, SOCK_STREAM, 0);

                            break;

#endif

#ifdef      IPPROTO_SCTP

                     case IPPROTO_SCTP:

                            fd = Socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);

                            break;

#endif

                     default:

                            err_quit("Can't create fd for level %d\n", ptr->opt_level);

                     }

 

                     len = sizeof(val);

                     if (getsockopt(fd, ptr->opt_level, ptr->opt_name,

                                             &val, &len) == -1) {

                            err_ret("getsockopt error");

                     } else {

                            printf("default = %s\n", (*ptr->opt_val_str)(&val, len));

                     }

                     close(fd);

              }

       }

       exit(0);

}

/* end checkopts2 */

 

/* include checkopts3 */

static char    strres[128];

 

static char    *

sock_str_flag(union val *ptr, int len)

{

/* *INDENT-OFF* */

       if (len != sizeof(int))

              snprintf(strres, sizeof(strres), "size (%d) not sizeof(int)", len);

       else

              snprintf(strres, sizeof(strres),

                             "%s", (ptr->i_val == 0) ? "off" : "on");

       return(strres);

/* *INDENT-ON* */

}

/* end checkopts3 */

 

static char    *

sock_str_int(union val *ptr, int len)

{

       if (len != sizeof(int))

              snprintf(strres, sizeof(strres), "size (%d) not sizeof(int)", len);

       else

              snprintf(strres, sizeof(strres), "%d", ptr->i_val);

       return(strres);

}

 

static char    *

sock_str_linger(union val *ptr, int len)

{

       struct linger   *lptr = &ptr->linger_val;

 

       if (len != sizeof(struct linger))

              snprintf(strres, sizeof(strres),

                             "size (%d) not sizeof(struct linger)", len);

       else

              snprintf(strres, sizeof(strres), "l_onoff = %d, l_linger = %d",

                             lptr->l_onoff, lptr->l_linger);

       return(strres);

}

 

static char    *

sock_str_timeval(union val *ptr, int len)

{

       struct timeval       *tvptr = &ptr->timeval_val;

 

       if (len != sizeof(struct timeval))

              snprintf(strres, sizeof(strres),

                             "size (%d) not sizeof(struct timeval)", len);

       else

              snprintf(strres, sizeof(strres), "%d sec, %d usec",

                             tvptr->tv_sec, tvptr->tv_usec);

       return(strres);

}

7.5 基本套接口选项

以下面的建议来总结对套接口选线的讨论:

1)在所有tcp服务中,在调用bind之前设置SO_REUSEADDR套接口选项;

2)当编写一个同一时刻在同一主机上可运行多次的多播应用程序时,设置SO_REUSEADDR套接口选项,并将本组的多播地址作为本地ip地址绑定。

7.10 fcntl函数

int  fcntl ( int fd, int  cmd,  …/* int arg */);

返回: 依赖于参数 cmd , -1  --------出错

每个描述字(包括套接口描述字)都有一组命令F_GETFL取得和F_SETFL设置的文件标志。影响套接口的两个标志是:

O_NONBLOCK   -------费阻塞I/O

O_ASYNC       -------信号驱动I/O

信号SIGIOSIGURG与其他信号不同之处是,这两个信号仅在已用命令F_SETOWN给套接口指派了属主后才会生成。

       当一个新的套接口由函数socket创建时,它没有属主,但是当一个新的套接口从一个监听套接口创建时,套接口属主便由已连接套接口从监听套接口继承而来(许多套接口选项也这样)。

7.11 小结

       SO_LINGER套接口选项使我们能更好控制函数close返回的时机,让我们可以强制发送一个RST而不是tcp的四分组连接终止序列。我们必须小心发送RST,因为这避免了tcpTIME_WAIT状态。也有套接口选项无法提供我们所需要信息的情况,此时就要求有应用级的ACK

       每个tcp套接口都有一个发送缓冲区和一个接受缓冲区,每个udp套接口都有一个接受缓冲区。SO_SNDBUFSO_RCVBUF套接口选项让我们可以改变这些缓冲区的大小。

阅读(265) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~