In response to your comments to my previous post . . .
You still haven't said which port you want to reuse but here we go.
Class variables:
* There's no need for the class variable
connection
, get rid of it.
* The class variable
readThread
is questionable as well. What if there are multiple read threads? Is that variable ever initialized to anything?
* Hashtables are sooooo .NET 1.1. Generics are better and there's no need for
clients
or
writers
to be lookup tables, a
List<Socket>
will suffice.
For the server method:
private volatile bool runServer = false;
public void RunServer()
{
TcpListener listener = new TcpListener(IPAddress.Parse(ipaddressstring), portnumber);
try
{
listener.Start();
DiplayMessage("Waiting For Connections...\r\n");
while (runServer)
{
if (listener.Pending())
{
Socket connection = listener.AcceptSocket();
lock (clients)
{
clients.Add(connection);
}
Thread clientThraed = new Thread(GetMessages);
clientThraed.IsBackground = true;
clientThraed.Start(connection);
}
else
{
Thread.Sleep(250);
}
}
}
catch (Exception error)
{
MessageBox.Show(error.ToString());
}
finally
{
listener.Stop();
}
return;
}
Inline comments should explain most of it but the highlights are that:
* it doesn't call any blocking methods (
AcceptSocket
) unless it knows it won't block
* it checks a boolean (
runServer
) to see if it should continue running
* it calls
listener.Stop()
before the method exits
* it makes the read thread that it creates a background thread
* it protects
clients
with a
lock
since it's accessed by both the main and server threads
* it passes the socket to GetMessages as a param
GetMessages now takes a parameter so it should start like this:
private void GetMessages(object obj)
{
Socket connection = obj as Socket;
}
All of these principals should be used to rewrite the
GetMessages
method so that it locks resources that are accessed by multiple threads and exists cooperatively. Also, I think the NetworkStream needs to be
Dispose()
d of when you're finished with it.
This now changes a whole bunch of other things in your app:
* before you start the server thread (in the connect button callback) set
runServer
to
true
.
* to stop the server thread just set
runServer
to
false
and the
RunServer
method will exit - this should replace the call to
Environment.Exit
.
* the read threads should likewise be killed by setting a bool to
false
to tell them to exit, if the client hasn't already sent the magic string.
* where you were closing the global
connection
before you should now be looping over every socket in
clients
and closing all of them. Be careful, though. If you close a socket while the thread that's monitoring it is still alive then that method will probably throw an exception. Before you close all sockets you should probably tell the read threads to exit. And remember to lock
clients
before you start looping.
* Be sure to lock
writers
when using it as well.
If you provide a more detailed explanation of what you're expecting your app to do you may get more helpful info. As it is this is a very broad question and answer that skims over a lot of stuff. If you have a more specific question you'll probably get a more specific answer.
Good Luck :)