I developed a game lift back-end server using a websocket sharp. The local test function provided by GameLift worked fine, but Web socket communication is not possible with the game session of Fleet created by the GameLift server.
To be exact, the connection is initially shown on the client as successful, but it is said that the connection was immediately disconnected. And even if the connection is marked as successful, no messages reach the server.
I wonder if there is anything I need to communicate with the AWS game lift server using a web socket. Please help me.
Fleet type : spot instance
Not use TLS
EC2 Port was set as |2022|TCP|0.0.0.0/0
Client Code for Connection
public static void AddService(string hostName, int port, string serviceName, WebSocketClientSession socketSession, bool overTls = false)
{
Dictionary<string, WebSocket> serviceMap = _instance.mServiceMap;
string uri = overTls
? $"wss://{hostName}:{port}/{serviceName}"
: $"ws://{hostName}:{port}/{serviceName}";
Debug.Log(uri);
WebSocket webSocket = new WebSocket(uri);
if (overTls)
{
webSocket.SslConfiguration.EnabledSslProtocols = SslProtocols.Tls;
}
webSocket.OnOpen += socketSession.OnOpen;
webSocket.OnClose += socketSession.OnClose;
webSocket.OnMessage += socketSession.OnMessage;
webSocket.OnError += socketSession.OnError;
serviceMap[serviceName] = webSocket;
}
public static async void ConnectAsync(string serviceName, Action<bool> onCompleted)
{
Dictionary<string, WebSocket> serviceMap = _instance.mServiceMap;
WebSocket webSocket = serviceMap[serviceName];
await Task.Run(webSocket.Connect);
if (webSocket.IsAlive)
{
// webSocket.EmitOnPing = true;
onCompleted?.Invoke(true);
return;
}
onCompleted?.Invoke(false);
}
Server Code for listening
public static void StartServer()
{
_instance.mServer.Start();
_instance.mHasStarted = true;
}
public static void StopServer()
{
_instance.mServer.Stop();
_instance.mHasStarted = false;
}
public static void AddService<T>(string serviceName) where T : WebSocketServerSession, new()
{
WebSocketServer server = _instance.mServer;
server.AddWebSocketService<T>($"/{serviceName}");
}
public static void RemoveService(string serviceName)
{
WebSocketServer server = _instance.mServer;
server.RemoveWebSocketService($"/{serviceName}");
}
At first, communication was attempted using TCP and UDP, but the same phenomenon occurred as a web socket.
Various searches and attempts were made for a week, but there was no harvest. There were so few questions about the game lift that there were no similar cases.
Even if it is not a game lift service, I would like to know if there are additional elements necessary for AWS connection.
It could be lots of different things. TLS mismatches, WebSocket parameter negotiation mismatches, authentication etc.
I'd suggest digging deeper into what is happening on the wire. Hopefully, it'll make things clearer, and lead you to a solution.
A Man-In-The-Middle proxy, like Burp, would be able to see into the HTTP connection, and the follow-up WebSocket negotiation. All you need to do is point your app at it via the proxy settings, and install the Burp CA certificate into your app platform (so it can intercept the TLS).
Otherwise, if that's not an option, you can always use Wireshark (though you won't be able to see inside the TLS).
I have an application that was written for remote trucks to use on cell service. Before I do anything, I am checking the internet with this class:
using System.Net;
namespace SSS.ServicesConfig.MiscClasses
{
public class VerifyInternetAccess
{
public static bool HasInternet()
{
try
{
using (var client = new WebClient())
using (var stream = client.OpenRead("http://www.google.com"))
{
return true;
}
}
catch
{
return false;
}
}
}
}
In some cases, the light on the external cellular device has a green light as if it has internet. My test class comes back false so it thinks it does not have internet.
The driver can then open up internet explorer, close internet explorer, promptly run my application and it passes the test above.
The users are saying that IE is 'waking up' the internet so that it can transfer.
Doesn't my class do essentially the same thing? If not, how can I 'wake up' the internet connection as IE does?
You didn't state if you're restricted to a certain mobile OS but this works on a normal box.
I try to leverage two features of the System.Net.NetworkInformation namespace.
I start with registering for the NetworkChangedEvent. By calling GetIsNetworkAvailable you get an idea if there is at least one other NIC present that is not the loopback interface.
If there is no connection I try to wake-up the network layer by getting pinging a host.
I use the Dns.GetHostEntry to obtain all IP Adresses known for a host. Next I try to Ping the address one by one.
Be aware that not all hosts allow ICMP traffic which would lead to timeouts in all circumstances. If however in the meantime the network becomes available the NetworkChanged event should have been fired and set the HasConnection to true
public class VerifyInternetAccess
{
private static bool HasConnection = false;
static VerifyInternetAccess()
{
NetworkChange.NetworkAvailabilityChanged += (o, ca) =>
{
HasConnection = ca.IsAvailable;
};
HasConnection = NetworkInterface.GetIsNetworkAvailable();
}
public static bool HasInternet()
{
bool hasEnded = false;
if (!HasConnection)
{
// let's try to wake up...
using (var ping = new Ping())
{
var iphost = Dns.GetHostEntry("www.google.com");
foreach (var addr in iphost.AddressList)
{
var reply = ping.Send(addr);
if (reply.Status == IPStatus.Success)
{
HasConnection = true;
break;
}
}
}
}
return HasConnection;
}
}
I am developing a PDA Application using c#,i need's to check internet connection before application starts execute,i have used the following code,which is working fine PDA system but not in Desktop
public static bool CheckForInternetConnection()
{
try
{
string hosname = System.Net.Dns.GetHostName();
IPHostEntry ent = Dns.GetHostEntry(hosname);
string ip = ent.AddressList[0].ToString();
bool ret = (ip != "127.0.0.1" && ip != "::1");
//MessageBox.Show(ret.ToString());
if (ret)
{
// MessageBox.Show("internet connected");
}
else
{
MessageBox.Show("internet not connected");
}
return ret;
}
catch
{
MessageBox.Show("internet not connected catch");
return false;
}
}
when I try to execute the same exe in desktop which is throwing me "internet not connected",where i am going wrong?
You have to ping google for example if a reply that means you have internet. What you've written is just checking if the device has ip address.
I have written Windows service, which perform Modbus WriteMultipleRegisters function call over TCP using NModbus library to 3-party devices every 10 minutes (ticks of System.Threading.Timer).
Occasionally this connection hang up open usually during network problems. As the device accepts only one Modbus connection at time and others are refused, connection during all next ticks fail with SocketException - ConnectionRefused.
But the device automatically closes connections which don't respond after short time. Something must keep connection open at my side even for two days. What's more when my Service is restarted, everything is fine again. So there is definitely some forgotten open connection. But I didn't manage to reproduce this bug in dev, so I don't where/when.. connection hang up. I only know that next connection is refused.
I do the modbus function call with this part of code:
using (TcpClient client = new TcpClient(device.ip, 502))
{
using (Modbus.Device.ModbusIpMaster master = Modbus.Device.ModbusIpMaster.CreateIp(client))
{
master.WriteMultipleRegisters(500, new ushort[] { 0xFF80 });
}
}
device.ip is string containing IP address of device - it's correct, confirmed from SocketException details.
As I'm using using statement dispose is called on both objects.
I have looked trough NModbus source code and everything is disposed correctly.
Any idea how its possible that with this code connection is not closed?
I agree with nemec. If you review the documentation for TcpClient.Dispose if does not specifically mention closing the connection. It frees managed and unmanaged resources by default, but it may not correctly tear down the connection.
Try changing your code to:
using (TcpClient client = new TcpClient(device.ip, 502))
{
try
{
using (Modbus.Device.ModbusIpMaster master = Modbus.Device.ModbusIpMaster.CreateIp(client))
{
master.WriteMultipleRegisters(500, new ushort[] { 0xFF80 });
}
}
catch(Exception e)
{
// Log exception
}
finally
{
client.Close();
}
}
That way you are doing a clean close before dispose and it should clean up even if the Modbus protocol throws some kind of exception.
did you play with TcpClient.LingerState Property
defualt setting could cause problems with resetting winsock
check it out
http://msdn.microsoft.com/pl-pl/library/system.net.sockets.tcpclient.lingerstate%28v=vs.110%29.aspx
This is not an answer, but a comment with code. We have this same issue on some of our installed computers, but not all of them. The issue itself is also very intermittent, sometimes going months without happening. I am hoping someone can find an answer. Here is our brute force destroy / reconnect code that does not work:
try
{
try
{
try
{
// Close the stream
var stream = _tcpClient.GetStream();
if (stream != null)
stream.Close();
}
catch { }
try
{
// Close the socket
if (_tcpClient.Client != null)
_tcpClient.Client.Close();
}
catch { }
// Close the client
_tcpClient.Close();
_tcpClient = null;
}
catch { }
if (_device != null)
{
_device.Dispose();
_device = null;
}
}
catch { }
System.Threading.Thread.Sleep(1000);
In C# to use a TcpClient or generally to connect to a socket how can I first check if a certain port is free on my machine?
more info:
This is the code I use:
TcpClient c;
//I want to check here if port is free.
c = new TcpClient(ip, port);
Since you're using a TcpClient, that means you're checking open TCP ports. There are lots of good objects available in the System.Net.NetworkInformation namespace.
Use the IPGlobalProperties object to get to an array of TcpConnectionInformation objects, which you can then interrogate about endpoint IP and port.
int port = 456; //<--- This is your value
bool isAvailable = true;
// Evaluate current system tcp connections. This is the same information provided
// by the netstat command line application, just in .Net strongly-typed object
// form. We will look through the list, and if our port we would like to use
// in our TcpClient is occupied, we will set isAvailable to false.
IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();
foreach (TcpConnectionInformation tcpi in tcpConnInfoArray)
{
if (tcpi.LocalEndPoint.Port==port)
{
isAvailable = false;
break;
}
}
// At this point, if isAvailable is true, we can proceed accordingly.
You're on the wrong end of the Intertube. It is the server that can have only one particular port open. Some code:
IPAddress ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
try {
TcpListener tcpListener = new TcpListener(ipAddress, 666);
tcpListener.Start();
}
catch (SocketException ex) {
MessageBox.Show(ex.Message, "kaboom");
}
Fails with:
Only one usage of each socket address (protocol/network address/port) is normally permitted.
When you set up a TCP connection, the 4-tuple (source-ip, source-port, dest-ip, dest-port) has to be unique - this is to ensure packets are delivered to the right place.
There is a further restriction on the server side that only one server program can bind to an incoming port number (assuming one IP address; multi-NIC servers have other powers but we don't need to discuss them here).
So, at the server end, you:
create a socket.
bind that socket to a port.
listen on that port.
accept connections on that port.
and there can be multiple connections coming in (one per client).
On the client end, it's usually a little simpler:
create a socket.
open the connection.
When a client opens the connection, it specifies the ip address and port of the server. It can specify its source port but usually uses zero which results in the system assigning it a free port automatically.
There is no requirement that the destination IP/port be unique since that would result in only one person at a time being able to use Google, and that would pretty well destroy their business model.
This means you can even do such wondrous things as multi-session FTP since you set up multiple sessions where the only difference is your source port, allowing you to download chunks in parallel. Torrents are a little different in that the destination of each session is usually different.
And, after all that waffling (sorry), the answer to your specific question is that you don't need to specify a free port. If you're connecting to a server with a call that doesn't specify your source port, it'll almost certainly be using zero under the covers and the system will give you an unused one.
Thanks for this tip. I needed the same functionality but on the Server side to check if a Port was in use so I modified it to this code.
private bool CheckAvailableServerPort(int port) {
LOG.InfoFormat("Checking Port {0}", port);
bool isAvailable = true;
// Evaluate current system tcp connections. This is the same information provided
// by the netstat command line application, just in .Net strongly-typed object
// form. We will look through the list, and if our port we would like to use
// in our TcpClient is occupied, we will set isAvailable to false.
IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpListeners();
foreach (IPEndPoint endpoint in tcpConnInfoArray) {
if (endpoint.Port == port) {
isAvailable = false;
break;
}
}
LOG.InfoFormat("Port {0} available = {1}", port, isAvailable);
return isAvailable;
}
TcpClient c;
//I want to check here if port is free.
c = new TcpClient(ip, port);
...how can I first check if a certain port is free on my machine?
I mean that it is not in use by any other application.
If an application is using a port others can't use it until it becomes free. – Ali
You have misunderstood what's happening here.
TcpClient(...) parameters are of server ip and server port you wish to connect to.
The TcpClient selects a transient local port from the available pool to communicate to the server. There's no need to check for the availability of the local port as it is automatically handled by the winsock layer.
In case you can't connect to the server using the above code fragment, the problem could be one or more of several. (i.e. server ip and/or port is wrong, remote server not available, etc..)
thanks for the #jro answer. I had to tweak it for my usage. I needed to check if a port was being listened on, and not neccessarily active. For this I replaced
TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();
with
IPEndPoint[] objEndPoints = ipGlobalProperties.GetActiveTcpListeners();.
I iterated the array of endpoints checking that my port value was not found.
To answer the exact question of finding a free port (which is what I needed in my unit tests) in dotnet core 3.1 I came up this
public static int GetAvailablePort(IPAddress ip) {
TcpListener l = new TcpListener(ip, 0);
l.Start();
int port = ((IPEndPoint)l.LocalEndpoint).Port;
l.Stop();
Log.Info($"Available port found: {port}");
return port;
}
note: based the comment by #user207421 about port zero I searched and found this and slightly modified it.
string hostname = "localhost";
int portno = 9081;
IPAddress ipa = (IPAddress) Dns.GetHostAddresses(hostname)[0];
try
{
System.Net.Sockets.Socket sock = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
sock.Connect(ipa, portno);
if (sock.Connected == true) // Port is in use and connection is successful
MessageBox.Show("Port is Closed");
sock.Close();
}
catch (System.Net.Sockets.SocketException ex)
{
if (ex.ErrorCode == 10061) // Port is unused and could not establish connection
MessageBox.Show("Port is Open!");
else
MessageBox.Show(ex.Message);
}
From the available ports I would exclude:
active TCP connections
active TCP listeners
active UDP listeners
With the following import:
using System.Net.NetworkInformation;
You can use the following function to check if a port is available or not:
private bool isPortAvailable(int myPort)
{
var availablePorts = new List<int>();
var properties = IPGlobalProperties.GetIPGlobalProperties();
// Active connections
var connections = properties.GetActiveTcpConnections();
availablePorts.AddRange(connections);
// Active tcp listners
var endPointsTcp = properties.GetActiveTcpListeners();
availablePorts.AddRange(endPointsTcp);
// Active udp listeners
var endPointsUdp = properties.GetActiveUdpListeners();
availablePorts.AddRange(endPointsUdp);
foreach (int p in availablePorts){
if (p == myPort) return false;
}
return true;
}
I give you a similar function for those who use VB.NET:
Imports System.Net.NetworkInformation
Private Function isPortAvailable(ByVal myPort As Integer) As Boolean
Dim props As IPGlobalProperties = IPGlobalProperties.GetIPGlobalProperties()
' ignore active connections
Dim tcpConnInfoArray() As TcpConnectionInformation = props.GetActiveTcpConnections()
For Each tcpi As Net.NetworkInformation.TcpConnectionInformation In tcpConnInfoArray
If tcpi.LocalEndPoint.Port = myPort Then
Return False
End If
Next tcpi
' ignore active TCP listeners
Dim activeTcpListeners() As Net.IPEndPoint = props.GetActiveTcpListeners
For Each tcpListener As Net.IPEndPoint In activeTcpListeners
If tcpListener.Port = myPort Then
Return False
End If
Next tcpListener
' ignore active UPD listeners
Dim activeUdpListeners() As Net.IPEndPoint = props.GetActiveUdpListeners
For Each udpListener As Net.IPEndPoint In activeUdpListeners
If udpListener.Port = myPort Then
Return False
End If
Next udpListener
Return True
End Function
netstat! That's a network command line utility which ships with windows. It shows all current established connections and all ports currently being listened to. You can use this program to check, but if you want to do this from code look into the System.Net.NetworkInformation namespace? It's a new namespace as of 2.0. There's some goodies there. But eventually if you wanna get the same kind of information that's available through the command netstat you'll need to result to P/Invoke...
Update: System.Net.NetworkInformation
That namespace contains a bunch of classes you can use for figuring out things about the network.
I wasn't able to find that old pice of code but I think you can write something similar yourself. A good start is to check out the IP Helper API. Google MSDN for the GetTcpTable WINAPI function and use P/Invoke to enumerate until you have the information you need.
If I'm not very much mistaken, you can use System.Network.whatever to check.
However, this will always incur a race condition.
The canonical way of checking is try to listen on that port. If you get an error that port wasn't open.
I think this is part of why bind() and listen() are two separate system calls.
ipGlobalProperties.GetActiveTcpConnections() doesn't return connections in Listen State.
Port can be used for listening, but with no one connected to it the method described above will not work.
You say
I mean that it is not in use by any
other application. If an application
is using a port others can't use it
until it becomes free.
But you can always connect to a port while others are using it if something's listening there. Otherwise, http port 80 would be a mess.
If your
c = new TcpClient(ip, port);
fails, then nothing's listening there. Otherwise, it will connect, even if some other machine/application has a socket open to that ip and port.
Be aware the time window between you make check and the moment you try to make connection some process may take the port - classical TOCTOU. Why don't you just try to connect? If it fails then you know the port is not available.
You don't have to know what ports are open on your local machine to connect to some remote TCP service (unless you want to use a specific local port, but usually that is not the case).
Every TCP/IP connection is identified by 4 values: remote IP, remote port number, local IP, local port number, but you only need to know remote IP and remote port number to establish a connection.
When you create tcp connection using
TcpClient c;
c = new TcpClient(remote_ip, remote_port);
Your system will automatically assign one of many free local port numbers to your connection. You don't need to do anything.
You might also want to check if a remote port is open. but there is no better way to do that than just trying to connect to it.
public static bool TestOpenPort(int Port)
{
var tcpListener = default(TcpListener);
try
{
var ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
tcpListener = new TcpListener(ipAddress, Port);
tcpListener.Start();
return true;
}
catch (SocketException)
{
}
finally
{
if (tcpListener != null)
tcpListener.Stop();
}
return false;
}
Check for error code 10048
try
{
TcpListener tcpListener = new TcpListener(ipAddress, portNumber);
tcpListener.Start();
}
catch(SocketException ex)
{
if(ex.ErrorCode == 10048)
{
MessageBox.Show("Port " + portNumber + " is currently in use.");
}
return;
}
I simply needed to verify if a port was available for listening. Condensing #Melloware example above to a one-liner as static method strictly for the purpose of indicating if the port is available works for me (.NET6).
using System.Net.NetworkInformation;
namespace MyNamespace
{
public static class NetworkValidation
{
public static bool IsListeningPortAvailable(int port) =>
!IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners().Any(x => x.Port == port);
}
}
Implementation as simple console app:
using MyNamespace;
int port = 5000;
var available = NetworkValidation.IsListeningPortAvailable(port);
Console.WriteLine($"Port:{port} available == {available}");
test_connection("ip", port);
public void test_connection(String hostname, int portno) {
IPAddress ipa = (IPAddress)Dns.GetHostAddresses(hostname)[0];
try {
System.Net.Sockets.Socket sock = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
sock.Connect(ipa, portno);
if (sock.Connected == true) {
MessageBox.Show("Port is in use");
}
sock.Close();
}
catch (System.Net.Sockets.SocketException ex) {
if (ex.ErrorCode == 10060) {
MessageBox.Show("No connection.");
}
}
}
try this, in my case the port number for the created object wasn't available so I came up with this
IPEndPoint endPoint;
int port = 1;
while (true)
{
try
{
endPoint = new IPEndPoint(IPAddress.Any, port);
break;
}
catch (SocketException)
{
port++;
}
}