Is TCP bidirectional or full-duplex?

It is both. It is bidirectional because it can send data in both directions, and it is full-duplex because it can do that simultaneously, without requiring line turnarounds, at the API level.

Of course at a lower level it may be restricted by the available physical layer.


It's certainly bidirectional, since both parties send / receive packets. What exactly do you mean when you ask if TCP is full-duplex?

Both sending and receiving packets at the same time has more to do with the physical component, while TCP is a protocol defining how data should be framed and handled in order to reach the destination.

The NIC (Network Interface Controller) is responsible for sending and receiving physical packets and you would have to check there about the half / full - duplex capabilities.

Wireless (802.11) for example is half-duplex if it is using the same antenna for sending and receiving radio signal.


The TCP API is full-duplex. This mean that TCP API allow send data from both side of connection just in same time. Let's see the source of test program to proof:

#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;
}

The output (on FreeBSD) is:

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

So TCP API is full-duplex and data may be sended from both side at the same time. I think that implementation is full-duplex too, but it need to write more complicated test to recognize. This is implementation dependent of course. And good implementation may does not effect when at least one transport chain link is not full-duplex.