I want to code a peer-to-peer like chat program in C#. I am trying to figure out how the networking would work. I know that the concept is that each peer is a client and a server at the same time. It can connect and be connected to. But my question is, how do you connect to a computer behind a router without the port being forwarded to that computer? I know things like Bittorrent do this with no problem. I was planning on using a tracker to keep a list of peers and the ports they listen on, but I still don't understand how to get through the router issue. Could someone please explain?
You're right, it's not trivial. The problem is something called NAT, or network address translation. Essentially, the IP you have within your own local network is unique, but within the broader context of the public Internet, many people behind the same router will have the same public IP. Thus, given an IP and some data, you can't necessarily tell which person on the other end should be getting it.
The most effective and easiest solution is to have a third party mediate the connection by interposing itself into the data stream. Instead of each person in the chat being a "client" and a "server" at the same time, there's only one server, and it's at a well-known public location; then everybody connects to it. The server then manages the communications and sends messages to people as they chat.
There are other solutions, though. For instance, instead of using a well-known server, you could use a well-known port(s): all communications take place on this port(s). Then you don't need a server, but all endpoints need to have that port open, which requires configuration beforehand.
I'm assuming that you mean in a NAT environment, and if so read and understand Peer-to-Peer Communication Across Network Address Translators (Ford, Srisuresh & Kegel.
The key concept is that each client must initiate a connection which will open a path through the NAT device. It may be useful to refer to the Pidgin source code to get some ideas.