我正在linux中设计一个C程序,我将有两个线程。一个主要线程是event_processor_thread,它执行主函数处理。第二个线程是一个始终在后台运行的event_dispatcher线程,实时写入和读取多个接口(非阻塞异步i / o)
我在网上做了一些研究,发现实现非阻塞套接字i / o的最佳方法可以通过
完成。select()
我选择后者,因为它更容易,并且我将拥有最多4个接口来读/写。
我很清楚使用readfds
的听/读机制,但我不确定如何使用writefds
!如果我将event_processor_thread中的数据放入共享内存并让此事件调度程序线程从共享内存中读取并使用send()
进行写入,那么选择是否会自行将数据发送到套接字?这就是为什么我需要在writefds
使用select()
?
如果我的问题不明确,我很抱歉,我基本上想要的是拥有一个非阻塞的I / O线程来将事件分配到事件处理器线程或从事件处理器线程分配到外部接口。在这方面的任何投入都受到高度赞赏。谢谢!
答案 0 :(得分:12)
select的writefds用于检查文件描述符是否已准备好进行写入。对于套接字,这意味着与套接字关联的发送缓冲区未满。
假设你的平台上的套接字有一个8 kb的缓冲区,你想发送100 kb的数据。
您调用write
并获得返回值8192,表示已写入前8192个字节。下一次write调用将返回EAGAIN
或EWOULDBLOCK
,表示发送缓冲区已满。
您现在可以使用select
找出发送缓冲区中何时有空间(即,当一个tcp / ip数据包已传输到客户端时),以便您可以继续写入。同时,您可以监听新连接并等待客户端的输入。
请注意,select
从不发送任何数据,它只是一次监视多个文件描述符的状态。
答案 1 :(得分:1)
不,select()
不会"负责写作"。当writefds集中包含的一个或多个文件描述符变为可写时,它将通知您。这可能意味着有问题的fd已完成您之前的(非阻塞)写操作,因此您现在可以执行另一个。
答案 2 :(得分:0)
select()
告诉您文件描述符何时可写。对于套接字,这意味着它可以接受新的出站数据而不会阻塞调用者。如果您调用send()
或write()
并且套接字的出站缓冲区已满,您将收到EAGAIN
或EWOULDBLOCK
错误,此时您将停止写入该套接字,直到它又变得可写了。 select()
还可以告诉您在调用非阻塞connect()
后套接字何时可写,表示已成功建立连接并且数据可以开始写入对等方。