Connecting to Multiple TCP Servers From Client C# - c#

Making the properties TcpClient and IPEndPoint appear to have fixed my issue! If anyone could explain why this is the case I would appreciate it. I do usually declare my class objects static but I don't entirely understand why it works this way.
I'd like to start by saying the usual, I've googled and googled but haven't found anything answering my question so please point me if there is already an answer to this question.
I have written successfully a TCP server and client in C#, however I would like my client to be able to connect to multiple servers. To be clear this is not a server with multiple clients connected to it, I had no issues configuring that.
Here is a little picture explaining what I mean:
Pretty, I know. But in all seriousness I can't get this to work. I met with the error: A connect request was made on an already connected socket
I have a class called client, with a TcpClient and an IPEndPoint:
public Client(IPEndPoint ip)
{
client = new TcpClient();
this.ip = ip;
}
This class has methods connect, send, receive etc. The issue comes when I do something like this:
Client host = new Client(hosts.ElementAt(0));
IPEndPoint ipe = hosts.ElementAt(0);
EDIT: This contructor occurs in a different method than the method the "host" constructor does
Client client = new Client(ipe);
client.ConnectAsync();
host.ConnectAsync();
Now originally I tried to use the new async methods and the await feature, it worked fine when it was only one host but on the second it began to error. I thought perhaps it was becuase I was using the same method and it was attempting to connect before the first await had completed, it would try to connect again on the first IP, no idea if that makes any sense but basically I thought, well I will just create a new thread for each connect attempt like so:
public void ConnectAsync()
{
ThreadPool.QueueUserWorkItem(delegate { ConnectAsyncMethod(); });
}
private void ConnectAsyncMethod()
{
Thread connectThread = new Thread(() =>
{
try
{
client.Connect(ip.Address, ip.Port);
this.clientStream = client.GetStream();
ReceiveAsync();
}
catch (SocketException se)
{
}
catch (NotSupportedException ns)
{
}
catch (Exception e)
{
}
});
connectThread.Start();
}
Even though the connect is run on a new thread, I still get the same error, but why?
Could anyone point me towards a solution and hopefully explain where the flaws in my thinking lie? I am now thinking perhaps it is something in the way sockets are handled but I'm really not sure.
I appreciate any help, thank you everyone.

You will need multiple Client objects to establish multiple connections to different addresses (or the same in fact). For example, you could have a Client ClientA connect to Server A and have a Client ClientB connect to Server B. You cannot have the same Client object connect two times to diffrent or the same address.

This is strange.Maybe you would check whether the 2nd client port conflicts with the first client which will result in the error.
Here I found the official manual of this(10056):
http://msdn.microsoft.com/zh-cn/library/windows/desktop/aa924071(v=vs.85).aspx

Related

C# program hangs on Socket.Accept()

I created a server "middleman" application that uses sockets and multi-threading techniques (ServerListener is run in a new thread). I found early on that when I would use the Socket.Accept() method, the program would hang indefinitely, waiting for that connection to happen. The problem is, as far as I can tell there is no reason for it not to.
I spent a good portion of the day trying lots of different things to make it work, and somewhere something changed because it suddenly started working for a while. However, as soon as I accidentally chose a different data source than "localhost" for the client application, the problem popped back up again. I have tried running the program without the firewall OR antivirus running, but no luck. The client program IS set to connect on port 10000. Here is my code:
public void ServerListener() {
UpdateStatus("Establishing link to server");
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Any, defaultPort));
server.Listen(queue);
UpdateStatus("Accepting Connections");
while (true) {
Socket client = default(Socket);
try {
client = server.Accept();
if (client != null) {
++count;
UpdateCount(count.ToString());
new Thread(
() => {
Client myclient = new Client(client, defaultPort, this);
}
).Start();
}
}
catch( Exception ex ){
MessageBox.Show(ex.ToString());
client.Close();
}
}
}
It will run just fine right up until server.Accept(), then hangs. As stated, it did work for a while earlier, but is now hanging again. I've tried to see if any other programs are using port 10000, and they aren't. I went over and over this with a friend, and we couldn't find the problem. Please help!
EDIT To be clear, I do know that Accept is a blocking call. The client program makes the connection on port 10000, but this program keeps on waiting on the Accept as if nothing happened. It did work for a time, so I know the connection is working like it is supposed to from the client program's end. However, I can't fathom why this program is now acting like that connection never happens, and continues to wait on the Accept.
Accept blocks on purpose. If you want to do other things while waiting for another client to connect you can:
Run the ServerListener in another Thread or better - a long running task:
using System.Threading.Tasks;
...
Task.Factory.StartNew(ServerListener, TaskCreationOptions.LongRunning);
Use the AcceptAsync method which uses the SocketAsyncEventArgs class. For that to work, you create a new SocketAsyncEventArgs instance, set its values and pass it to socket.AcceptAsync.

