博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
网络编程之 Socket函数 (二)
阅读量:2176 次
发布时间:2019-05-01

本文共 9161 字,大约阅读时间需要 30 分钟。

1. 概述

             在《网络编程之 socket函数 (一)》 中所讲到的所有socket函数并不涉及设置socket属性,而只是定义了客户端和服务器端的socket流程。服务器端和客户端的使用流程如下:
            客户端:
                 socket()->connect()->send()/recv()->close()
            服务器端:
                 socket()->bind()->listen()->accept()->close()
                                                                      |
                                                                      |  ->send()/recv()->close()
                                                                      |
                                                                      |  ->select()->send()/recv()->close()

            下面介绍的一些函数则涉及socket的属性设置。事实上socket的不同属性对socket的行为影响巨大。

2. 函数介绍

            控制套接字属性的函数包括:
           
1. getsockopt(): 用于查询指定的套接字一个特定的套接字选项的当前值。
           
2. setsockopt(): 用于为指定的套接字设定一个特定的套接字选项。
           
3. fcntl(): 向打开的文件fd发送命令,更改其属性。在linux下所有的一切都被认为是文件,socket也不例外。可以认为fcntl()是ioctl()的一个子集。
           
4. octl(): 此函数像个杂货铺,对设备的控制通常都通过这个函数来实行,具体对设备的操作方式取决于设备驱动程序的编写。fcntl()和ioctl()的区别如同fread()和read()函数的关系。
           
5. ioctlsocket(): 此函数只能用于windows平台,相当于linux下套接口函数ioctl()的一个子集。

2.1 setsockopt()

#include 
#include
int getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen);int setsockopt(int sock, int level, int optname, const void *optval, socklen_t optlen);
            
参数sock: 将要被设置或者获取选项的套接字。
            
参数level: 选项所在的协议层。level指定控制套接字的层次.可以取三种值: 
               
SOL_SOCKET: 通用套接字选项. 
                I
PPROTO_IP:  IP选项. 
               
IPPROTO_TCP: TCP选项. 
            
参数optname:需要访问的选项名。
            
参数optval:对于getsockopt(),指向返回选项值的缓冲。对于setsockopt(),指向包含新选项值的缓冲。
            
参数optlen:对于getsockopt(),作为入口参数时,选项值的最大长度。作为出口参数时,选项值的实际长度。对于setsockopt(),现选项的长度。

            
SOL_SOCKET通用套接字选项,可以认为是应用socket应用层的选项,包括以下各选项:
======================================================================== 
选项名称        说明                  数据类型 
======================================================================== 
SO_ACCEPTCONN                 套接口正在用listen()监听                                     int
SO_BROADCAST                    允许发送广播数据                                                 int 
SO_DEBUG                              允许调试                                                                int 
SO_DONTROUTE                    不查找路由,禁止选径                                         int 
SO_ERROR                              获得套接字错误                                                    int 
SO_KEEPALIVE                       保持连接                                                                int 
SO_LINGER                              延迟关闭连接                                                       struct linger 
SO_OOBINLINE       带外数据放入正常数据流                                     int 
SO_RCVBUF                             接收缓冲区大小                                                   int 
SO_SNDBUF                             发送缓冲区大小                                                   int 
(SO_RCVLOWAT)                    接收缓冲区下限                                                    int 
(SO_SNDLOWAT)                   发送缓冲区下限                                                    int 
(SO_RCVTIMEO)                     接收超时                                                                struct timeval 
(SO_SNDTIMEO)                     发送超时                                                                struct timeval 
SO_REUSERADDR                 允许重用本地地址和端口                                      int 
SO_TYPE                                  获得套接字类型                                                    int 
SO_BSDCOMPAT                   与BSD系统兼容                                                    int 

======================================================================== 

           注:上述括号中的选项表示window下不支持的但linux支持之选项

           
 IPPROTO_IP选项,可以认为是操作系统为应用程序开的接口,用于控制底层IP层的一些特性,包括以下各列:
======================================================================== 
选项名称        说明                  数据类型 
======================================================================== 
IP_HDRINCL                        在数据包中包含IP首部                                          int 
(IP_OPTINOS)                     IP首部选项                                                            int 
IP_TOS                                  服务类型 
IP_TTL                                   生存时间                                                               int 
======================================================================== 

           注:上述括号中的选项表示window下不支持的但linux支持之选项

            
