对监听套接字进行read、write和connect操作会怎样?

博主:恩恩~~~值得好好想想哦~~~~~~~~~

转自:http://blog.csdn.net/moonvs2010/article/details/7783572

 

已经学习的时候没有想过这个问题,只知道用监听套接字来执行accept操作,获取与客户端的连接,从来就没想过如果对监听套接字执行普通套接字的操作会怎样,今天特意做了个实验,对这三种情况进行测试。

  一、 read操作

  代码如下:

  1. #include <sys/types.h>   
  2. #include <unistd.h>   
  3. #include <sys/epoll.h>   
  4. #include <errno.h>   
  5. #include <sys/socket.h>   
  6. #include <netinet/in.h>   
  7. #include <string.h>   
  8. #include <stdlib.h>   
  9. #include <stdio.h>   
  10.   
  11. int main(void)  
  12. {  
  13.     int                  listenfd = -1;  
  14.     int                  connfd = -1;  
  15.     int                  ret;  
  16.     int                  epfd = -1;  
  17.     char                 buf[1024];  
  18.     struct epoll_event   ep;  
  19.     struct sockaddr_in   sa;  
  20.     struct sockaddr_in   conn_addr;  
  21.   
  22.     listenfd = socket(AF_INET, SOCK_STREAM, 0);  
  23.     sa.sin_family = AF_INET;  
  24.     sa.sin_addr.s_addr = htonl(INADDR_ANY);  
  25.     sa.sin_port = htons(8080);  
  26.   
  27.     bind(listenfd, (struct sockaddr *)&sa, sizeof (sa));  
  28.     listen(listenfd, 20);  
  29.     conn_addr.sin_family = AF_INET;  
  30.     inet_pton(AF_INET, "192.168.9.143", &conn_addr.sin_addr);  
  31.     conn_addr.sin_port = htons(80);  
  32.     memcpy(buf, "woaini"sizeof ("woaini"));  
  33.     if (connect(listenfd, (struct sockaddr *)&conn_addr, sizeof (conn_addr)) < 0) {  
  34.         perror("connect");  
  35.         return -1;  
  36.     }  
  37.     return 0;  
  38. }  
#include <sys/types.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    int                  listenfd = -1;
    int                  connfd = -1;
    int                  ret;
    int                  epfd = -1;
    char                 buf[1024];
    struct epoll_event   ep;
    struct sockaddr_in   sa;
    struct sockaddr_in   conn_addr;

    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = htonl(INADDR_ANY);
    sa.sin_port = htons(8080);

    bind(listenfd, (struct sockaddr *)&sa, sizeof (sa));
    listen(listenfd, 20);
    conn_addr.sin_family = AF_INET;
    inet_pton(AF_INET, "192.168.9.143", &conn_addr.sin_addr);
    conn_addr.sin_port = htons(80);
    memcpy(buf, "woaini", sizeof ("woaini"));
    if (connect(listenfd, (struct sockaddr *)&conn_addr, sizeof (conn_addr)) < 0) {
        perror("connect");
        return -1;
    }
    return 0;
}

上面代码的输出结果,如下图所示:

  1. connect: Transport endpoint is already connected  
connect: Transport endpoint is already connected

这个错误对应的错误码是EISCONN,也就是说监听套接字是处于“连接”状态的。至于为什么监听套接字处于“连接”状态,只能去看协议栈了,我现在也回答不上来,弄明白之后再发文章了。

二、 read操作

