# Point-to-point communication (MPI) In a single-process C program, functions communicate through shared memory: one writes to a variable and another reads it. Across processes with separate address spaces — especially on different machines — that doesn't work. The low-level solution is sockets: `send(fd, buf, n, 0)` pushes bytes out and `recv(fd, buf, n, 0)` pulls them in on the other end. MPI point-to-point communication is the same idea at a higher level: you address messages by process rank instead of file descriptor, and the runtime handles the network transport. `MPI_Send` transmits a buffer to a target rank; `MPI_Recv` receives into a buffer from a source rank. Both specify the buffer address, element count, datatype, peer rank, message tag, and communicator. The tag is an integer that distinguishes between multiple messages from the same sender. ```c if (rank == 0) { int x = 42; MPI_Send(&x, 1, MPI_INT, 1, 0, MPI_COMM_WORLD); } else if (rank == 1) { int x; MPI_Recv(&x, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); printf("received %d\n", x); } ``` `MPI_ANY_SOURCE` and `MPI_ANY_TAG` are wildcards that match any sender or tag in `MPI_Recv`. When wildcards are used, the actual source, tag, and element count are returned in the `MPI_Status` struct. `MPI_Sendrecv` combines a send and a receive in a single call, which is the simplest way to avoid deadlock in patterns where every process must both send and receive simultaneously.