IPPROTO_TCP选项,可以认为是操作系统为应用程序开的接口,用于控制底层TCP层的一些特性,包括以下各列:
======================================================================== 
选项名称        说明                  数据类型 
======================================================================== 
(TCP_MAXSEG)                  TCP最大数据段的大小                                        int 
TCP_NODELAY                  不使用Nagle算法                                                 int 

======================================================================== 

           注:上述括号中的选项表示window下不支持的但linux支持之选项

            
返回值(Linux):
            成功执行时,返回0。失败返回-1,errno被设为以下的某个值   
               EBADF:sock不是有效的文件描述词
               EFAULT:optval指向的内存并非有效的进程空间
               EINVAL:在调用setsockopt()时,optlen无效
               ENOPROTOOPT:指定的协议层不能识别选项
               ENOTSOCK:sock描述的不是套接字
            
返回值(Windows):
               WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
               WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
               WSAEFAULT:optlen参数非法。
               WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
               WSAENOPROTOOPT:未知或不支持选项。其中,SOCK_STREAM类型的套接口不支持SO_BROADCAST选项,SOCK_DGRAM类型的套接口不支持SO_ACCEPTCONN、SO_DONTLINGER 、SO_KEEPALIVE、SO_LINGER和SO_OOBINLINE选项。
              WSAENOTSOCK:描述字不是一个套接口。
            
注意:
            当设置TCP套接口接收缓冲区的大小时,函数调用顺序是很重要的,因为TCP的窗口规模选项是在建立连接时用SYN与对方互换得到的。对于客户,SO_RCVBUF选项必须在connect之前设置;对于服务器,SO_RCVBUF选项必须在listen前设置。

2.2 fcntl()

#include 
#include
int fcntl(int fd, int cmd);int fcntl(int fd, int cmd, long arg);int fcntl(int fd,int cmd, struct flock *lock);
           
 参数fd: 是被参数cmd操作的描述符.

            参数cmd: 对描述符操作的命令码。有如下选项:

==============================================================

            
FD_DUPFD                                                                     复制文件描述符
           
 F_GETFD或者
F_SETFD                                                获得/设置文件描述符
            
F_GETFL或者
F_SETFL                                                获得/设置文件状态值
            
F_GETOWN
F_SETOWN                                          获得/设置异步I/O所有权
            
F_GETLK或者
F_SETLK或者
F_SETLKW                  获得/设置文件记录锁

            F_GETLEASE或者F_SETLEASE                                获得/设置文件租约

===============================================================

            参数arg: 参数cmd对应的命令参数,有些命令存在此arg,有些不存在。

           
1. F_GETFL和F_SETFL的标志如下面的描述:
               
O_NONBLOCK        非阻塞I/O;如果read(2)调用没有可读取的数据,或者如果write(2)操作将阻塞,read或write调用返回-1和EAGAIN错误
               
O_APPEND              强制每次写(write)操作都添加在文件大的末尾,相当于open(2)的O_APPEND标志
               
O_DIRECT               最小化或去掉reading和writing的缓存影响.系统将企图避免缓存你的读或写的数据.如果不能够避免缓存,那么它将最小化已经被缓存了的数据造 成                                                       的影响.如果这个标志用的不够好,将大大的降低性能
               
O_ASYNC                当I/O可用的时候,允许SIGIO信号发送到进程组,例如:当有数据可以读的时候
             
注意:
             在修改文件描述符标志或文件状态标志时必须谨慎,先要取得现在的标志值,然后按照希望修改它,最后设置新标志值。不能只是执行F_SETFD或F_SETFL命令,这样会关闭以前设置的标志位。
             
2. F_GETLK/F_SETLK/F_SETLKW 命令及标志如下面的描述:
                   
F_GETLK          通过第三个参数arg(一个指向flock的结构体)取得第一个阻塞lock description指向的的锁.取得的信息将覆盖传到fcntl()的flock结构的信息.如果没有发现能够阻止本次锁(flock)生成的锁,这 个结构将不被改变,除非锁的类型被设置成F_UNLCK.   
                   
F_SETLK          按照指向结构体flock的指针的第三个参数arg所描述的锁的信息设置或者清除一个文件segment锁.F_SETLK被用来实现共享(或读)锁 (F_RDLCK)或独 占(写)锁(F_WRLCK),同样可以去掉这两种锁(F_UNLCK).如果共享锁或独占锁不能被设置,fcntl()将立即返 回EAGAIN.
                   
