【问题标题】:Is TCP bidirectional or full-duplex?TCP是双向的还是全双工的?
【发布时间】:2015-04-14 05:09:03
【问题描述】:

Bidirectionalfull-duplex 是不同的概念。例如Ethernet 只是半双工的,因为在特定时间,只有一个主机可以通过线路发送数据,并且它不能同时发送和接收数据。

所以当我们在以太网上使用 TCP 时,我认为 TCP 只是双向或半双工的。

但是here 它说 TCP 是全双工的。为什么?

【问题讨论】:

  • 现代以太网是全双工的。
  • @YuHao 谢谢,但是如果在旧的半双工以太网环境中呢? TCP 怎么能适应那里?
  • TCP 作为“传输层协议”为上层提供了双向通道,我认为应该看上下文。
  • TCP 不关心 IP 层以下的层做什么或不做什么,只要它们可以移动 IP 数据报即可。
  • TCP 当然可以是全双工的,其中两个主机可以同时生成数据报。然而,真正决定这些数据报(现在是帧)能否以全双工方式交换的是 MAC 和 PHY 层。

标签: sockets tcp duplex


【解决方案1】:

两者兼而有之。它是双向的,因为它可以双向发送数据,它是全双工的,因为它可以在 API 级别同时执行此操作,而无需换线。

当然,在较低级别上,它可能会受到可用物理层的限制。

【讨论】:

    【解决方案2】:

    它肯定是双向的,因为双方都发送/接收数据包。当您询问 TCP 是否为全双工时,您究竟是什么意思?

    同时发送和接收数据包更多地与物理组件有关,而 TCP 是一种协议,它定义了应如何构建和处理数据以到达目的地。

    NIC(网络接口控制器)负责发送和接收物理数据包,您必须在那里检查半双工/全双工功能。

    例如,无线 (802.11) 是半双工的,如果它使用相同的天线来发送和接收无线电信号。

    【讨论】:

    【解决方案3】:

    TCP API 是全双工的。这意味着 TCP API 允许同时从连接的两端发送数据。让我们看看测试程序的来源来证明:

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #include <unistd.h>
    
    
    void do_write(const char* who, int socket) {
        const char hello[] = "hello!";
        if( 0 < write(socket, hello, strlen(hello)) )
            printf( "%s: write done ok\n", who );
        else
            printf( "%s: write error: %s\n", who, strerror(errno) );
    }
    
    void do_read(const char* who, int socket) {
        /* do parental things with this end, like reading the child's message */
        char buf[1024];
        int n = read(socket, buf, sizeof(buf));
        if( 0 < n )
            printf("%s: received '%.*s' %db\n", who, n, buf, n);
        else if( 0 == n )
            printf( "%s: no data available\n", who );
        else
            printf( "%s: read error: %s\n", who, strerror(errno) );
    }
    
    int main() {
        int fd[2];
        static const int parent = 0;
        static const int child = 1;
        pid_t pid;
    
        socketpair(PF_LOCAL, SOCK_STREAM, 0, fd);
    
        pid = fork();
        if (pid == 0) {      /* child process */
            close(fd[parent]);
            do_write("child", fd[child]);
            do_read("child", fd[child]);
            /* sleep(1); */
            do_write("child", fd[child]);
            do_read("child", fd[child]);
        } else {             /* parent process */
            close(fd[child]);
            do_write("parent", fd[parent]);
            do_read("parent", fd[parent]);
            do_write("parent", fd[parent]);
            do_read("parent", fd[parent]);
        }
    
        return 0;
    }
    

    输出(在 FreeBSD 上)是:

    parent: write done ok
    child: write done ok
    child: received 'hello!' 6b
    child: write done ok
    parent: received 'hello!hello!' 12b
    parent: write done ok
    child: received 'hello!' 6b
    parent: no data available
    

    所以 TCP API 是全双工的,数据可以同时从双方发送。我认为实现也是全双工的,但它需要编写更复杂的测试来识别。当然,这取决于实现。当至少一个传输链链路不是全双工时,良好的实施可能不会产生影响。

    【讨论】:

    • 这不是'源',它是你写的一个测试程序。
    • 测试程序的来源并不能证明什么。问题是关于 TCP 的。问题中没有出现“API”一词。
    • 谢谢,oklas,你的证明源代码正是我要找的。​​span>
    【解决方案4】:

    是的,TCP 连接提供全双工服务。让我们了解全双工的含义。这意味着同时在两个实体之间交换数据(发送和接收)。由于 TCP 是一种传输层协议,传输层协议提供了运行在不同主机上的进程之间的逻辑通信,所以这里全双工的含义也在这方面。

    这里全双工的意思是“如果一台主机上的进程A和另一台主机上的进程B之间存在TCP连接,那么应用层数据可以从进程A流向进程B在应用层数据从进程 B 流向进程 A 的同时”。 TCP 连接也始终是点对点,即在单个发送方和单个发送方之间接收者。请记住,来自进程 A 的数据尚未通过传输层以下的层,同样来自进程 B 的数据将通过传输层以下的层。

    来源:Kurose, Ross 的计算机网络。

    【讨论】:

    • 不需要单独的主机甚至单独的进程。
    【解决方案5】:

    通过阅读您发布的文章,我认为很明显他们在谈论 TCP 支持全双工通信(强调我的):

    [TCP] 是全双工协议,这意味着每个 TCP 连接支持一对字节流,每个方向一个流。

    【讨论】:

      【解决方案6】:

      这取决于您在考虑哪一层。在物理层上,取决于介质,电信号如何传输;如果您从传输层考虑,它是全双工的,因为每个对等方都可以根据需要同时发送和接收。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-15
        • 1970-01-01
        • 2014-06-18
        • 1970-01-01
        • 2015-03-15
        • 1970-01-01
        相关资源
        最近更新 更多