TCPClient & Sockets failing to connect to the Server

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.

C#: System.Net.Sockets.TcpListener is sometimes not closing Socket properly

in one of my projects I have implemented a small HTTP server to stream the video data of a connected webcam. For this task I'm utilizing the System.Net.Sockets.TcpListener from .NET Framework 4.5, which listens to a pre-configured endpoint and uses the AcceptSocketAsync() mtehod to wait for incomming requests. You can see the relevant code parts below:
this.server = new TcpListener(endpoint);
this.server.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(true, 0));
this.server.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
this.server.Start();
...
this.listenTask = Task.Factory.StartNew(this.Listen);
...
private async void Listen()
{
try
{
while (this.server.Server.IsBound)
{
Socket socket = await this.server.AcceptSocketAsync();
if (socket == null)
{
break;
}
Task.Factory.StartNew(() => this.ClientThread(socket));
}
}
catch (ObjectDisposedException)
{
Log.Debug("Media HttpServer closed.");
}
}
This works fine, when I start the application and the HTTP server is started for the first time. However, when I stop the HTTP server (done via CheckBox in the settings of the application) the unverlying listening socket is sometimes not closed. When I check for the state of the sockets via console (netstat -ano) I can see that the socket is still in state LISTENING. The resulting problem is, when I restart the HTTP server again I get an System.Net.Sockets.SocketException with the message "Only one usage of each socket address is normally permitted", which is not surprising.
The relevant code part for stopping the HTTP server is as follows:
...
if (this.server != null)
{
if (this.server.Server != null)
{
if (this.server.Server.Connected)
{
this.server.Server.Shutdown(SocketShutdown.Both);
this.server.Server.Disconnect(true);
}
this.server.Server.Close();
}
this.server.Stop();
}
...
I also keep track of my open connections and close them after finishing the transmission of data and when stopping the server. None of the connection sockets stays opened, so I believe only the listening socket should be relevant for this problem.
I already tried various combinations/orders of the Shutdown(), Disconnect(), Close() and Stop() methods when stopping the server, as well as setting/unsetting several options when starting the server like Linger and ReuseAddress, which sometimes seemed to fix the problem at first, but then a few days later the problem occurred again.
I also tried to "force" the listening socket to close when stopping the server using GetTcpTable(...) and SetTcpEntry(...) from iphlpapi.dll, as described in this question: How to close a TCP connection by port?
Unfortunately, this approach did not work for me (it change anything about the state of the listening socket at all).
As I'm a little bit clueless of what else I could do, I'm asking here if somebody has an idea of what might cause the discribed problem or how to solve it. Any help would be greatly appreciated.
Kind regards,
Chris
You should almost always leave TcpListener.Server alone. It's there so you can set socket options on it, not use it for control purposes.
So your Listen should be:
private async void Listen()
{
try
{
while (true)
{
Socket socket = await this.server.AcceptSocketAsync();
if (socket == null)
{
break;
}
Task.Run(() => this.ClientThread(socket));
}
}
catch (ObjectDisposedException)
{
Log.Debug("Media HttpServer closed.");
}
}
(assuming you do actually want one thread per client, an architecture I do not recommend in general).
When you're ready to stop, just stop:
if (this.server != null)
{
this.server.Stop();
}
If you do not have any special requirement, it is suggested to make use of TcpListener class and its methods only or if you have such requirement, do not use TcpListener and start with the Raw socket.
TcpListener class is self sufficient to provide method like
Start(), AcceptTcpClient() and Stop().
You can create a List<TcpClient> and loop through each client and call client.close() after calling Stop() on the TcpListener instance.
A very good example of client server communication is on MSDN:
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener(v=vs.110).aspx
Regards
On server socket, shutdown & disconnect is not needed for listening sockets. Those calls are needed only for connected sockets. Replace the socket stop with below code:
if (this.server != null)
{
if (this.server.Server != null)
{
this.server.Server.Close();
this.server.Server = NULL;
}
}
I would dispose of your socket connections once you have closed them. The documentation says they should be disposed after closed but personally I like to say when to dispose of anything that use the IDisposable interface.