F_SETLKW          除了共享锁或独占锁被其他的锁阻塞这种情况外,这个命令和F_SETLK是一样的.如果共享锁或独占锁被其他的锁阻塞,进程将等待直到这个请求能够   完成. 当fcntl()正在等待文件的某个区域的时候捕捉到一个信号,如果这个信号没有被指定SA_RESTART,fcntl将被中断.
               当一个共享锁被set到一个文件的某段的时候,其他的进程可以set 共享锁到这个段或这个段的一部分.共享所阻止任何其他进程set独占锁到这段保护区域的任何部分.如果文件描述符没有以读的访问方式打开的话,共享锁的设置请求会失败.
               独占锁阻止任何其他的进程在这段保护区域任何位置设置共享锁或独占锁.如果文件描述符不是以写的访问方式打开的话,独占锁的请求会失败。
             
参数flock的指针:
              flcok结构定义如下:
struct flcok {        short int l_type; /* 锁定的状态*/       //这三个参数用于分段对文件加锁,若对整个文件加锁,则:l_whence=SEEK_SET,l_start=0,l_len=0;       short int l_whence;/*决定l_start位置*/        off_t l_start; /*锁定区域的开头位置*/        off_t l_len; /*锁定区域的大小*/       pid_t l_pid; /*锁定动作的进程*/ };
              其中l_type 有三种状态: 
               
F_RDLCK 建立一个供读取用的锁定 
               
F_WRLCK 建立一个供写入用的锁定 
               
F_UNLCK 删除之前建立的锁定
              l_whence 也有三种方式: 
               
SEEK_SET 以文件开头为锁定的起始位置。 
               
SEEK_CUR 以目前文件读写位置为锁定的起始位置 
               
SEEK_END 以文件结尾为锁定的起始位置。 
              
返回值:
              与命令有关。如果出错,所有命令都返回-1,如果成功则返回某个其他值。
              下列三个命令有特定返回值:F_DUPFD,F_GETFD,F_GETFL以及F_GETOWN。
              第一个返回新的文件描述符,
              第二个返回相应标志,
              最后一个返回一个正的进程ID或负的进程组ID。
               fcntl是控制文件属性的专用命令,和socket相关的选项,用的比较多的可能就是设置阻塞或者非阻塞socket了。如下:
fcntl(fd, F_SETFL, O_NONBLOCK)

2.3 ioctl()

#include
int ioctl(int handle, int cmd, char* argp);
              
参数handle: 是被参数cmd操作的描述符.
              
参数cmd: 对描述符操作的命令码。有如下选项:
             
 参数argp: 参数cmd对应的命令参数,有些命令存在argp,有些不存在
              cmd和argp的关系如下:
============================================================================================
类别
Request
说明
数据类型
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
套接口                    
SIOCATMARK                       是否位于带外标记                                                int
                               
SIOCSPGRP                         设置套接口的进程ID 或进程组ID                        int
                               
SIOCGPGRP                         获取套接口的进程ID 或进程组ID                        int
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
文件                    
   FIONBIO                                 设置/ 清除非阻塞I/O 标志                                     int
                             
