socket status 的状态变化详解
原文链接:
http://www.diranieh.com/SOCKETS/SocketStates.htm
-----------------------------------------------------------------------
Socket States
Summary
WHAT ARE SOCKET STATES
Regardless of the socket type (TCP or UDP), operation mode (blocking, non-blocking, or asynchronous) or application type (single- or multi-threaded), changes in socket states are what propel a network application. Therefore, for a network application to be efficient, it needs to detect and handle changes in socket states as efficient as possible.
The state of a socket determines which network operations will succeed, which operations will block, and which operations with will fail (the socket state even determines the error code). Sockets have a finite number of states, and the WinSock API clearly defines the conditions that trigger a transition from one state to another. Note that different types of sockets ( stream vs. datagram have different states and different transitions.
DATAGRAM SOCKET STATES
The following diagram represents all states that can be detected programmatically for a datagram (UDP) socket. About the only thing that UDP socket applications care about is the readable state:

The states in the figure above are detailed as follows:
| Socket State | Meaning |
| opened | socket() returned an unnamed socket (an unnamed socket is one that is not bound to a local address and port). The socket can be named explicitly with bind or implicitly with sendto() or connect(). |
| named | A named socket is one that is bound to a local address and a port. The socket can now send and/or receive. |
| readable | The network system received data and is ready to be read by the application using recv() or recvfrom(). |
| not writable | The network system does not have enough buffers to accommodate outgoing data. |
| closed | The socket handle is invalid. |
STREAM SOCKET STATES
The following diagram represents all states that can be detected programmatically for a stream (TCP) socket:

The states in the figure above are detailed as follows:
| Socket State | Meaning |
| opened | socket() returned an unnamed socket (an unnamed socket is one that is not bound to a local address and port). The socket can be named explicitly with bind() or implicitly with conenct(). |
| named and listening | The socket is named (bound to a local address and port) and is ready to accept incoming connection requests. |
| connection pending | The network system received an incoming connection requests and is waiting for the application to respond. |
| connected | An association (virtual circuit) has been established between a local and remote host. Sending and receiving data is now possible |
| readable | The network system received data and is ready to be read by the application using recv() or recvfrom(). |
| OOB readable | Out Of Band data received by the network system received data and is ready to be read by the application (usingrecv() or recvfrom().) |
| Not writable | The network system does not have enough buffers to accommodate outgoing data. |
| close pending | The virtual circuit is close. |
| closed | The socket handle is invalid. |
DETECTING SOCKET CHANGES
How does one detect changes in socket state? There are three different ways
- Using the return value of function calls.
- Using synchronous functions such as select(), ioctlsocket(), or setsockopt().
- Using the asynchronous function, WSAAsyncSelect().
WSAAsyncSelect() is by far the preferred method for detecting socket state changes.
FUNCTION CALL SUCCESS OR FAILURE
The return value of most functions can be used to determine a socket’s state. This strategy works fine with blocking sockets, but is very inefficient with non-blocking sockets, as the application will need to perform polling in order to detect state changes. Use this method only with blocking sockets.
SYNCHRONOUS DETECTION
Synchronous detection is performed by calling blocking or non-blocking functions whose return values indicate the state of the socket.
ASYNCHRONOUS DETECTION
Asynchronous socket state detection means that WinSock DLL will notify the application any time after the asynchronous socket state detection function has been called. Notification is performed via Windows messages. Asynchronous socket state detection is performed using WSAAsyncSelect(). On error this function returns SOCKET_ERROR and WSAGetLastError() can be used to get the specific error. On success, this function returns zero to indicate that:
- The socket is now non-blocking.
- If any the requested events match the current state of the socket, WinSock DLL posts a message for each matched event.
- If any the requested events match the future state of the socket, WinSock DLL posts a message for each matched event, as long as the re-enabling function is called for that event.
- If this socket creates a new socket using accept(), WSAAsyncSelect() will monitor the new socket for the same events requested previously.
WSAAsyncSelect() will remain in effect until WSAAsyncSelect() is called with a different lEvent parameter, or with lEvent equal to zero.
WSAAsyncSelect() is simple to work with. Basically, you tell WSAAsyncSelect() what you want to know about, and the WinSock DLL will tell you about it when it happens. The following diagrams illustrate how WSAAsyncSelect() works for a client that sends data and reads it back, and for the server to which the client connects.


WHAT ARE THE WSAASYNCSELECT EVENTS?
The following table lists the events that WSAAsyncSelect() can detect. Note that each event is equivalent to a socket state
| Event | When It Occurs(Socket State) | Meaning | Re-Enable Function |
| FD_ACCEPT | Connection request received (connection pending) | accept() likely to succeed. Must call accept() to get the socket handle for the new connection. | accept() |
| FD_CLOSE | Connection close received (close pending) | Remote done sending data, though data may remain to be read. Therefore, call recv() to check for any remaining data. closesocket() will complete immediately. | <none> |
| FD_CONNECT | Connection now established (connected) | Association established so sending and receiving on the socket is possible | <none> |
| FD_OOB | Out Of Band data with ready to read | recv() with MSG_OOB will return OOB data. Avoid using OOB at all. | recv() or recvfrom() |
| FD_READ | Data received by network system is ready for application to read (readable) | recv() or recvfrom() likely to succeed. If any data remains after calling recv() or recvfrom(), WinSock will post another FD_READ message. | recv() or recvfrom() |
| FD_WRITE | Network system buffers are available for outgoing data. | send() or sendto() likely to succeed | send() or sendto() |
When a call to WSAAsyncSelect() succeeds, WinSock DLL checks the current state of the socket immediately and posts a message for each requested event that matches the socket state.
WHEN TO CALL WSAASYNCSELECT ()
As a rule of thumb, call WSAAsyncSelect() immediately after you open the socket with socket(). This guarantees that you register for asynchronous event notification before the event can occur.
WHAT ARE RE-ENABLING FUNCTIONS?
Events have re-enabling functions so that WinSock DLL can avoid flooding applications with notification messages. After WinSock DLL posts a notification message, it will not post another until the application calls the enabling function for that message.
For example, WinSock DLL posts the FD_READ when data first arrives (level trigger), but does not post again as more data arrives. After the application calls recv() – the FD_READ enabling function - WinSock DLL will post another FD_READ message if there is still data available (level-trigger). The following diagram illustrates a flowchart of WSAAsyncSelect() level triggering event notification

WHAT IS IN A NOTIFICATION MESSAGE?
A WinSock DLL notification message is handled very similarly to Windows messages where lParam and wParam are used to hold information
wParam : Socket handle
(LOWORD)lParam : Event value
(HIWORD)lParam : WinSock error value
Always use WSAGETSELECTEVENT to extract the event value from lParam, and WSAGETSELECTERROR to extract the error value from lParam. Never use WSAGetLastError() as the value returned by this function may be different from that returned by WSAGETSELECTERROR macro.
BE PREPARED FOR FAILURE
Between the time WinSock DLL posts an asynchronous notification message to your application, and the time your application acts on it, things may change. Always handle WSAWOULDBLOCK gracefully to avoid serious problems. The WinSock DLL is required to post another notification message since you called the enabling function and the state did not change when the DLL posted the first message.
LOOPING IN RESPONSE
Asynchronous event notification has an inherent latency between the event and the arrival of the event notification message. The only event affected adversely by this latency is FD_READ event. You can offset this effect by calling recv() or recvfrom() more than once in response to each FD_READ event. This will generate extra FD_READ messages each time you call and data still remains. These extra messages will enhance the effect of the looping reads.
To loop safely calling recv() or recvfrom(), you should:
- Limit the number of times you loop (8 or less).
- handle WSAWOULDBLOCK gracefully.
CANCELING ASYNCHRONOUS NOTIFICATION
There are two ways to cancel asynchronous event notifications
- Call WSAAsyncSelect() passing NULL for lEvent parameter.
- Close socket using closesocket().
Note that in both cases, asynchronous notification messages may still be in the queue. Your application should anticipate them and either avoid normal processing, or, be prepared to handle the function failure that may result (failure with WSANOTSOCK error after calling closesocket())
SAMPLE APPLICATION
<TODO>
SELECT()
Like WSAAsyncSelect(), select() is a general purpose state detection and notification function. It can detect all states detected by WSAAsyncSelect(), but does not provide the same resolution; in order to determine some socket states, you must interpret the results of a call to select() in the context of the current socket state.
The select() function operates synchronously. select() is very similar in concept to WaitForMultipleObject() Win32 API. select() takes a set of sockets and blocks until one of the sockets is ‘signalled’ Using select() involves more work in coding than WSAAsyncSelect() which is far more elegant and far more efficient.
PEEKING AT DATA
Some application might require the ability to know how much data is available, or they may need to take a look at the data before they remove it from the incoming buffer.
To detect how much data is available, use ioctlsocket() with FIONREAD flag. To copy incoming data into an application buffer without actually removing the data from the network system buffers, use recv() or recvfrom() with MSG_PEEK flag.
Using these facilities is not recommended as any peek-read is inherently inefficient. It may even cause the application to fail. Your application will work faster, be more portable, and reliable if you simply use recv() or recvfrom() to read data directly into your application.
socket status 的状态变化详解的更多相关文章
- iOS中 HTTP/Socket/TCP/IP通信协议详解
// OSI(开放式系统互联), 由ISO(国际化标准组织)制定 // 1. 应用层 // 2. 表示层 // 3. 会话层 // 4. 传输层 // 5. 网络层 // 6. 数据链接层 // 7. ...
- iOS中 HTTP/Socket/TCP/IP通信协议详解 韩俊强的博客
每日更新关注:http://weibo.com/hanjunqiang 新浪微博 简单介绍: // OSI(开放式系统互联), 由ISO(国际化标准组织)制定 // 1. 应用层 // 2. 表示层 ...
- Mysql show Status常用参数详解
状态名 作用域 详细解释 Aborted_clients Global 由于客户端没有正确关闭连接导致客户端终止而中断的连接数 Aborted_connects Global 试图连接到MySQL服务 ...
- 关于Socket和ServerSocket类详解
Socket类 套接字是网络连接的一个端点.套接字使得一个应用可以从网络中读取和写入数据.放在两个不同计算机上的两个应用可以通过连接发送和接受字节流.为了从你的应用发送一条信息到另一个应用,你需要知道 ...
- Linux系统编程(36)—— socket编程之UDP详解
UDP 是User DatagramProtocol的简称,中文名是用户数据报协议.UDP协议不面向连接,也不保证传输的可靠性,例如: 1.发送端的UDP协议层只管把应用层传来的数据封装成段交给IP协 ...
- Linux系统编程(31)—— socket编程之TCP详解
TCP有源端口号和目的端口号,通讯的双方由IP地址和端口号标识.32位序号.32位确认序号.窗口大小稍后详细解释.4位首部长度和IP协议头类似,表示TCP协议头的长度,以4字节为单位,因此TCP协议头 ...
- TCP/IP、UDP、HTTP、SOCKET详解
文章大纲 网络OSI七层及各层作用 TCP与UDP基本介绍 TCP连接过程详解 SOCKET原理与连接详解 一.网络OSI七层及各层作用 应用层:文件传输,电子邮件,文件服务,虚拟终端 T ...
- MySQL状态变量详解
MySQL状态变量详解 mysql的状态变量(status variables)记录的mysql服务器的运行状态信息.查看语法如下: SHOW [GLOBAL | SESSION] STATUS; S ...
- http服务详解(1)
前言:要熟练掌握一个服务,首先需要非常了解这个服务的工作过程. 跨网络的主机间通讯 在建立通信连接的每一端,进程间的传输要有两个标志: IP地址和端口号,合称为套接字地址 socket address ...
随机推荐
- HTML&CSS基础-内联和块元素
HTML&CSS基础-内联和块元素 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.html源代码 <!DOCTYPE html> <html> ...
- vue-(过滤器,钩子函数,路由)
1.局部过滤器 在当前组件内部使用过滤器,修饰一些数据 //声明 filters:{ '过滤器的名字':function(val,a,b){ //a 就是alax ,val就是当前的数据 } } // ...
- 麻雀虽小,五脏俱全。基于Asp.net core + Sqlite 5分钟快速上手一个小项目
虽然该方法不会用在实际开发中,但该过程对于初学者还是非常友好的,真应了麻雀虽小,五脏俱全这句话了.好了不多废话了,直接开始!! 1.建立一个名为test的Asp.net core web应用程序 这一 ...
- Redis与Python的交互
驱动模块 redis模块用来在Python环境下驱动Redis数据库 可以直接用pip方式安装 pip install redis 或者国内镜像下载: pip install -i https://p ...
- CSS 相邻元素选择器
相邻兄弟选择器(Adjacent sibling selector)可选择紧接在另一元素后的元素,且二者有相同父元素.选择相邻兄弟 如果需要选择紧接在另一个元素后的元素,而且二者有相同的父元素,可以使 ...
- maven中profile的使用
转载:https://blog.csdn.net/java_collect/article/details/83870215 前言 在开发过程中,我们的项目会存在不同的运行环境,比如开发环 ...
- Samba服务安装
安装Samba服务 1.在可以联网的机器上使用yum工具安装,如果未联网,则挂载系统光盘进行安装. # yum install samba samba-client samba-swat 有依赖关 ...
- jquery页面多个倒计时效果
<div class="timeBox" data-times="2019/06/30,23:59:59"> 距结束 <span class= ...
- linux 下安装 nginx 及所需的各种软件工具
我当前的虚拟机是 vmware 15,用的镜像是centOs 7 CentOS-7-x86_64-DVD-1810.iso 确保你的虚拟机是通网的. 1.如果是新环境,没安装过gcc,那么先安装这个. ...
- C#题(子文章)(持续更新)
-----> 总文章 入口 文章目录 [-----> 总文章 入口](https://blog.csdn.net/qq_37214567/article/details/90174445) ...