TcpListener: Reject an incoming connection request before connection

I have a service that's open to everyone on the public internet. It runs TcpListener to manage incoming connections.
The service maintains a list of persistently misbehaving clients by their incoming IP address. Any connections coming from a listed IP are sent a "go away" message as the connection is closed down.
I'd prefer it if the socket isn't opened in the first place, but by the time AcceptTcpClient has returned, the connection is already opened.
Is there a way for my code to step in and examine incoming connection requests (and perhaps reject them) before they are opened?
Many thanks.
WSAAccept allows specifying a callback which can decide whether to accept or reject a connection. See this question for how to call it from C#.
Since you're using .Net I assume you must be running under Windows.
There is no way from the sockets API to do what you seek. However, you could have your program add Windows Firewall rules to accomplish the same thing -- assuming you have Windows Firewall turned on.
For anyone looking for a solid answer to this still:
TcpListener inListener;
bool _canClientConnect = true;
TcpClient _client;
if (_inListener != null && _inListener.Pending() && _canClientConnect) { // Accept actual client
_canClientConnect = false;
_cancelTokenSource = new CancellationTokenSource();
_client = _inListener.AcceptTcpClient();
_stream = _client.GetStream();
if (_recieverTask != null) {
_recieverTask.Start();
}
}
if (_inListener.Pending() && !_canClientConnect) { // Client found connecting, but we are already connected.
_inListener.AcceptTcpClient().Close(); // Accept the client connection and immediately close it.
}

Is it possible to create an event and handle it, if the connection to a MySQL server is lost?

Let's say I have my client application and it makes a connection to the MySQL server. Fantastic. I don't implement this as a thread. I just utilise the MySQLConnection class.
And now let's say Jim who's really careless about the office accidently reboots the MySQL server without asking permission first.
I want to know when the disconnection happens so the client application is aware and the user doesn't get a lot of errors.
I can think of a few ways to check this but I don't know if they'll work and even if they're elegant in design. I was wondering what you folks thought was the most appropriate way.
Implement the connection as a thread and check it every x seconds (if it's even possible)
Create and handle an event when the connection drops (sort of relies on the point above)
Maybe there's a event built into the MySQL Connector library that I'm not even aware of
Some other mystical dark code that I'm not aware of
Any help is very much appreciated.
Edit: This question has been answered in comments. Thanks for reading.
I have an "occasionally connected" application and faced this problem. I needed to know if the user had a network connection and, if they did, if they had a VPN connection that would allow them to connect to the SQL Server database. I used a timer to ping the database server once a minute to check its reachability.
public NetworkStatus GetNetworkStatus()
{
NetworkStatus netStatus = new NetworkStatus();
netStatus.NetworkAvailable = NetworkInterface.GetIsNetworkAvailable();
try
{
if (netStatus.NetworkAvailable)
{
Ping p = new Ping();
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
PingReply reply = p.Send(DB_SERVER_NAME, 1200, buffer);
netStatus.PublisherPingSuccess = reply.Status == IPStatus.Success;
}
}
catch (Exception ex)
{
netStatus.PublisherPingSuccess = false;
netStatus.Error = ex;
}
return netStatus;
}

Categories