【Socket】详述socket编程之select()和poll()函数

Socket.Poll()

public bool Poll (

                    int microSeconds,

                    SelectMode mode

)

MSDN:

Poll 方法将会检查 Socket 的状态。指定 selectMode 参数的 SelectMode.SelectRead,可确定 Socket是否为可读。指定 SelectMode.SelectWrite,可确定 Socket 是否为可写。使用SelectMode.SelectError 检测错误条件。Poll 将在指定的时段(以 microseconds 为单位)内阻止执行。如果希望无限期的等待响应,则将 microSeconds 设置为一个负整数。

 

int  microSeconds,

MSDN:

等待响应的时间(以微秒为单位)。

自己理解:

是Poll程序中断运行时间。 如microseconds=1000;Poll阻塞1000毫秒,microseconds<0将无限等待响应。

2010.8.30

 

SelectMode mode

 public enum SelectMode

 {

     SelectRead = 0,  //     读状态模式。

     SelectWrite = 1, //     写状态模式。

     SelectError = 2, //     错误状态模式。

 }

MSDN:

模式(SelectMode)

返回(return)

SelectRead

1.  如果已调用Listen并且有挂起的连接,则为true。

2.如果有数据可供读取,则为true。

3.如果连接已关闭、重置或终止,则返回true。

SelectWrite

1.  如果正在处理Connect并且连接已成功,则为true。

2.  如果可以发送数据,则返回true。

SelectError

1.  如果正在处理不阻止的Connect,并且连接已失败,则为true。

2.  如果OutOfBandInline未设置,并且带外数据可用,则为true。

自己理解:

只对红色部分理解。

         2010.8.30

MSDN例子:

//Creates the Socket for sending data over TCP.

Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream,

   ProtocolType.Tcp );

 

// Connects to host using IPEndPoint.

s.Connect(EPhost);

if (!s.Connected)

{

   strRetPage = "Unable to connect to host";

}

// Use the SelectWrite enumeration to obtain Socket status.

 if(s.Poll(-1, SelectMode.SelectWrite)){

      Console.WriteLine("This Socket is writable.");

 }

 else if (s.Poll(-1, SelectMode.SelectRead)){

        Console.WriteLine("This Socket is readable." );

 }

 else if (s.Poll(-1, SelectMode.SelectError)){

      Console.WriteLine("This Socket has an error.");

 }

 

自己例子:

protected override void ProcMessage()

        {

            int microSeconds = 50;

            EndPoint senderRemote = socket.RemoteEndPoint;

            int dataLen, msgLen = 0;

            try

            {

                if (socket.Poll(microSeconds, SelectMode.SelectRead))

                {

                    dataLen = ReceiveFrom(m_ReceiveBuf, m_ReceiveBuf.Length, socket);

                    if (EClass.Message.Message.Valid(m_ReceiveBuf))

                        MessageParse(m_ReceiveBuf, dataLen, (IPEndPoint)senderRemote);

                }

            }

            catch (SocketException se)

            {

                SocketError err = se.SocketErrorCode;

            }

        }

 

Socket.Select()

public static void Select (

               IList checkRead,

               IList checkWrite,

               IList checkError,

               int microSeconds

)

MSDN:

Select 是一种静态方法,它可确定一个或多个 Socket 实例的状态。必须先将一个或多个套接字放入 IList中,然后才能使用 Select 方法。通过调用 Select(将 IList 作为 checkRead 参数),可检查是否具有可读性。若要检查套接字是否具有可写性,请使用 checkWrite 参数。若要检测错误条件,请使用 checkError。在调用 Select 之后,IList 中将仅填充那些满足条件的套接字。

 

如果当前处于侦听状态,则可读意味着可成功地对 Accept 进行调用而没有阻止。如果当前已接受连接,则可读意味着有可读取的数据。这些情况下,所有的接收操作均可成功进行而没有阻止。可读性也可指示远程 Socket是否已经关闭连接;如果连接已关闭,则对 Receive 的调用将立即返回,并返回零字节。

 

