阻塞与非阻塞我的小结

1.connect函数响应中断返回后仍然回到函数的调用。
       实践证实,对于一个非阻塞的socket,若是在调用connect函数时,若是发生中断,这函数响应中断,但当中断返回时,继续connect函数的调用,直到connect超时失败或接收到错误ICMP包或链接成功服务器

        2.accept()
        若是侦听进程是非阻塞模式工做,当调用accept()函数接收来自客户端的请求后,返回的socket套接字,默认为阻塞的工做模式。网络

1、阻塞模型
    可能发生阻塞的套接口调用分为四种:
    1>.输入操做:read、readv、recv、recvfrom和recvmsg函数
    2>.输出操做:write、writev、send、sendto和sendmsg函数
    3>.接收外来链接:accept()函数
    4>.初始化外出的链接:connect()函数数据结构

2、I/O模型
    1.阻塞I/O
    2.非阻塞I/O
    3.I/O复用(select函数)
    4.信号驱动I/O(SIGIO)
    5.异步I/O异步

3、I/O复用模型的应用场合
    1.当客户处理多个描述字时(通常是交互式输入和网络套接口),必须使用I/O复用。
    2.一个客户同时处理多个套接口
    3.若是一个TCP服务器既要处理侦听套接口,又要处理已链接套接口,通常也要用到I/O复用。
    4.若是一个服务器既要处理TCP,又要处理UDP,通常也要使用I/O复用。
    5.若是一个服务器要处理多个服务或者多个协议(inetd守护进程)。socket

4、拒绝服务型攻击
    服务器某一个时刻阻塞于只处理单个客户,而不能处理其余客户的需求,这就致使了拒绝服务型攻击,可能的解决办法是:(a)使用非阻塞I/O模型;(b)让 每一个客户由单独的控制线程提供服务(例如,建立子进程或线程来为每一个客户提供服务);(c)对I/O操做设置超时。函数

5、connect()函数
    
1.阻塞模式
    客户端调用connect()函数将激发TCP的三路握手过程,但仅在链接创建成功或出错时才返回。返回的错误可能有如下几种状况:
    1>.若是TCP客户端没有接收到SYN分节的响应,则返回ETIMEDOUT,阻塞模式的超时时间在75秒(4.4BSD内核)到几分钟之间。
    2>.若是对客户的SYN的响应时RST,则代表该服务器主机在咱们指定的端口上没有进程在等待与之链接(例如服务器进程也许没有启动),这称为硬错,客户一接收到RST,立刻就返回错误ECONNREFUSED.
    3>.若是某客户发出的SYN在中间的路由器上引起了一个目的地不可达ICMP错误,屡次尝试发送失败后返回错误号为EHOSTUNREACH或ENETUNREACH.spa

附加:产生RST的三种状况,一是SYN到达某端口但此端口上没有正在侦听的服务器、二是TCP想取消一个已有链接、三是TCP接收了一个根本不存在的链接上的分节。线程

2.非阻塞模式
    采用非阻塞的工做模式要考虑一下两种状况:
1>.若是是链接本机,则调用connect()函数会马上创建。
2>.若是服务器是网络中的用户,则调用connect()函数须要从几个毫秒的局域网到几百毫秒或几秒的广域网。而且函数会马上返回EINPROCESS错误,但TCP通讯的三路握手过程正在进行,因此可使用select函数来检查这个链接是否创建成功。
    源自Berkeley的实现有两条与select函数和非阻塞相关的规则:
1>.当链接成功创建时,描述字变成可写。
2>.当链接创建出错时,描述字变成便可读又可写。code

6、accept()函数
1.阻塞模式
    若是在一个阻塞套接口上调用accept()函数,并且没有新的链接,进程会进入睡眠状态。orm

2.非阻塞模式
    若是在一个非阻塞套接口上调用accept()函数,并且没有新的链接,将返回EWOULDBLOCK错误。

3.一种非阻塞模式例子的问题及解决办法
    问题描述:在服务器端侦听套接口采用阻塞的方式工做,而且使用select检测是否有已经创建起的链接,若是有则调用accept()函数接收该链接,问 题是若是客户端首先调用connect()函数链接服务器后马上又调用close()函数关闭该链接,而在服务器端,在select()函数返回和调用 accept()函数之间,接收到客户端的断开,则会删除该套接口在已链接套接口中的内容,因此服务器将会阻塞在accept()函数,直到有客户链接才 返回。
    解决办法:(1).若是用select来获知什么时候有链接已就绪能够accept时,老是把侦听套接口置为非阻塞,同时(2).在后面的accept调用中 忽略如下错误:EWOULDBLOCK(Berkeley的实如今客户放弃链接时出现的错误)、ECONNABORTED(Posix.1g的实如今客户 放弃链接时出现的错误)、EPROTO(SVR4的实如今客户放弃链接时出现的错误)和EINTR(若是信号被捕获)。

7、select()函数
    select()函数准备好读的条件:
    1>.套接口有数据可读
    2>.该链接的读这一半关闭(也就是接收了FIN的TCP链接)。对这样的套接口进行读操做将不阻塞并返回0(也就是返回EOF)。
    3>.该套接口是一个侦听套接口且已完成的链接数不为0。
    4>.其上有一个套接口错误待处理,对这样的套接口的读操做将不阻塞并返回-1,并设置errno,能够经过设置SO_ERROR选项调用getsockopt函数得到。

    select()函数准备好写的条件:
    1>.套接口有可用于写的空间。
    2>.该链接的写这一半关闭,对这样的套接口进行写操做将产生SIGPIPE信号。
    3>.该套接口使用非阻塞的方式connect创建链接,而且链接已经异步创建,或则connect已经以失败了结。
    4>.其上有一个套接口错误待处理。

8、read()函数和recv函数
    read()函数返回值表明的意义:
    1>.若是对方TCP发送数据,则套接口就变为可读且read返回大于0的值(即数据的字节数)。
    2>.若是对方TCP发送一个FIN(对方进程终止),套接口就变为可读且read返回0(文件结束)。
    3>.若是对方TCP发送一个RST(对方主机崩溃并从新启动),套接口就变成可读且read返回-1,返回的错误号errno为ECONNRESET。


9、write()函数和send函数
    若是向一个接收了FIN的套接字进行写操做是可行的,但若是向一个接受了RST的套接字进行写操做则是致命的,内核会向该进程发送一个SIGPIPE信号,返回EPIPO,该错误类型默认为终止进程。


SIGPIPE信号
    向一个接受了RST的套接字进行写操做时,内核会向该进程发送一个SIGPIPE信号,该信号的缺省行为是终止进程,所以进程必须捕获它以避免被不情愿的终止。
   


五、 Linux中Socket的数据结构
(1)

struct sockaddr { //用于存储套接字地址
    unsigned short sa_family;//地址类型
    char sa_data[14]; //14字节的协议地址
};

(2)

struct sockaddr_in{ //in 表明internet
    short int sin_family; //internet协议族
    unsigned short int sin_port;//端口号,必须是网络字节顺序
    struct in_addr sin_addr;//internet地址,必须是网络字节顺序
    unsigned char sin_zero;//添0(和struct sockaddr同样大小
};

(3)

 struct in_addr{
    unsigned long s_addr;
};
相关文章
相关标签/搜索