I'm new to c# and trying to set up a server client connection for some test purpose.
Currently I have this snippet letting my client app crashing when it trys to connect while the server isn't running. It seems to me the crash is happening in the client.Connect line, letting me no chance to prevent this, as it didn't return form the method when the crash happens.
Also looking on MSDN didn't give me some usefull info.
so would I have to make some preperation?
because just checking a return value isn't possible as the crash happens inside the method.
Or is there a way I had to check before for I run the connect mehtod for connectability?
Int32 port = 4999;
Byte[] teststring;
GameConfiguration objGameConfClient = new GameConfiguration();
TcpClient client = new TcpClient();
client.Connect("XXX.XXX.XXX.XXX", port);
if (client == null)
{
return;
}
http://msdn.microsoft.com/de-de/library/system.net.sockets.tcpclient%28v=vs.110%29.aspx
The MSDN example apears to me also not handling this crash, is it?
try
{
client.Connect("XXX.XXX.XXX.XXX", port);
}
catch(Exception e)
{
//XXX
}
Related
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
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.
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.
I have mobile RF terminal with Windows CE 6.0 CF 3.5 and I need send data as quickly as possible to my server.
Problem is that wifi connection is not stable enough in place of use.
I reduced the loss of data with repeated sending when connection is aborted by exception. But time for exception is ~21sec and it's too long for me. Repeated connections are successful (mostly), but I need shorten time for exception, or find different method for connection.
For data receive I have TCP server in terminal. And here I have one thread with timer and after my timeout I close client (TcpClient) and catch exception from this :-). But I mean that this method is not ideal.
Any ideas??
Thanks!
Below is my code for TCP client connection
internal string TCPsend(string strMessage)
{
string exception = string.Empty;
TcpClient client = null;
try
{
client = new TcpClient(IPServer, PortServer);
client.SendTimeout = 500; //no effect
Stream stream = client.GetStream();
StreamWriter strWriter = new StreamWriter(stream);
strWriter.Write(strMessage);
strWriter.Close();
}
catch (Exception ex)
{
exception = ex.ToString();
utility.SaveExceptionLog("SendTCP A: " + ex.ToString());
}
finally
{
if (client != null)
{
client.Close();
}
}
return exception;
}
If you want to take connectivity check into your hands, probably you should open new thread, where you will check in a loop for an established connection.
Here is the answer where the trivial check disscussed: What is the best way to check for Internet connectivity using .NET?
This will impact on overall sending performance, but should reduce the waiting time.
I'm trying to find out whether a Socket is currently connected - according to the MSDN docs for Socket.Connected - I should do the following:
// This is how you can determine whether a socket is still connected.
bool blockingState = client.Blocking;
try
{
byte [] tmp = new byte[1];
client.Blocking = false;
client.Send(tmp, 0, 0);
Console.WriteLine("Connected!");
}
catch (SocketException e)
{
// 10035 == WSAEWOULDBLOCK
if (e.NativeErrorCode.Equals(10035))
Console.WriteLine("Still Connected, but the Send would block");
else
{
Console.WriteLine("Disconnected: error code {0}!", e.NativeErrorCode);
}
}
finally
{
client.Blocking = blockingState;
}
Console.WriteLine("Connected: {0}", client.Connected);
I've tested this works by connecting the socket to a remote server running on Windows and killing the remote server and it works fine.
However, if I do the same with a remote Server running on Unix (in this case MAC OS X) then the code does not work - the client.Send(tmp, 0, 0) call completes without throwing an exception and prints "Connected: true".
I'm guessing this has something to do with the fact that the other side of the connection has closed so the send may still work but a receive would fail - can I do a zero-byte Receive or something to see if the socket is closed?
Yes, you can.
Calling Send only really checks if the local socket is open. Calling Receive will check the other end too.
Maybe you can sniff with Wireshark the traffic and see if there are any difference if the dying server side is a windows or unix system.
Maybe the dying windows system is able to send a tcp close while the unix system can't. That would explain the difference (but maybe not help your actual problem).
btw, if you would use a udp connection you could never determine if the other site is living, due to the fact this would be a send & forget communication.