问题
I want to admit I'm not the strongest in c# and I have developed this program by looking at several tutorials, I would appreciate a lot if you can be detailed in your answer.
I would like my TCP Server to always listening for incoming connections and when a new TCP Client connects, I want it to discard the old connection and use the new one.
I have tried to implement this answer; https://stackoverflow.com/a/19387431/3540143
but my issue is the fact that when I'm simulating a TCP client, but somehow the answer above will only receive one message (my current code receive all messages sent), also I've tried to convert the data over so I receive it in same way as the code below but without any success.
Also the code above I believe is just accepting new clients, without discarding the previous connected clients.
My current code, which can handle a connection and search for new connection once a disconnection have been made, I want to make it so I'm always looking for new connection and if a new client want to connect I'm discarding the current to let the new through
public class TCPListener
{
public static void Listener()
{
TcpListener server = null;
try
{
// Set the TcpListener on carPort.
Int32 port = 5002;
// TcpListener server = new TcpListener(port);
server = new TcpListener(IPAddress.Any, port);
// Start listening for client requests.
server.Start();
// Buffer for reading data
Byte[] bytes = new Byte[256];
String data = null;
// Enter the listening loop.
while (true)
{
Console.Write("Waiting for a connection... ");
// Perform a blocking call to accept requests.
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
// Get a stream object for reading
NetworkStream stream = client.GetStream();
int i;
// Loop to receive all the data sent by the client.
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
// Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);
}
// Shutdown and end connection
Console.WriteLine("Client close");
client.Close();
}
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
finally
{
// Stop listening for new clients.
Console.WriteLine("Stop listening for new clients.");
server.Stop();
}
}
}
EDIT: If anyone needs the solution for my issue then this is how the code looks like when I applied what Cecilio Pardo suggested, which works really great!
public class TCPListener
{
Form form = new Form();
public static void Listener()
{
TcpListener server = null;
try
{
// Set the TcpListener on carPort.
Int32 port = 5002;
// TcpListener server = new TcpListener(port);
server = new TcpListener(IPAddress.Any, port);
// Start listening for client requests.
server.Start();
// Buffer for reading data
Byte[] bytes = new Byte[256];
String data = null;
// Enter the listening loop.
while (true)
{
Console.Write("Waiting for a connection... ");
// Perform a blocking call to accept requests.
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
data = null;
bool dataAvailable = false;
// Get a stream object for reading
NetworkStream stream = client.GetStream();
int i;
while (true)
{
if (!dataAvailable)
{
dataAvailable = stream.DataAvailable;
//Console.WriteLine("Data Available: "+dataAvailable);
if (server.Pending())
{
Console.WriteLine("found new client");
break;
}
}
if (dataAvailable)
{
// Loop to receive all the data sent by the client.
i = stream.Read(bytes, 0, bytes.Length);
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);
dataAvailable = false;
}
if (server.Pending())
{
Console.WriteLine("found new client");
break;
}
}
Console.WriteLine("Client close");
// Shutdown and end connection
client.Close();
}
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
finally
{
// Stop listening for new clients.
Console.WriteLine("Stop listening for new clients.");
server.Stop();
}
}
}
回答1:
While you are in your inner while
loop, you can't check for new connections. So you would have to add something like this inside the loop:
if ( server.Pending() ) break;
That will exit your loop as soon as another connection is waiting.
Another problem is that stream.Read
will block until some data is available, so new connections will not get handled if the active one is idle. So you have to change it, and not call Read
unless there is some data, using stream.DataAvailable
回答2:
This is what I'm using and it's working pretty good so far, I've just started working on this type of application. If I make any significant changes or find bugs with this code I'll update:
class ClientListener
{
const int PORT_NO = 4500;
const string SERVER_IP = "127.0.0.1";
private TcpListener listener;
public async Task Listen()
{
IPAddress localAddress = IPAddress.Parse(SERVER_IP);
listener = new TcpListener(localAddress, PORT_NO);
Console.WriteLine("Listening on: " + SERVER_IP + ":" + PORT_NO);
listener.Start();
while (true)
{
// Accept incoming connection that matches IP / Port number
// We need some form of security here later
TcpClient client = await listener.AcceptTcpClientAsync();
if (client.Connected)
{
// Get the stream of data send by the server and create a buffer of data we can read
NetworkStream stream = client.GetStream();
byte[] buffer = new byte[client.ReceiveBufferSize];
int bytesRead = stream.Read(buffer, 0, client.ReceiveBufferSize);
// Convert the data recieved into a string
string data = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine("Recieved Data: " + data);
}
}
}
public void StopListening()
{
listener.Stop();
}
}
来源:https://stackoverflow.com/questions/35322605/how-to-set-tcplistener-to-always-listen-and-when-new-connection-discard-current