Windows Sockets网络编程(1)TCP select & thread

select在socket通信中有着举足轻重的地位,这要先从recv谈起。既然来到了本文,就默认你已经明白了send/recv阻塞式通信了,如果不太了解可以先阅读《Windows Sockets网络编程(0)TCP In Action》。这种阻塞式通信,存在一个很大的问题:“假设需要建立两条以上的TCP/UDP通信,那么recv该如何弄?”。很常见的方式是多线程?回答很正确。一般网络通信,肯定是要开启一个线程用来接受数据的,也就是在一个子线程中recv。那么,如果有N条TCP/UDP通道,就必须使用N个线程。开设线程本身需要一定的消耗(Windows一个线程,默认需要4M左右的线程栈),而更多的问题是线程间的互斥与同步。那么一个解决方案——select机制,出现了。


select有何作用?

如果可以用一个不太准确的数学式子来表示的话,可以这么写:

  • select = recv + recv + … + recv.

当然,在不采取特殊手段的前提下,上式中的recv个数是<=64的。那么,select到底是什么?

有人回答:“select是recv监视器。”

这个比喻其实很恰当。

fd_set集合

要使用select,则必须知道fd_set集合。它是系统中的一个socket集合类型。由于你可能没接触过这个类型,看起来觉得有些奇怪。如果我在这里写个int或者long,你可能就觉得亲切了。

fd_set g_tcp_select_client; //global default fd_set all null.
//long a[64];

虽然fd_set从字面来看“set”像是集合,但是它的内部构造却是一个数组。也就是说上面的g_tcp_select_client,其实完全可以当做一个数组使用。可以想象一下long a[64]如何使用,fd_set也莫过于此。

create socket

相信来到本文的你,已经会很熟练的创建socket了。那么,以前你是如何管理创建好的socket呢?

SOCKET tcp_client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  1. 你是使用一个数组SOCKET array[5],将所有的SOCKET存放进去?
  2. 还是前进一步,使用STL map将其存放进去?能够更方便的查找?

其实,有一种相对来说,更好的方式。你要学会使用select,要学会fd_set的使用。

//add into select set
FD_SET(tcp_client_socket, &g_tcp_select_client);

FD_SET是一个宏,以上语句,就可以将我们创建的SOCKET添加到fd_set集合中了。而且,fd_set与select配合可以对SOCKET进行神奇的管理。

select函数

那么真正的select函数是什么样子呢?select到底是如何监视recv的呢?

int select( int nfds, fd_set FAR* readfds, fd_set * writefds, fd_set * exceptfds, const struct timeval * timeout);
  • nfds:是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错!在Windows中这个参数的值无所谓,可以设置不正确。
  • readfds:(可选)指针,指向一组等待可读性检查的套接口。
  • writefds:(可选)指针,指向一组等待可写性检查的套接口。
  • exceptfds:(可选)指针,指向一组等待错误检查的套接口。
  • timeout:select()最多等待时间,对阻塞操作则为NULL。

对于参数timeout来说,如果传入NULL,则表示无限阻塞。如果需要设置超时时间?那么你可以这样:

timeval tm;
tm.tv_sec = 1L;   //s
tm.tv_usec = 100L;//ms

如何使用select?

select使用起来有不少注意事项:

 u_int select_ret = select(0, &tcp_select_client_temp, NULL, NULL, NULL);//select核心

假设tcp_select_client_temp中存放的是:[123][456][789][][][][][][].

也就是说,fd_set中目前已经放入了3个SOCKET。那么,使用上述一条select语句就可以对这3个SOCKET是否与数据到来进行监视了。(而不需要开启3个线程,然后每个线程中使用1个recv)。

for (
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值