原文链接:

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 的状态变化详解的更多相关文章

  1. iOS中 HTTP/Socket/TCP/IP通信协议详解

    // OSI(开放式系统互联), 由ISO(国际化标准组织)制定 // 1. 应用层 // 2. 表示层 // 3. 会话层 // 4. 传输层 // 5. 网络层 // 6. 数据链接层 // 7. ...

  2. iOS中 HTTP/Socket/TCP/IP通信协议详解 韩俊强的博客

    每日更新关注:http://weibo.com/hanjunqiang  新浪微博 简单介绍: // OSI(开放式系统互联), 由ISO(国际化标准组织)制定 // 1. 应用层 // 2. 表示层 ...

  3. Mysql show Status常用参数详解

    状态名 作用域 详细解释 Aborted_clients Global 由于客户端没有正确关闭连接导致客户端终止而中断的连接数 Aborted_connects Global 试图连接到MySQL服务 ...

  4. 关于Socket和ServerSocket类详解

    Socket类 套接字是网络连接的一个端点.套接字使得一个应用可以从网络中读取和写入数据.放在两个不同计算机上的两个应用可以通过连接发送和接受字节流.为了从你的应用发送一条信息到另一个应用,你需要知道 ...

  5. Linux系统编程(36)—— socket编程之UDP详解

    UDP 是User DatagramProtocol的简称,中文名是用户数据报协议.UDP协议不面向连接,也不保证传输的可靠性,例如: 1.发送端的UDP协议层只管把应用层传来的数据封装成段交给IP协 ...

  6. Linux系统编程(31)—— socket编程之TCP详解

    TCP有源端口号和目的端口号,通讯的双方由IP地址和端口号标识.32位序号.32位确认序号.窗口大小稍后详细解释.4位首部长度和IP协议头类似,表示TCP协议头的长度,以4字节为单位,因此TCP协议头 ...

  7. TCP/IP、UDP、HTTP、SOCKET详解

    文章大纲 网络OSI七层及各层作用 TCP与UDP基本介绍 TCP连接过程详解 SOCKET原理与连接详解     一.网络OSI七层及各层作用   应用层:文件传输,电子邮件,文件服务,虚拟终端 T ...

  8. MySQL状态变量详解

    MySQL状态变量详解 mysql的状态变量(status variables)记录的mysql服务器的运行状态信息.查看语法如下: SHOW [GLOBAL | SESSION] STATUS; S ...

  9. http服务详解(1)

    前言:要熟练掌握一个服务,首先需要非常了解这个服务的工作过程. 跨网络的主机间通讯 在建立通信连接的每一端,进程间的传输要有两个标志: IP地址和端口号,合称为套接字地址 socket address ...

随机推荐

  1. 大数据之路week07--day05 (Hive的搭建部署)

    在之前博客中我有记录安装JDK和Hadoop和Mysql的过程,如果还没有安装,请先进行安装配置好,对应的随笔我也提供了百度云下载连接. 安装JDK:   https://www.cnblogs.co ...

  2. python3.7内置函数整理笔记

    #python3.7 内置函数整理 #abs(x) #返回数字的绝对值. 参数可以是整数或浮点数. 如果参数是复数,则返回其大小 # print(abs(1)) # print(abs(-1)) # ...

  3. 2.spring的主要模块作用

    spring中大约包含20过个模块, 主要包括以下几部分: 1. Core Container Core Container(核心容器)包含Core,Beans,Context和Expression ...

  4. norm()函数

    n = norm(v) 返回向量 v 的欧几里德范数.此范数也称为 2-范数.向量模或欧几里德长度. 例1: K>> norm([3 4]) ans = 5

  5. java 利用反射调用静态方法的示例

    内容简介 主要介绍使用反射的机制来调用执行类中的静态方法. 静态方法 public class GisUtil { private final static Logger logger = Logge ...

  6. ElementUI入门和NodeJS环境搭建

    1. ElementUI简介 我们学习VUE,知道它的核心思想式组件和数据驱动,但是每一个组件都需要自己编写模板,样式,添加事件,数据等是非常麻烦的,   所以饿了吗推出了基于VUE2.0的组件库,它 ...

  7. codepush安装

    https://github.com/lisong/code-push-server/blob/master/docs/README.md =====> 安装mysql下载mysql yum r ...

  8. PostgreSQL 查看表、索引等创建时间

    select s.oid,s.relname,t.stausename,t.stasubtype from pg_class s,pg_stat_last_operation t where s.re ...

  9. 谈MongoDB的应用场景

    转载自:http://blog.csdn.net/adparking/article/details/38727911 MongoDB的应用场景在网上搜索了下,很少介绍关于传统的信息化应用中如何使用M ...

  10. logo的一般做法

    <body> <!-- h1里面嵌套a,并且有网站名,方便seo --> <h1> <a href="#">小米官网</a&g ...