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

Is TCP bidirectional or full-duplex?

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

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

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

当然是双向的,因为双方都发送/接收数据包。当你问TCP是否是全双工时,你到底是什么意思?

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

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

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

两者都是。它是双向的,因为它可以在两个方向上发送数据,它是全双工的,因为它可以在 API 级别同时进行,而不需要线路周转。

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

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

[TCP] is a full duplex protocol, meaning that each TCP connection supports a pair of byte streams, one flowing in each direction.

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

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

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

这里full-duplex表示"If there is a TCP connection between Process A on one host and Process B on another host, then application layer data can flow from Process A to Process B at the same time as application layer data flows from Process B to Process A"。TCP连接也总是point-to-point,即单个发送者和单个接收者之间。请记住,来自进程 A 的数据尚未通过传输层以下的层,类似地,来自进程 B 的数据将通过传输层以下的层。

资料来源:计算机网络作者 Kurose, Ross。

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