c#.net framework 4.0 client profile,Windows application..
i am developing a game which needs to send its current movements of the game through internet to remote computer where the same application(game) is installed.In Same way current movements of the game of remote computer should be send back...
How this could be possible ?
All the answers so far are using a TCP based approach. If you need high performance and low latency then you might find it better to use UDP instead.
TCP brings a lot of overhead with it to guarantee that packets will be resent if they are lost (and various other bits of functionality). UDP on the other hand leaves it up to you to deal with packets not arriving. If you have a game where losing the odd update isn't important you can achieve far better bandwidth use, latency and scalability by using UDP instead of TCP.
UDP still leaves you with all the issues of firewalls, security etc though.
If you need to have it work without worrying about firewalls being an issue then you want to choose a solution that uses HTTP over port 80.
To do that you need to implement a client-server behavior through TCP/IP
There are very different ways to do this
This code I've written could give you a start (it's an option, but not the only one, I leave it off to you to choose the method that suits you best)
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
static class ServerProgram
{
[STAThread]
static void Main()
{
ATSServer();
}
static void ATSServer()
{
TcpChannel tcpChannel = new TcpChannel(7000);
ChannelServices.RegisterChannel(tcpChannel);
Type commonInterfaceType = Type.GetType("ATSRemoteControl");
RemotingConfiguration.RegisterWellKnownServiceType(commonInterfaceType,
"RemoteATSServer", WellKnownObjectMode.SingleCall);
}
}
public interface ATSRemoteControlInterface
{
string yourRemoteMethod(string parameter);
}
public class ATSRemoteControl : MarshalByRefObject, ATSRemoteControlInterface
{
public string yourRemoteMethod(string GamerMovementParameter)
{
string returnStatus = "GAME MOVEMENT LAUNCHED";
Console.WriteLine("Enquiry for {0}", GamerMovementParameter);
Console.WriteLine("Sending back status: {0}", returnStatus);
return returnStatus;
}
}
class ATSLauncherClient
{
static ATSRemoteControlInterface remoteObject;
public static void RegisterServerConnection()
{
TcpChannel tcpChannel = new TcpChannel();
ChannelServices.RegisterChannel(tcpChannel);
Type requiredType = typeof(ATSRemoteControlInterface);
//HERE YOU ADJUST THE REMOTE TCP/IP ADDRESS
//IMPLEMENT RETRIEVAL PROGRAMATICALLY RATHER THAN HARDCODING
remoteObject = (ATSRemoteControlInterface)Activator.GetObject(requiredType,
"tcp://localhost:7000/RemoteATSServer");
string s = "";
s = remoteObject.yourRemoteMethod("GamerMovement");
}
public static void Launch(String GamerMovementParameter)
{
remoteObject.yourRemoteMethod(GamerMovementParameter);
}
}
Hope this Helps.
You should look into some middleware teknologies like WCF, Web service
this is object oriented and easy to develop when you first get the hang of it
You have a lot to consider for this.
You will need to think about security, firewall issues etc.
If that is all put to one side, then you can set up a tcp socket server / client approach.
A quick google will yield plenty of examples.
Check out the Microsoft example http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.aspx
What have you tried?
You can use the System.Net and System.Net.Sockets namespaces to send TCP packets.
Related
How can I check PC is Connected with Intranet or Internet without using Ping method and IP address in C#?
For my use case, I needed to have a service up in a LAN network and check Network status from time to time. I eventually used this:
static readonly INetworkListManager NetworkListManager = new NetworkListManager();
// ...
while (NetworkListManager.IsConnected) {
// do something...
}
// loop is over. no internet!
while (!NetworkListManager.IsConnected) {
// wait for reconnection...
}
In my case that achieved what I needed, and with some testing it also worked on my WAN environment. But as always, there's no 100% correct assumption when it comes to interacting with other hardware. Incorrect result can happen, so put in as much as test you can.
Here's something i used for a game of mine to detect if there is a network connection without it even touching or talking the router or other devices:
// Recommended for clean code
public static bool InternetConnection() => System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
The code above is just the same as:
public static bool InternetConnection() {
return System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
}
I have a very strange problem with my connection to a server on a TCPListener/TCPClient basis. At some point during testing I am unable to connect to my server-application anymore, every try it times out. Netstats on both sides show, that my application listens on the right port, and the client is trying to connect to the right ip and port, but it does not advance further than "SYN_SENT". The server just displays "LISTENING" all the time. All I can do is restart my PC, which temporarily fixes this problem. But after some connections, it starts all over again.
Up to now I tested TCPClient and Sockets class to connect to the server but both show this behaviour, what is not surprising, as TCPClient is a wrapper around the Sockets Class afaik.
Firewall is checked on both sides, things like Remote Desktop work perfectly fine, and is not blocking the Connection of my Application. There are no connections left to close or something, already cheked everything I know (maybe not that much ;) )
So whats the problem?
Edit:
A Method that needs to connect to my Server:
public int GetSomeDataFromServer(string blargh)
{
int ret;
try
{
using(ConnectionTCPStream ctp = new ConnectionTCPStream())
{
if(ctp.EstSecConnWithServ())
{
ret = CKSHandler(ctp, blargh);
}
else
{ ret = (int)ErrFlags.ServerDeniedConnection; }
}
return ret;
}
catch(Exception)
{
InternalError = ErrFlags.ServerUnreachable;
return (int)ErrFlags.ServerUnreachable;
}
}
The Constructor of my Class that is dealing with the Connections:
public ConnectionTCPStream()
{
Client = new TcpClient("VeryImportantAdress", 49778); //it fails right here!
rsaCrypt = new RSACH() { RSAForeignPubKey = "An 8192-Bit long RSA Public key." };
AESPASS = AESThenHMAC.CreatePassword(200);
}
Sounds like you are using up all your connections or some other resource.
What do you see when you do a netstat -an ? Do you see a bunch of open ports?
There an Article Here that could possibly help you here
Some other resource may be killing you, might be worth having an SA fire up a resource monitor to check the health of the host when you run into this situation.
If there's no errors being thrown, it makes your life that much harder. The problem typically happens when you don't cleanly clean up your socket disconnects.
The answer is the firewall which changed its mind every now and then. I couldn't test that before because i had no access to it. Now i have changed settings while i had this blockade and it worked fine again. So the answer is: Always have access to the firewall and don't forget to check it.
I've been playing with XNA and want to try and make a game work over LAN but it turns out that to do this I need to use something called remoting. Anyway I managed to get this to work
public class TestObject : MarshalByRefObject
{
int testInt;
public Level()
{
this.testInt = 5.Zero;
}
public int GetNumber()
{
return testInt;
}
}
and my server
channel = new TcpChannel(4444);
ChannelServices.RegisterChannel(channel, false);
Type type = Type.GetType("Domain.Level,Domain");
RemotingConfiguration.RegisterWellKnownServiceType(type,
"FirstRemote",
WellKnownObjectMode.Singleton);
and client
this.chanel = new TcpChannel();
ChannelServices.RegisterChannel(chanel, false);
this.testObject = (TestObject)Activator.GetObject(typeof(TestObject),
"tcp://localhost:4444/FirstRemote");
so that works but the problem is that the server has no way to access the object and I cant make a constructor that takes arguments so there is no way to initialize any data on the test object. How do I make an object, and then make it use that instead of making a new object?
Unfortunately, you'll probably find that realtime network communication in games is more complex than the current direction you're taking. Most games use persistent socket connections to pass information back and forth between clients and other methods are generally too slow for realtime networking.
I recommend looking into the Lidgren networking library. Lidgren abstracts network communication and makes it much easier to serialize data into very small and fast packets that can be transferred via several reliability modes across UDP and TCP. You can find the Lidgren project here:
http://code.google.com/p/lidgren-network-gen3/
As a side note, it was very valuable for me to read how the Unreal Engine does networking here:
http://udn.epicgames.com/Three/NetworkingOverview.html
And I wrote a blog that demonstrates some specific details about implementing a client/server pattern:
http://syndicatex.com/flatredball/flatredball-and-lidgren-multiplayer-networking/
Are there any high level, simple IPC libraries for C#? It seems most posts point to using WCF. But this looks far more complicated than I need. I just want to send asynchronous messages between two C# apps that may or may not be on the same system.
I am hoping something exists that is as simple to use as the following which comes down to just a Send and an OnRead command. (Link is the IPC library I hope exists).
private void StartServer()
{
using (var link = new Link("InstanceName"))
{
link.OnRead += delegate(Link client, object data)
{
client.Send("Echoing " + data);
};
link.Connect();
Console.WriteLine("Press any key to stop the server.");
Console.ReadKey();
}
}
private void StartClient()
{
using (var link = new Link("serverName", "InstanceName"))
{
link.OnRead += delegate(Link server, object data) { Console.WriteLine(data); };
link.Connect();
link.Send("Hello There!");
Console.WriteLine("Press any key to stop the client.");
Console.ReadKey();
}
}
Self-hosted WCF would come close.
You can take a look at our MsgConnect which offers exactly what you need and for many platforms including .NET. Design of MsgConnect is inspired by Windows API - PostMessage/SendMessage/GetMessage functions, yet MsgConnect has Socket transport which lets you send messages across network. Samples are available in the installation package.
I know that I am not the first to ask the question: How do I find out if my application is online or not?
I found this post: StackOverflow.
I want to do it with C# and .NET 3.5.
The recommendation is to ping the resource regularly. I am not very happy with that advice. I would rather detect a network change and THEN ping my service to check if it is online.
.NET provides two events for this purpose:
NetworkChange.NetworkAvailabilityChanged
NetworkChange.NetworkAddressChanged
The first event sounds good but it is fired only if the last network card which is online goes offline. I have several virtual network cards which have been installed by VMWare and those are always online.
The second event works but between plugging the network cable and the event, there are often 5 seconds wait time.
The Windows tray icon reacts more or less immediately when I am unplugging the cable.
What is the best way to be as fast as this tray icon?
My workaround would be to poll
NetworkInterface.GetAllNetworkInterfaces()
every 500ms and to throw my own event in case that the status of a network adapter changed.
There must be a better solution :)
I tried the link the Webleeuw suggested, but that code also needs between 4 and 10 seconds to notify me when I plug or unplug my cable.
Now, I wanted to know if it just my computer or installation and I wrote my own Observer class which is based on NetworkInterface.GetAllNetworkInterfaces().
And: It works with lightning speed. My app reacts now as quickly as does the tray.
The code is far from production code, it is just a quick hack. But this is what I will build upon now :)
using System;
using System.Net.NetworkInformation;
using Timer=System.Threading.Timer;
namespace NetworkCheckApp
{
public class NetworkStatusObserver
{
public event EventHandler<EventArgs> NetworkChanged;
private NetworkInterface[] oldInterfaces;
private Timer timer;
public void Start()
{
timer = new Timer(UpdateNetworkStatus, null, new TimeSpan(0, 0, 0, 0, 500), new TimeSpan(0, 0, 0, 0, 500));
oldInterfaces = NetworkInterface.GetAllNetworkInterfaces();
}
private void UpdateNetworkStatus(object o)
{
var newInterfaces = NetworkInterface.GetAllNetworkInterfaces();
bool hasChanges = false;
if (newInterfaces.Length != oldInterfaces.Length)
{
hasChanges = true;
}
if (!hasChanges)
{
for (int i = 0; i < oldInterfaces.Length; i++)
{
if (oldInterfaces[i].Name != newInterfaces[i].Name || oldInterfaces[i].OperationalStatus != newInterfaces[i].OperationalStatus)
{
hasChanges = true;
break;
}
}
}
oldInterfaces = newInterfaces;
if (hasChanges)
{
RaiseNetworkChanged();
}
}
private void RaiseNetworkChanged()
{
if (NetworkChanged != null)
{
NetworkChanged.Invoke(this, null);
}
}
}
}
Try this using NetworkChange class
using System.Net.NetworkInformation
private void Form5_Load(object sender, EventArgs e)
{
NetworkChange.NetworkAvailabilityChanged += new NetworkAvailabilityChangedEventHandler(NetworkChange_NetworkAvailabilityChanged);
}
private void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
{
if (e.IsAvailable)
{
MessageBox.Show("Available");
}
else
{
MessageBox.Show("Not available");
}
}
People here already told it but there is a diference between network availability and internet availability.
You can have network availability between your network interface and local router but havent internet availability between your local router and your Internet Service Provider (ISP).
There is another problem that testing by ping will tell you about internet availability but not about what network interface is providing it, i think the only way is force ping throught one interface but it isnot possible on windows.
Pinging your resource regularly is the only option that will give you a notification if the service goes offline, as well as if the client goes offline. Potentially you want to handle both situations.
The windows tray icon is very likely connected to the network card drivers, i.e. below the operating system level which is why it can react so fast.
Since the network card is only one of many links between your client and the service that it accesses on the Internet, the only reliable way to detect whether or not the Internet is available is to poll some service out on the Internet, much the same way that ping does. In TCP/IP networking, this is known as a keepalive, and many protocols will have this built into them as an option.
About the pinging: depending on how you wish to interpret the results, pinging doesn't seem watertight to me. What if the target times out once in a while, while the connection remains alive? I have yet to see the server that never fails to respond to a ping.
Checking every X millis if the network interface is still online (NetworkInterface.OperationalStatus property) seems more reliable if you'd ask me.
EDIT: This article deals with network address events on a lower level than the System.Net.NetworkInformation.NetworkChange class, or so it seems. On my pc it works very fast, so hopefully you'll be able to use that solution.
You can use ping, but I would also build a simple call to return a "yes" if it is online. That way you do know if the server is up and that it is running your code. Also I would only call or ping when a network resource is needed and not continually.
Doing a ping is definitely not the cleanest option, especially if it is a web server. Some hosts will disable response to ICMP traffic, so you may ping but not get a response. How about just handling the exception gracefully when it occurs?