• 假装在火星
    2019-08-09
    之前看过一些文章解释,为什么tcp建立连接需要三次握手,解释如下

    tcp连接的双方要确保各自的收发消息的能力都是正常的。
    客户端第一次发送握手消息到服务端,
    服务端接收到握手消息后把ack和自己的syn一同发送给客户端,这是第二次握手,
    当客户端接收到服务端发送来的第二次握手消息后,客户端可以确认“服务端的收发能力OK,客户端的收发能力OK”,但是服务端只能确认“客户端的发送OK,服务端的接收OK”,
    所以还需要第三次握手,客户端收到服务端的第二次握手消息后,发起第三次握手消息,服务端收到客户端发送的第三次握手消息后,就能够确定“服务端的发送OK,客户端的接收OK”,
    至此,客户端和服务端都能够确认自己和对方的收发能力OK,,tcp连接建立完成。
    展开

    作者回复: 赞

     6
     76
  • 阿卡牛
    2019-08-09
    这个问题的本质是, 信道不可靠, 但是通信双发需要就某个问题达成一致. 而要解决这个问题, 无论你在消息中包含什么信息, 三次通信是理论上的最小值. 所以三次握手不是TCP本身的要求, 而是为了满足"在不可靠信道上可靠地传输信息"这一需求所导致的

    作者回复: 赞。

     1
     31
  • 彭俊
    2019-08-11
    如何使用非阻塞调用套接字:使用fcntl函数设置套接字的属性fcntl(fd, F_SETFL, flags);
    非阻塞调用的 使用的场景:程序在调用返回之前,需要做其他事情,可以选择用定时轮询或事件通知的方式获取调用结果。
    是否可以调用bind 函数:可以,但是调用bind函数,也就是客户端指定了端口号,这样容易造成端口冲突,所以客户端不调用bind函数,让系统自动选择空闲端口比较好
    
     24
  • leesper
    2019-08-19
    思考题1:非阻塞调用的场景就是高性能服务器编程!我所有的调用都不需要等待对方准备好了再返回,而是立即返回,那么我怎么知道是否准备好了?就是把这些fd注册到类似select或者epoll这样的调用中,变多个fd阻塞为一个fd阻塞,只要有任何一个fd准备好了,select或者epoll都会返回,然后我们在从中取出准备好了的fd进行各种IO操作,从容自然 ^o^

    作者回复: 赞,下面的内容会讲到这部分了

    
     14
  • fjpcode
    2019-08-09
    1. 非阻塞套接字往往配合多路复用机制,达到提高CPU利用率,实现高并发的目的。
    2. 客户端做bind当然是可以的,但是因为连接请求往往是由客户端主动发起的,所以在客户端做bind显得不那么必要,还要承担端口冲突的风险。
    
     6
  • 鱼向北游
    2019-09-02
    关于三次握手
    几句话解释清楚
    1.信道不安全 保证通信需要一来一回
    2.客户端的来回和服务端的来回 共四次 这是最多四次
    3.客户端的回和服务端的来合并成一个,就是那个sync k ack j+1
    4.这样就是三次握手
    展开

    作者回复: 很清楚,很简洁。

    
     5
  • 一周思进
    2019-08-09
    刚好最近写了个通过man帮助手册编写基础tcp服务器
    https://mp.weixin.qq.com/s/bNdfXNQcZ3z_WzDWL5yQfA
    
     3
  • 星亦辰
    2019-08-09
    思考题2

    客户端可以bind 指定使用固定端口来连接。
    没有bind 则会产生一个随机的端口来完成连接请求。

    想到一个比较有意思的事情:

    客户端bind 以后,对内网进行端口扫描,表象则是,远程随机端口,到本地固定端口完成通信。看似,是本地开启了服务。如果bind 80 443 22这些常规端口,则可以迷惑安全人员 😄
    展开

    作者回复: 想多了,可以区分出来是不是本地监听端口(被动套接字)的,而且这个在大多数情况下不被允许的。

     3
     3
  • Knight²º¹⁸
    2019-08-11
    老师我有一个问题,编程语言中的IO模型和操作系统中的IO关系是什么?

    作者回复: 就是要和操作系统I/O打交道,编程语言的I/O模型是通过抽象和设计,总结出的一套规范。

     2
     2
  • 浦上清风
    2019-08-09
    1. 非阻塞 == 异步通信 ???
    2. 可以是可以,但是不安全???

    作者回复: 1 不是等价的
    2 没有必要,还徒增了端口冲突的危险。

    
     2
  • _stuView
    2019-08-09
    sockfd里的这个fd代表什么

    作者回复: file description,文件描述符。UNIX世界里万物皆文件。

     6
     2
  • 旅途
    2019-12-28
    老师 两个问题麻烦解答下
    1.如果服务端 使用随机端口 那么客户端时怎么知道的 不使用随机的话 是客户端要先知道服务端的端口然后配置进去吗
    2.三次握手时 每次通信的消息都加一 这个目的是什么 每次返回一个"1" 或者"success" 是不是也行?

    作者回复: 1.客户端一定需要预先知道待连接的服务器端的地址和端口,至于怎么让客户端知道,通过配置,启动参数,都是可以的;
    2.加1的目的是为了对这个报文进行唯一性确认,防止报文串掉了,这样我们就无法知道谁跟谁了。

    
     1
  • Ghost
    2019-12-20
    简单的就是
    A:你能听到我说话吗?
    B:听得到,你能听得到我说话吗?
    A:听得到

    保证通信的双方都是有接收跟发送消息的能力
    展开

    作者回复: 嗯。

    
     1
  • 云端
    2019-09-10

    您好:老师

    int socket_init()
    {
           struct protoent* protocol = NULL;
            protocol=getprotobyname("icmp");
            int sock=socket(AF_INET,SOCK_RAW,protocol->p_proto);

    }

    在外部两次调用该函数,icmp协议原始套接字返回文件描述符相同,每次都是sock=5,为什么?怎么才能在外部多次调用该函数时返回的上下文描述符不一样?
    展开

    作者回复: 我的程序和结果 :

    #include "lib/common.h"

    int socket_init()
    {
        struct protoent* protocol = NULL;
        protocol=getprotobyname("icmp");
        int sock=socket(AF_INET,SOCK_RAW,protocol->p_proto);
        if(sock == -1){
            error(1,errno,"create socket failed");
        }
        return sock;
    }

    int main(int c, char **v) {
        printf("socket %d \n", socket_init());
        printf("socket %d \n", socket_init());
    }

    socket 3
    socket 4

     1
     1
  • 苦行僧
    2019-08-14
    顶上的留言非常完美的解释了为什么是三次握手
    
     1
  • zhchnchn
    2019-08-09
    这篇很是解惑,感谢。有2个问题想请教老师:
    1. `socket`函数的参数`domain`的值,在`bind`函数的参数`addr`的`sin_family`中也需要设置,这样不是重复了吗?
    2. `connect`函数出错返回可能的3种情况中,其中第1种“TIMEOUT 错误”和第3种“destination unreachable”,感觉都是连接不到服务端的IP,这两种情况有什么区别吗?

    作者回复: 1.两个不是一个东西,一个是套接字地址,一个是套接字,都需要设置。

    2.unreachable是被动收到了其他网络涉笔发来的ICMP报文信息,而timeout是在尝试一段时间后主动放弃的。

     3
     1
  • Keep-Moving
    2019-08-09
    老师,想问一下,为什么是三次握手,而不是四次、五次握手?

    作者回复: 因为三次握手是最简洁的方式,已经足够完成信息的确认。

     2
     1
  • 广训
    2019-08-09
    记得很久前学套接字,提供的例子就是客户端bind端口,基本第二次和以后在运行,就告诉端口被占用,那时候不懂,就换个端口再来一次

    作者回复: 这是有原因的,不需要每次都换端口,下面会降到具体解法。

     1
     1
  • 星亦辰
    2019-08-09
    非阻塞,一般是把请求接收到的套接字传递给子进程或子线程,然后,主进程,主线程继续等待下一个请求。多数网络服务器都是这个路子吧

    作者回复: 非阻塞,是指I/O模型,不是等待数据或连接,还是通过I/O通知的方式来感知数据或连接。

    后面的章节会详细讲述非阻塞模型

    
     1
  • 莫珣
    2020-01-15
    思考题1:可以通过设置socket的属性来设置socket为非阻塞,这样在该socket上的所有操作都是非阻塞的。Linux下是fcntl(fd, F_SETFL, flags)。使用场景的话,个人理解是为了解耦和性能。
    思考题2:可以调用bind函数,但是这样一来客户端会使用固定端口,容易产生冲突,另外,一般而言我们希望客户端具备快速启动的能力,但是因为TIMEWAIT状态的存在,使用随机端口会更容易处理一些。

    然后看到评论区里很多人说三次握手的事情,个人认为理解三次握手为什么是三次,具体三次握手是为什么,需要从“TCP是全双工的”这句话来理解。
    展开
    
    
我们在线,来聊聊吧