监听套接字不可写?
在分析libevent源码并实现自己的网络库的时候想到这样一个问题:为什么注册事件的时候总是替换着注册EPOLLIN和EPOLLOUT呢?
于是我就在接收新连接注册新连接的监听事件时把EPOLLIN和EPOLLOUT都注册上了,结果就是,一直进EPOLLOUT,也就是说连接的套接字一直都可以可写的,这又引出另一个问题,epfd中注册的fd只有监听套接字时没有一直进EPOLLOUT呢?难道监听的套接字不可写?于是就有了这篇测试的文章。
既然怀疑,那就写个demo试试嘛。
1 #include <unistd.h> 2 #include <sys/types.h> 3 #include <sys/socket.h> 4 #include <netinet/in.h> 5 #include <arpa/inet.h> 6 7 #include <stdio.h> 8 #include <string.h> 9 #include <errno.h> 10 11 int main(int argc, char **argv) 12 { 13 printf("start\n"); 14 int fd = socket(AF_INET, SOCK_STREAM, 0); 15 if (fd == -1) 16 { 17 printf("socket\n"); 18 return -1; 19 } 20 21 struct sockaddr_in addr; 22 memset(&addr, 0, sizeof(addr)); 23 addr.sin_family = AF_INET; 24 addr.sin_addr.s_addr = INADDR_ANY; 25 addr.sin_port = htons(8080); 26 27 if (-1 == bind(fd, (struct sockaddr*)&addr, sizeof(addr))) 28 { 29 printf("bind\n"); 30 return -1; 31 } 32 33 if (-1 == listen(fd, 5)) 34 { 35 printf("listen\n"); 36 return -1; 37 } 38 39 int iRet = send(fd, "hello", 5, 0); 40 if (-1 == iRet) 41 { 42 printf("send\n"); 43 return -1; 44 } 45 else if (0 == iRet) 46 { 47 printf("Send zero data\n"); 48 } 49 else 50 { 51 printf("Succ\n"); 52 } 53 54 printf("End\n"); 55 return 0; 56 }
用gdb执行该程序:(至于为什么用gdb执行该程序,将在另一篇文章中说)
这里可以看到,收到了一个SIGPIPE的信号。
关于SIGPIPE这个信号的意思,man pages有这样一个解释:
意思就是说往一个没有读取端的pipe写数据,这就证实了我们的猜测,监听套接字是不可写的。