  FIOASYNC                             设置/ 清除信号驱动异步I/O 标志                         int
                               
FIONREAD                             获取接收缓存区中的字节数                                int
                               
FIOSETOWN                         设置文件的进程ID 或进程组ID                            int
                               
FIOGETOWN                         获取文件的进程ID 或进程组ID                           int
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
接口                      
 SIOCGIFCONF                       获取所有接口的清单                                           struct ifconf
                               
SIOCSIFADDR                       设置接口地址                                                       struct ifreq
                               
SIOCGIFADDR                       获取接口地址                                                       struct ifreq
                               
SIOCSIFFLAGS                      设置接口标志                                                       struct ifreq
                               
SIOCGIFFLAGS                      获取接口标志                                                       struct ifreq
                               
SIOCSIFDSTADDR               设置点到点地址                                                   struct ifreq
                               
SIOCGIFDSTADDR               获取点到点地址                                                   struct ifreq
                               
SIOCGIFBRDADDR              获取广播地址                                                       struct ifreq
                               
SIOCSIFBRDADDR              设置广播地址                                                       struct ifreq
                               
SIOCGIFNETMASK               获取子网掩码                                                       struct ifreq
                               
SIOCSIFNETMASK               设置子网掩码                                                       struct ifreq
                               
SIOCGIFMETRIC                   获取接口的测度                                                   struct ifreq
                               
SIOCSIFMETRIC                   设置接口的测度                                                   struct ifreq
                               
SIOCGIFMTU                         获取接口MTU                                                       struct ifreq
                               
SIOCxxx                                  (还有很多取决于系统的实现)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
ARP                        
SIOCSARP                           创建/修改ARP 表项                                               struct arpreq         
                               
SIOCGARP                           获取ARP 表项                                                       struct arpreq
                               
SIOCDARP                           删除ARP 表项                                                       struct arpreq
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
路由                        
SIOCADDRT                         增加路径                                                               struct rtentry
                               
SIOCDELRT                         删除路径                                                               struct rtentry
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
流                              
I_xxx
-----------------------------------------------------------------------------------------------------------------------------------------------------------------

2.4 ioctlsocket()

#include 
int PASCAL FAR ioctlsocket( SOCKET s, long cmd, u_long FAR* argp);
            参数s:一个标识套接口的描述字。
            参数cmd:对套接口s的操作命令。有如下选择:
                FIONBIO: 允许或禁止套接口s的非阻塞模式。argp指向一个无符号长整型,如允许非阻塞模式则非零,如禁止非阻塞模式则为零。当创建一个套接口时,它就处于阻 塞模式(也就是说非阻塞模式被禁止)。这与BSD套接口是一致的。WSAAsynSelect()函数将套接口自动设置为非阻塞模式。如果已对一个套接口进行了WSAAsynSelect() 操作,则任何用ioctlsocket()来把套接口]重新设置成阻塞模式的试图将以WSAEINVAL失败。为了把套接口重新设置成阻塞模式,应用程序必须首先用WSAAsynSelect()调用(IEvent参数置为0)来禁止WSAAsynSelect()。
            FIONREAD:确定套接口s自动读入的数据量。argp指向一个无符号长整型,其中存有ioctlsocket()的返回值。如果s是SOCKET_STREAM类型,则FIONREAD返回在一次recv()中所接收的所有数据量。这通常与套接口中排队的数据总量相同。如果S是SOCK_DGRAM 型,则FIONREAD返回套接口上排队的第一个数据报大小。

            SIOCATMARK:确实是否所有的带外数据都已被读入。这个命令仅适用于SOCK_STREAM类型的套接口,且该套接口已被设置为可以在线接收带外数据 (SO_OOBINLINE)。如无带外数据等待读入,则该操作返回TRUE真。否则的话返回FALSE假,下一个recv()或recvfrom()操作将检索“标记”前一些或所有数据。应用程序可用   SIOCATMARK操作来确定是否有数据剩下。如果在“紧急”(带外)数据[前有常规数据,则按序接收这些数据(请注意,recv()和recvfrom() 操作不会在一次调用中混淆常规数据与带外数]据)。argp指向一个BOOL型数,ioctlsocket()在其中存入返回值。

             
参数argp:指向cmd命令所带参数的指针。
(版权所有,转载时请注明作者和出处http://blog.csdn.net/arau_sh/article/details/12030951)
你可能感兴趣的文章
【托业】【新东方全真模拟】01~02-----P5~6
查看>>
【托业】【新东方全真模拟】03~04-----P5~6
查看>>
【托业】【新东方托业全真模拟】TEST05~06-----P5~6
查看>>
【托业】【新东方托业全真模拟】TEST09~10-----P5~6
查看>>
【托业】【新东方托业全真模拟】TEST07~08-----P5~6
查看>>
solver及其配置
查看>>
JAVA多线程之volatile 与 synchronized 的比较
查看>>
Java集合框架知识梳理
查看>>
笔试题(一)—— java基础
查看>>
Redis学习笔记(三)—— 使用redis客户端连接windows和linux下的redis并解决无法连接redis的问题
查看>>
Intellij IDEA使用(一)—— 安装Intellij IDEA(ideaIU-2017.2.3)并完成Intellij IDEA的简单配置
查看>>
Intellij IDEA使用(二)—— 在Intellij IDEA中配置JDK(SDK)
查看>>
Intellij IDEA使用(三)——在Intellij IDEA中配置Tomcat服务器
查看>>
Intellij IDEA使用(四)—— 使用Intellij IDEA创建静态的web(HTML)项目
查看>>
Intellij IDEA使用(五)—— Intellij IDEA在使用中的一些其他常用功能或常用配置收集
查看>>
Intellij IDEA使用(六)—— 使用Intellij IDEA创建Java项目并配置jar包
查看>>
Eclipse使用(十)—— 使用Eclipse创建简单的Maven Java项目
查看>>
Eclipse使用(十一)—— 使用Eclipse创建简单的Maven JavaWeb项目
查看>>
Intellij IDEA使用(十三)—— 在Intellij IDEA中配置Maven
查看>>
面试题 —— 关于main方法的十个面试题
查看>>