 <p>The TCP protocol described in <a href="http://www.ietf.org/rfc/rfc793.txt" rel="nofollow">RFC 793</a> describes the terms <em>socket</em> and <em>connection</em>. A <em>socket</em> is an IP address and port number pair. A <em>connection</em> is a pair of <em>sockets</em>. In this sense, the same <em>socket</em> can be used for multiple <em>connections</em>. It is in this sense that the <code>socket</code> being passed to <code>accept()</code> is being used. Since a <em>socket</em> can be used for multiple connections, and the <code>socket</code> passed to <code>accept()</code> represents that <em>socket</em>, the API creates a new <code>socket</code> to represent the <em>connection</em>.</p> <p>If you just want an easy way to make sure the one <code>socket</code> that <code>accept()</code> creates for you is the same socket you used to do the <code>accept()</code> call on, then use a wrapper FTW:</p> <pre><code>int accept_one (int accept_sock, struct sockaddr *addr, socklen_t *addrlen) { int sock = accept(accept_sock, addr, addrlen); if (sock &gt;= 0) { dup2(sock, accept_sock); close(sock); sock = accept_sock; } return sock; } </code></pre> <p>If you are wanting a way for a client and server to connect to each other, without creating any more than just one <code>socket</code> on each side, such an API does exist. The API is <code>connect()</code>, and it succeeds when you achieve a <a href="http://stackoverflow.com/questions/5139808/tcp-simultaneous-open-and-self-connect-prevention"><em>simultaneous open</em></a>.</p> <pre><code>static struct sockaddr_in server_addr; static struct sockaddr_in client_addr; void init_addr (struct sockaddr_in *addr, short port) { struct sockaddr_in tmp = { .sin_family = AF_INET, .sin_port = htons(port), .sin_addr = { htonl(INADDR_LOOPBACK) } }; *addr = tmp; } void connect_accept (int sock, struct sockaddr_in *from, struct sockaddr_in *to) { const int one = 1; int r; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &amp;one, sizeof(one)); bind(sock, (struct sockaddr *)from, sizeof(*from)); do r = connect(sock, (struct sockaddr *)to, sizeof(*to)); while (r != 0); } void do_peer (char *who, const char *msg, size_t len, struct sockaddr_in *from, struct sockaddr_in *to) { int sock = socket(PF_INET, SOCK_STREAM, 0); connect_accept(sock, from, to); write(sock, msg, len-1); shutdown(sock, SHUT_WR); char buf[256]; int r = read(sock, buf, sizeof(buf)); close(sock); if (r &gt; 0) printf("%s received: %.*s%s", who, r, buf, buf[r-1] == '\n' ? "" : "...\n"); else if (r &lt; 0) perror("read"); } void do_client () { const char msg[] = "client says hi\n"; do_peer("client", msg, sizeof(msg), &amp;client_addr, &amp;server_addr); } void do_server () { const char msg[] = "server says hi\n"; do_peer("server", msg, sizeof(msg), &amp;server_addr, &amp;client_addr); } int main () { init_addr(&amp;server_addr, 4321); init_addr(&amp;client_addr, 4322); pid_t p = fork(); switch (p) { case 0: do_client(); break; case -1: perror("fork"); exit(EXIT_FAILURE); default: do_server(); waitpid(p, 0, 0); } return 0; } </code></pre> <p>If instead you are worried about performance issues, I believe those worries are misguided. Using the TCP protocol, you already have to wait at least one full round trip on the network between the client and the server, so the extra overhead of dealing with another socket is negligible. A possible case where you might care about that overhead is if the client and server are on the same machine, but even then, it is only an issue if the connections are very short lived. If the connections are so short lived, then it would probably be better to redesign your solution to either use a cheaper communication medium (e.g., shared memory), or apply framing on your data and use a persistent connection.</p>