I have a C++ application that currently uses a simple TCP/IP client/server model to communicate between 2 instances of itself. This works fine on a local network, but I would like this to be used across an external network. Currently, maybe due to firewall issues, it is not able to connect across an external network.
I am not an expert on networking, but I was thinking about having a dedicated server in the middle acting as a hub for communications. Will this mitigate firewall issues?
How do networked games communicate with each other? Is there usually a server in the middle or is it peer-to-peer?
In any case, I'd appreciate any advice on protocols and infrastructure to implement a network enabled application.
Regards
I think the problem is dedicated to the NAT as mentioned by cnicutar.
Maybe you want to have a look at libupnp for automatic port forwarding in the hardware firewalls (your router at home)
There is no de facto architecture for multiplayer network games. Both client-server (most MMOs, most PC FPS's and RTS's) and Peer-to-Peer (most console games) are valid approaches.
Juoni Smed's survey in his book "Algorithms and Networking for Computer Games" is a pretty good overview of the different architectures in the wild.
For the specific issues you're talking about, your need for a proxy server, as others have noted, is probably down to NAT issues - the two machines you're trying to get talking do not have public IP addresses. If you want to pursue a Peer-to-Peer architecture (or to have one of your clients act as the server, as many modern Client-Server games do) you will need your clients to talk directly to each other. This can be achieved with NAT Traversal, unfortunately this is a fiddly process.
Luckily you can use a modern framework like the excellent Raknet which includes State Synchronisation, Remote Procedure Calls AND NAT Traversal out of the box. It's free for hobbyist use and is incorporated in to several modern industrial-grade game engines.
The bane of modern internet communications is NAT. Due to NAT (which shouldn't be confused with a simple firewall) a large portion of hosts on the internet don't have a public address and thus can't (easily) accept incoming connections. NAT breaks the internet so badly that people are moving to a totally different scheme, with slightly different semantics, just to get rid of it.
There are basically two class of solutions
NAT traversal which is sometimes used for peer-to-peer communication. Usually NAT traversal schemes require some publicly accessible server for brokering the initial connection, but the actual communication is done peer-to-peer
Client-server communication. This is easier (since the server generally should have a publicly accessible address) but also kind of inefficient. For instance, say you've got a peer on the same 10Gb LAN. If you want to send him a file through the server (which happens to be in another country) it's going to take ages instead of seconds.
I'm not sure which one is "generally used". But think of it this way:
If there is the logical need for a "controller" (say 8 people are playing a strategy game) then you probably need a server
If any two peers can logically interact without a "controller", you probably want peer-to-peer communication
If you need to transfer LOTS of data fast (file transfer), you almost surely want p2p.
The easiest way to accomplish what you want is by using sockets(in case you are doing it differently). The way you are connecting your app is usually how it's done. Also if it work sin a local network and it does not over the Internet it must be a firewall issue so try opening ports in your router configuration.
You will have to give more info about your program in order to explain if you should go with peer-to-peer or with a server.
Related
I'm thinking about creating EC2 instances that run industrial software. This EC2 instance should be able to receive data from Serial COM port. Is it possible to connect things like this, with eventually a serial tunneling or anything else ?
There are two parts to the answer to this question.
Yes, absolutely, this is possible in theory.
...but it might not be practical or possible for the specific purpose/application/device that you have in mind.
Terminal servers are a simple illustration of the principle. Note that in this sense, I'm not referring to a Windows Remote Desktop "terminal server," but to the generic device commonly called a terminal server which, in its simplest form, is a physical device that speaks a serial protocol such as RS-232 on one side, and TCP on the other side. RS-232 is the wire protocol of a PC "COM" port.
But a computer, configured with appropriate drivers, can have a "virtual" COM port that appears -- to software on the computer -- as an interface just like a physical COM port, but the driver for that COM port, instead of providing the software with access to literal hardware is in fact managing a TCP connection, tunneling the send and receive bits from the COM port back to the physical port on the terminal server.
The terminal server could be an actual, dedicated terminal server device, could be a full size PC, a microcontroller with network capability, a Raspberry Pi with a USB-to-Serial adapter... there are a lot of potential variations.
Problems to consider:
A lot of older industrial software seems very poorly written. This is my impression, anyway. The implementers, perhaps working at the edges of their expertise, having made certain design assumptions that work on physical COM ports but may not be compatible with such a deployment. This is less likely to be true if the systems are newer, and run on a modern OS, but back in the early days of Windows and before, this was a real mess.
License key dongles, if present, might rely on peculiarities of physical COM ports that are difficult or impossible to virtualize. The terms of the software license may constrain you from doing this.
Some equipment may be unnecessarily sensitive to the delay that is introduced by the distances involved. There are, for example, 22 ms of round-trip time in the Internet path between one of my facilities and the nearest AWS region. At 9600-8-N-1 that is the time to transmit ~23 bytes, and that's best case -- the virtualization layer and encryption will add more. The machine or the software may or may not be well-written enough to accept that kind of delay, which does not occur on a physical, local COM port.
If the machine is being controlled (not simply observed) then you need to absolutely ensure that you are not creating a safety hazard by separating the machine from its software through a virtualization layer.
"Sharing" control of a machine by software on multiple EC2 instances seems like it might be implied by your illustration, but this potentially adds an entirely different set of complexity.
In theory, yes, it's possible. I mean, even Windows remote desktop allows you to share a local COM port with the remote system, allowing remote software to access and control your local device.
In practice, this potentially requires a lot of attention to a large number of factors that vary by operating system as well as by the specific peculiarities of the devices and software in question.
EC2 connectivity is through the network interface, so I don't think a direct connection like the one you are asking is possible.
However, if you are talking about industrial devices supporting automation, chances are you can use MQTT or at least a MQTT bridge. If that's the case, you can take a look at AWS IOT Core
With AWS IOT Core you don't only get bidirectional connectivity between your devices and AWS, but also powerful analytics, device registry and management, and full integration with the AWS ecosystem.
There's lots of games on Steam nowadays (Table Top Simulator, SpeedRunners) that allows people to host their own online multiplayer matches/games without the need for port forwarding.
One thing I thought of of how they do it is they simply have one server that processes all the matches as separate threads.
But then I'm starting to wonder about getting bottle necked.
I then heard these games simply somehow allow TCP to be holepunched through their NAT, getting past the need for port forwarding.
But how in say, C++ using winsock, would one do this? Or GameMaker: Studio? Or just any game in general? How do you allow people to play without port forwarding? What's the process?
I see so many games on Steam do it nowadays it must not be too complicated.
As this question is explicitely related to steam, I think it's worth mentioning the steamworks API, especially SteamNetworking. It allows peer-to-peer connection relaying through steam servers:
https://partner.steamgames.com/doc/api/ISteamNetworking
bool AllowP2PPacketRelay( bool bAllow );
Allow or disallow P2P connections to fall back to being relayed
through the Steam servers if a direct connection or NAT-traversal
cannot be established.
One may use UPnP to automatically configure the router to do the port forwarding. There's a library for that in http://pupnp.sourceforge.net/
The alternative way is to have a external server managing all traffic, so that everyone connects there, thus avoiding nat issues.
I would like to have some advices about my project. I am currently developing a musical application/game in C++/Qt, with a multiplayer mode, and I have the following requirements (ideally):
I want to be able to have friends contacts, and be able to chat and play with them
I need to send/receive realtime datas to these contacts (music notes)
I don't want to create a server application
What would you recommend to do this?
I was thinking of using xmpp protocol, so I can connect to google/jabber and retrieve contacts, chat with them. Actually this part works, but then I don't konw how to send/receive realtime datas. For the realtime part, I was thinking of using direct TCP communication, but I need to know external ip of my contacts, and I have no idea how to do it. I was thinking to automatically send my external ip and tcp port to all my contacts every time I connect, but I didn't find solution to retrieve external ip from code. So I'm a bit stuck. Any advice?
Is there alternative solutions? alternative protocols?
Thanks you,
Laurent
You're going to have a really hard time avoiding writing a server, for realistic, practical, and performance reasons:
Many residential internet connections are behind firewalls (at the ISP, local router, or OS level) that limit accepting connections from outside the network. NAT further complicates accepting connections from the internet on a LAN.
There are precious few methods of internet communication that are serverless, and those that are are subject to using local peer discovery to find peers. Most LPD traffic will not make it off your lan, the ISP will filter it (otherwise you'd be able to "locally" discover peers on the entire internet).
Bandwidth can be a concern for games. Not everyone has a high speed internet connection yet (though market penetration of fiber optics and fast DSL is pretty high at this point), and you'd end up with problems connecting slower hosts to a large swarm.
Servers facilitate star-like networks, which are very efficient. Other network topologies exist, but many suffer from drawbacks that severely inhibit their ability to scale.
Star networks, for example, for clients, require O(connections) =
O(1), O(bandwidth) = O(1), and O(latency) = O(1).
Fully connected networks require every client to be connected to
every other client, so O(connections) = O(bandwidth) = O(n), and
O(latency) = O(1).
In ring networks, each client connects to 2 neighbors and messages of
distant clients are forwarded. Therefore, they have O(connections) =
O(1), but O(bandwidth) = O(latency) = O(n).
If all you need is a chat system, or want badly enough not to write your own server that you're willing to piggyback the entire online experience over a chat server, you could probably rely on something like an XMPP server.
If you choose to go that route, make sure that proper authentication and encryption is used wherever necessary to protect user's private data (passwords, etc). I recommend using a cryptographic authentication scheme that allows clients to authenticate other clients (such as a challenge/response scheme, or something else). Or, you could mediate all authentication with a central service.
Keep in mind that many chat services will not want to provide your project with free bandwidth. Even if you do decide to use XMPP as the heart of your multiplayer protocol, expect to be running your own server.
I've been reading around on the www but just can't get the most important basics of P2P.
The diagram is like this:
[peer1]<-->[dsl-router1]<-->[central server]<-->[dsl-router2]<-->[peer2]
I'm developing a chat software on the central server. Chat messages being transfered thru' the central server well by now, however, I need to make the p2p file sharing feature because the bandwidth (the cable bandwith, not the transfer limit) of the server supposed for transfering chat messages only.
The problem is that, my software on central server knows the IPs and ports of router1 and router2, but not the peer1 and peer2 as these peers are behind the routers and don't have IP addresses.
How to actually transfer some data from peer1 to peer2 and vice versa without having this data passing thru' central server?
(and the worst case is that there is a wireless router between peer and dsl-router)
There are two basic ways of doing this. The new way is to use IGDP (opening a port via uPnP). This is described quite well here:
http://www.codeproject.com/Articles/13285/Using-UPnP-for-Programmatic-Port-Forwardings-and-N
If neither of the two nodes have a router supporting uPnP then another alternative is TCP hole punching, which is not perfect but works quite well in practice. This is described here:
http://www.brynosaurus.com/pub/net/p2pnat/
During some situations, "routers" supplied by the ISP may run on bridge mode, which directly exposes the peer computer on the internet (the computer gets a public internet address). If at least one side has this configuration (or in a similar situation that the peer client is not behind another device), then things should be rather straight forward: simply assign the central server's job to whoever that have this privilege.
In the other case where both peers only have a local address (e.g. 192.168.0.2) assigned to their computers, it would then be rather difficult to get through the routers; clients behind routers are for the most part unreachable from the outside unless they originated the request. Then, one solution to the problem is port forwarding. By doing port forwarding, either through explicitly written rules or UPnP, some ports on the peer computer is exposed to the public internet, as in the first situation where instead of only some ports the entire computer is exposed.
If you are without either of these, then there is no simple way to avoid sending through the central server. Though you could, potentially, find other peers who have the capability to transfer for others.
Let's say I have a server, and two clients connected to it. (via TCP, but it doesn't matter)
My goal is to allow a direct connection between those two clients. This is to allow direct voice contact between two players, for example, or any other client plugin they may have installed which don't need server interaction (like playing some kind of random game between the two). The server can be there to help setting up the connection.
From duskwuff's answer, I got several leads:
http://en.wikipedia.org/wiki/STUN which describes an algorithm to do that, and
http://en.wikipedia.org/wiki/UDP_hole_punching
From those, I got more leads:
http://www.h-online.com/security/features/How-Skype-Co-get-round-firewalls-747197.html
http://nutss.gforge.cis.cornell.edu/stunt.php -- A possible STUN implementation with TCP
With time, I could surely work out something for my program. For now I'm using C++ and TCP (Qt Sockets or Boost sockets), but if needed I don't mind doing UDP in C and wrapping it.
The bounty is there for any programmer having experience with those in C and C++ that may give tips to make this easier, by linking to example programs, updated libraries, or any other useful information. A documented, flexible & working C++ TCP implementation would be the best but I'll take what I get!
Punching TCP holes in NAT is sometimes/often possible (it depends of the NAT behavior). This is not a simple subject to learn, but read the corresponding chapter about NAT traversal from Practical JXTA II (available online on Scribd) to understand the nature of the issues to solve.
Then, read this. It comes from the guy who wrote that: http://nutss.gforge.cis.cornell.edu/stunt.php (one of the links in your question).
I am not a C/C++ specialist, but the issues to solve are not language specific. As long as you have access to TCP from your code base, that's enough. Keep in mind that implementing UDP traversal is easier than TCP.
Hope these tips help.
P.S.: I am not aware of a C/C++ implementation of the solution. The code mentioned in Cornell's link is NOT operational as confirmed by the author. I tried to resuscitate it myself, but he let me know it was completely tweaked for research purposes and far from production ready.
I'm not aware of any way to reliably punch through firewalls for TCP, but there's a similar method for UDP traffic that's pretty well documented:
http://en.wikipedia.org/wiki/STUN
http://en.wikipedia.org/wiki/UDP_hole_punching
A few links to projects that might be of interest or helpful:
http://sourceforge.net/projects/stun/
http://udt.sourceforge.net/
http://www.telehash.org/
You're looking for rendezvous server for NAT hole punching: the server that is publicly accessible (not behind NAT/firewall or they are properly configured) to help computers behind NAT/firewall to establish peer-to-peer connection.
UDP is more popular in NAT punching because provides much better results than TCP. Clear and informative description of UDP NAT hole punching can be found here.
If you need reliable communication, you can use reliable protocols over UDP:
SCTP (libraries) - standardized one, or
one of many custom protocols, e.g. RakNet (I used this library, it's quite mature and feature-rich and has NAT punching implementation), Enet or many others (Q8)
Ephemeral ports won't magically eliminate the need to relay through the server, because they are only valid during the life of the session opened through a well known service port. Basically ephemeral ports depend on a server session.
You will need to use the server to relay communications between both clients, that is act as a proxy server. One option would be to setup a SSH tunnel through a SSH proxy server, with the added benefit of security.
Still this doesn't guarantee that the firewall won't block the connection. That depends on the firewall type and configuration. Most residential routers that act as firewalls, by default block all incoming connections. This is normally fine because most of the time the computers behind the firewall act only as clients, which initiate the connections to the outside. And this setup varies, because some restrict initiating connections only to well known service ports like HTTP, HTTPS, FTP, SFTP, SSH, etc., and if your proxy server uses a non-well-known-service port then the connection will be blocked.
But firewalls can be setup to block outgoing traffic also, this is most common in corporate networks, which don't even allow direct connections to web servers and route everything through proxy servers, in order to control resource usage.
You can also research on the use of UPnP to open ports dynamically.