TCP是双向的还是全双工的?

Posted

技术标签:

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

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

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

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

【问题讨论】:

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

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

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

【讨论】:

【参考方案2】:

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

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

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

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

【讨论】:

谢谢。所以我认为duplex这个词只是不适用到TCP。所以本教程 (ssfnet.org/Exchange/tcp/tcpTutorialNotes.html) 不准确地说是TCP is Full-Duplex 我认为是指TCP协议支持全双工通信。【参考方案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】:

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

【讨论】:

以上是关于TCP是双向的还是全双工的?的主要内容,如果未能解决你的问题,请参考以下文章

Android最佳实践——深入浅出WebSocket协议

单工半双工全双工的区别

网络半双工和全双工

使用WebSocket进行全双工通信

WebSocket(基于TCP的全双工通信协议)

Linux TCP并不是全双工的