如果至少一个相关套接字(checkRead、checkWrite 和 checkError 列表中的套接字)符合其指定的条件,或者超过 microSeconds 参数,则无论先出现其中哪种情况,都会返回 Select。将 microSeconds 设置为 -1 会指定无限大的超时值。

 

如果对 Connect 进行非阻止调用,则可写意味着已经成功连接。如果已经建立连接,则可写性意味着所有的发送操作均会成功完成而没有阻止。

 

如果对 Connect 进行非阻止调用,则 checkerror 参数将标识尚未成功连接的套接字。

 

 

自己理解:

Select是一个静态方法。主要用于多个Socket套接字。

1.   把从客户端接到Socket存到在ArrayList列表里。

2.    执行Socket.Select(ArrayList,ArrayList,ArrayList,1000);会对ArrayList进行筛选,吧不符合条件的从ArraList里删除,留下符合条件的Socket。

2010.8.31

 

MSDN例子:

IPHostEntry ipHostEntry = Dns.Resolve(Dns.GetHostName());

            IPAddress ipAddress = ipHostEntry.AddressList[0];

 

            Socket socket0 = null;

            Socket socket1 = null;

            Socket socket2 = null;

            Socket socket3 = null;

            Socket socket4 = null;

            Socket socket5 = null;

 

            ArrayList listenList = new ArrayList();

            listenList.Add(socket0);

            listenList.Add(socket1);

            listenList.Add(socket2);

 

            ArrayList acceptList = new ArrayList();

            acceptList.Add(socket3);

            acceptList.Add(socket4);

            acceptList.Add(socket5);

 

            for (int i = 0; i < 3; i++)

            {

                listenList[i] = new Socket(AddressFamily.InterNetwork,

                                           SocketType.Stream,

                                           ProtocolType.Tcp);

                ((Socket)listenList[i]).Bind(new IPEndPoint(ipAddress, 11000 + i));

                ((Socket)listenList[i]).Listen(10);

            }

 

            // Only the sockets that contain a connection request

            // will remain in listenList after Select returns.

 

            Socket.Select(listenList, null, null, 1000);

 

            Console.Write(listenList.Count.ToString());

 

            for (int i = 0; i < listenList.Count; i++)

            {

                acceptList[i] = ((Socket)listenList[i]).Accept();

            }

            Console.Read();

 

运行以后listenList全部剔除,按理应该保留符合SelectRead条件的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
selectpoll和epoll是三种多路复用的机制,用于处理多个I/O事件的方式。它们在网络编程中常用于监听多个文件描述符的状态变化,以提高程序的并发处理能力。 1. selectselect是最古老的一种多路复用机制。它的原理是通过一个位图数组来标记文件描述符的状态变化,并提供了三个监视集合,分别是读集合、写集合和异常集合。通过调用select函数,将需要监视的文件描述符及其对应的集合传入,然后select会阻塞程序,直到有文件描述符状态发生变化或超时。缺点是select所能监视的文件描述符数量存在限制。 2. pollpollselect的改进版,它使用链表来存储文件描述符和对应的事件集合。与select不同,poll没有限制监视的文件描述符数量。通过调用poll函数,将需要监视的文件描述符及其对应的事件集合传入,然后poll会阻塞程序,直到有文件描述符状态发生变化或超时。 3. epoll:epoll是Linux特有的一种多路复用机制,与selectpoll相比,在大规模并发连接时具有更好的性能。epoll通过在内核中创建一个事件表,将需要监视的文件描述符注册到这个事件表中,并通过epoll_ctl函数来控制事件的注册和删除。通过调用epoll_wait函数,程序可以等待多个文件描述符上的事件,并将就绪的文件描述符返回。 总结来说,selectpoll和epoll都是用于处理多个I/O事件的方式,但epoll在性能上更为出色。在选择使用哪种机制时,需要根据实际情况考虑并发连接数、平台兼容性以及对性能的要求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值