如果监听套接字处于“连接”状态的话,那我是不是就可以直接进行read或write操作了呢,试一下,代码如下:

  1. #include <sys/types.h>   
  2. #include <unistd.h>   
  3. #include <sys/epoll.h>   
  4. #include <errno.h>   
  5. #include <sys/socket.h>   
  6. #include <netinet/in.h>   
  7. #include <string.h>   
  8. #include <stdlib.h>   
  9. #include <stdio.h>   
  10.   
  11. int main(void)  
  12. {  
  13.     int                  listenfd = -1;  
  14.     int                  connfd = -1;  
  15.     int                  ret;  
  16.     int                  epfd = -1;  
  17.     char                 buf[1024];  
  18.     struct epoll_event   ep;  
  19.     struct sockaddr_in   sa;  
  20.     struct sockaddr_in   conn_addr;  
  21.   
  22.     listenfd = socket(AF_INET, SOCK_STREAM, 0);  
  23.     sa.sin_family = AF_INET;  
  24.     sa.sin_addr.s_addr = htonl(INADDR_ANY);  
  25.     sa.sin_port = htons(8080);  
  26.   
  27.     bind(listenfd, (struct sockaddr *)&sa, sizeof (sa));  
  28.     listen(listenfd, 20);  
#include <sys/types.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    int                  listenfd = -1;
    int                  connfd = -1;
    int                  ret;
    int                  epfd = -1;
    char                 buf[1024];
    struct epoll_event   ep;
    struct sockaddr_in   sa;
    struct sockaddr_in   conn_addr;

    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = htonl(INADDR_ANY);
    sa.sin_port = htons(8080);

    bind(listenfd, (struct sockaddr *)&sa, sizeof (sa));
    listen(listenfd, 20);
  1. if (read(listenfd, buf, sizeof (buf)) <=0) {  
  2.     perror("read");  
  3.     return -1;  
  4. }  
  5. return 0;  
    if (read(listenfd, buf, sizeof (buf)) <=0) {
        perror("read");
        return -1;
    }
    return 0;
}

上面代码的输出结果如下:

  1. read: Transport endpoint is not connected  
read: Transport endpoint is not connected

这里返回的错误码是ENOTCONN。奇怪了,connect的时候不是说已经连接了吗,怎么read的时候又报没有连接的错误呢?这个问题也得去看协议栈才能解答,所以学习网络编程一定得学习协议栈,否则不要说自己精通网络编程!

三、 write操作

 如果执行write操作会怎样呢,代码如下:

  1. <SPAN style="FONT-SIZE: 12px">#include <sys/types.h>  
  2. #include <unistd.h>   
  3. #include <sys/epoll.h>   
  4. #include <errno.h>   
  5. #include <sys/socket.h>   
  6. #include <netinet/in.h>   
  7. #include <string.h>   
  8. #include <stdlib.h>   
  9. #include <stdio.h>   
  10.   
  11. int main(void)  
  12. {  
  13.     int                  listenfd = -1;  
  14.     int                  connfd = -1;  
  15.     int                  ret;  
  16.     int                  epfd = -1;  
  17.     char                 buf[1024];  
  18.     struct epoll_event   ep;  
  19.     struct sockaddr_in   sa;  
  20.     struct sockaddr_in   conn_addr;  
  21.   
  22.     listenfd = socket(AF_INET, SOCK_STREAM, 0);  
  23.     sa.sin_family = AF_INET;  
  24.     sa.sin_addr.s_addr = htonl(INADDR_ANY);  
  25.     sa.sin_port = htons(8080);  
  26.   
  27.     bind(listenfd, (struct sockaddr *)&sa, sizeof (sa));  
  28.     listen(listenfd, 20);  
  29.     if (write(listenfd, buf, sizeof (buf)) <= 0) {  
  30.         perror("write");  
  31.         return -1;  
  32.     }  
  33.     printf("write: %d\n", ret);  
  34.   
  35.     return 0;  
  36. }</SPAN>  
#include <sys/types.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    int                  listenfd = -1;
    int                  connfd = -1;
    int                  ret;
    int                  epfd = -1;
    char                 buf[1024];
    struct epoll_event   ep;
    struct sockaddr_in   sa;
    struct sockaddr_in   conn_addr;

    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = htonl(INADDR_ANY);
    sa.sin_port = htons(8080);

    bind(listenfd, (struct sockaddr *)&sa, sizeof (sa));
    listen(listenfd, 20);
    if (write(listenfd, buf, sizeof (buf)) <= 0) {
        perror("write");
        return -1;
    }
    printf("write: %d\n", ret);

    return 0;
}

上面代码运行后,没有任何输出,也就是说代码根本就没执行到printf语句,而且也没有错误输出,这是为什么呢?gdb调试,原来在执行write的时候收到了SIGPIPE信号,所以进程终止了。但是没有任何输出,有点不理解。因为如果进程接收到SIGSEGV信号时,会输出“segment fault”,但是SIGPIPE信号时却没有任何输出。

 

上面的实验和一些问题可能平时都很少考虑,但就是这些细节问题我相信真正回答上来的人很少,或者根本不屑于回答,但这就是细节,就是在内核代码中的细节。所以在linux下编程,一定要去学些linux的内核源码,学习其中的机制和编程方法。希望能给刚接触linux编程的同学一些启示,不要像我一样走一些弯路。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值