3

I am currently working on a C++ networking program using Winsock 2, it's a chatting program without a server between the two computers. It would be convenient if none of the users are forced to run a server program, which has a listener, it makes them have to port forward. This would, of course, require them to both enter each other's IPs, but that's okay. Is there a way to create a TCP connection by running the same client program on two different computers, using the same port and each inputting the other computer's IP without having to port forward?

BubLblckZ
  • 434
  • 4
  • 14
  • 3
    There are ways to connect to another computer without opening the port (TCP/UDP hole punching), but one of them has to listen. – tkausl Jan 13 '20 at 16:11
  • 1
    Once established a TCP connection is symetric. But the establishment is not: one part has to call `listen` and `accept` while the other calls `connect`. Use UDP if you want symetry. – Serge Ballesta Jan 13 '20 at 16:23

3 Answers3

5

Although you will need to call bind in order to allow another machine to connect to that port, you do not need to call accept.

As long as both processes have called bind on their accepting port, then assuming that the address sin is initialized to the appropriate destination, each process can symmetrically connect to each other using a loop that looks like this:

  while (connect(s, sin, slen) < 0) {
      if (errno == ECONNREFUSED) continue;
      perror("connect");
      _exit(0);
  }

This is the "simultaneous open" case in the TCP state machine diagram. Each side sends SYN simultaneously, so each side responds with SYN/ACK. After each side sends ACK to complete the 3-way handshake, both sides enter the ESTABLISHED state.

Try It Online does not support threads or access to loopback, but it does allow me to conveniently present the complete coding example.

jxh
  • 69,070
  • 8
  • 110
  • 193
0

If I right understand your task: (2 home computers in different networks, without "white" ip-addresses; computers those connected to internet through providers).

Answer: You can't. You can't through UDP too.

You need something with ip-address, available from external networks. That is named server (or home computer) with "white" ip-address. And that "something" should receive your TCP connections.

Evgeny
  • 1,072
  • 6
  • 6
0

In TCP, one party must call bind(), listen(), and accept(), while the other party must call connect(). There is no getting around that, that is just how TCP works.

If the listener is behind a NAT/Proxy, it must use port forwarding as needed.

Have the clients decide who is initially the listener and who is the connecter. If a connection fails, reverse the roles and try again. If a connection still fails, then you need an outside server that both clients can connect to, to facilitate communications between them.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 1
    Found a working way to do it, at least with what I meant (not using a listener and without port forwarding). So it works with two computers running the same program. First you use bind() to bind the socket to the local address and some port, and then you use connect() to the other computer's IP with the same port. – BubLblckZ Jan 14 '20 at 19:01
  • @BubLblckZ That typically requires the app on the other computer to call `listen()` and `accept()` for `connect()` to connect to.. Unless you are trying to [hole-punch your way through a NAT](https://en.wikipedia.org/wiki/TCP_hole_punching), which is a whole different thing... – Remy Lebeau Jan 14 '20 at 21:15
  • 1
    See jxh's answer to this post, that is how I meant. – BubLblckZ Jan 23 '20 at 20:54