码迷,mamicode.com
首页 > 其他好文 > 详细

unix网络编程

时间:2020-02-18 14:55:18      阅读:57      评论:0      收藏:0      [点我收藏+]

标签:全双工   服务   splay   知识   color   unix   shu   odi   perror   

Unix 网络编程

传输层部分知识点

TIME_WAIT状态

  • MSL: maximum segment lifetime

任何TCP的实现都需要为MSL选择一个合适的值, RFC的建议值是2分钟。分组可能出现迷途,若迷途分组在MSL中找到路, 造成重复,TCP必须修复

TIME_WAIT存在的理由:

  1. 可靠的实现全双工的连接和终止
    考虑最终ACK丢失的情况,

  2. 允许老的重复分组在网络中消逝
    TCP的化生身现象, 因为TIME_WAIT的时间是2MSL, 故TIME_WAIT可以确保先前化身(incarnation)的老重复分组都已经在网络中消失了

    不过存在一个例外: 如果到达的SYN的序列号大于前一化身的结束序列号,源自Berkely的实现应该给当前TIME_WAIT状态的连接启动新的化身

SCTP

连接: 类似TCP, 但是是四路握手, 主要差别在于作为SCTP整体的一部分的cookie的生成
终止: 不允许"半关闭"

技术图片技术图片 连接和终止

Coding

函数细节补充

  • inet_pton and inet_ntop
    ?inet_addr已经被废弃了, inet_aton其实也不太好, 新的代码应该要使用inet_pton and inet_ntop, 例如如下例子

    struct sockaddr_in makeAddr(char const *addr, uint16_t port) {
        struct sockaddr_in ret{};
        inet_pton(AF_INET, addr, &ret.sin_addr.s_addr);
        // ret.sin_addr.s_addr = inet_addr(addr); 例如用上面哪行代码代替此行
        ret.sin_family = AF_INET;
        ret.sin_port = htons(port);
        bzero(&ret.sin_zero, 8);
        return ret;
    }
  • listen的作用
    ??刚由socket创建的套接字, 系统默认其为主动套接字, listen的作用是把一个未连接的主动套接字转换为被动套接字. 第二个参数是内核为相应的socket排队的最大排队数 (incomplete connection queue: 处于SYN_RCVD状态)

    并发服务器的一个细节

    考虑如下代码
void detail() {
    pid_t pid;
    int listenfd, connfd;

    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in addr = makeAddr();
    bind(listenfd, (sockaddr *)addr, sizeof(struct sockaddr_in));

    listen(listenfd, 128);

    while(true) {
        struct sockaddr_in clientAddr;
        socklen_t addrlen = sizeof(struct sockaddr);
        connfd = accept(listenfd, (sockaddr_in) &clientAddr, &addrlen);

        if(pid = fork()) {
            close(listenfd);
            // do something here
            close(connfd);
            exit(0);
        }
        close(connfd); //注意这里
    }
}

我们知道, TCP套接口字调用close会导致发送一个FIN, 然后会连接终止, 为什么这里不会呢?

??事实上, 每个文件或socket都会有一个引用计数(引用计数在文件表项中维护), fork的时候会让计数*2, 而close让计数-1, 所以不会出现问题, 真正socket的清理和资源的释放过程要等计数为0的时候才会发生
??注意, 如果一直fork了也不close, 那么会耗尽所有可用的文件描述符, 导致连接一直打开着
??如果我们确实想要某个TCP连接上发送一个FIN, 那么我们可以改用shutdown函数.

处理被中断的系统调用

??如accept, 是一个慢系统调用, 多数网络支持函数都属于这个类型. 当阻塞于慢系统调用的一个进程捕获某个信号且进入相应的处理函数的时候, 该系统调用可能返回一个EINTR错误.(有的内核自动重启某些被中断的系统调用), 不过为了便于移植, 我们必须对EINTR有所准备, 一个处理办法就是

while(true) {
    connfd = accept(listenfd, (sockaddr_in) &clientAddr, &addrlen);
    if(connfd < 0) {
        if(errno == EINTR)
            continue;
        else perror("accept");
    }
}

注意: 有一个函数我们不能这样处理, 就是connect, 如果他出了EINTR, 再次调用会立即返回一个错误, 我们必须用select函数来等待连接完成

处理accept返回前连接终止

如下图的情况的时候,

技术图片

如何处理这种问题依赖于不同的实现, 之后再说

小结

??所有客户端和服务器都从调用socket开始, 客户端connect, 服务端bind, listen和accept, 大多数TCP都是并发的, 而大多数UDP却是迭代的

IO复用 -- select 和 poll

unix网络编程

标签:全双工   服务   splay   知识   color   unix   shu   odi   perror   

原文地址:https://www.cnblogs.com/Kimbing-Ng/p/12325965.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!