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

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

  一、 read操作

  代码如下:

#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;
}

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

connect: Transport endpoint is already connected

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

二、 read操作

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

#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 (read(listenfd, buf, sizeof (buf)) <=0) {
        perror("read");
        return -1;
    }
    return 0;
}

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

read: Transport endpoint is not connected

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

三、 write操作

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

#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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值