Click here to Skip to main content
15,504,830 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi
i got error during close the socket
i can't use it again with the same port


my code is
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Net;
using System.Collections;
namespace ChatMulti_ThreadedServerForms
{
    public partial class MultiThreaded_Server : Form
    {
        public Socket connection = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
        private Thread readThread;
        int counter = 0;
        // new
        private Hashtable clients = new Hashtable();
        private Hashtable writers = new Hashtable();
        private delegate void DisplayDelegate(string msg);
        private delegate void DisableInputDelegate(bool flag);
        public string ipaddressstring = "";
        public int portnumber = 0;
        public MultiThreaded_Server()
        {
            InitializeComponent();
        }
        private void MultiThreaded_Server_Load(object sender, EventArgs e)
        {
            
        }
        
        public void RunServer()
        {
            TcpListener listener;
            try
            {
                listener = new TcpListener(IPAddress.Parse(ipaddressstring), portnumber);
                listener.Start();
                DiplayMessage("Waiting For Connections...\r\n");
                
                while (true)
                {
                    connection = listener.AcceptSocket();
                    counter++;
                    Thread clientThraed = new Thread(GetMessages);
                    clients.Add(clientThraed, connection);
                    clientThraed.Start();
                }
            }
            catch (Exception error)
            {
                MessageBox.Show(error.Message);
            }
        }
        public void GetMessages()
        {
            Socket connection = (Socket)clients[Thread.CurrentThread];
            int count = counter;
            NetworkStream socketStream = new NetworkStream(connection);
            BinaryWriter writer = new BinaryWriter(socketStream);
            BinaryReader reader = new BinaryReader(socketStream);
            writers.Add(Thread.CurrentThread, writer);
            DiplayMessage("Connection {" + counter + "} recieved...\r\n");
            writer.Write("SERVER >> Connetion successful...");
            
            DisableInput(false);
            string theReply = "";
            do
            {
                theReply = reader.ReadString();
                DiplayMessage("\r\n" + theReply);
            } while (theReply != "CLIENT >> exit" && connection.Connected);
            DiplayMessage("\r\nClient " + count +" terminated connection...");
            writer.Close();
            reader.Close();
            socketStream.Close();
            connection.Close();
            writers.Remove(Thread.CurrentThread);
            clients.Remove(Thread.CurrentThread);
            DisableInput(true);
        }
        private void MultiThreaded_Server_FormClosing(object sender, FormClosingEventArgs e)
        {
            Environment.Exit(Environment.ExitCode);
        }
        
        private void DiplayMessage(string msg)
        {
            if (Connstatuslbl.InvokeRequired)
            {
                Invoke(new DisplayDelegate(DiplayMessage), new object[] { msg });
                
            }
           
                //Connstatuslbl.Text += msg;
            
        }
        private void DisableInput(bool flag)
        {
            if (textBox2.InvokeRequired)
            {
                Invoke(new DisableInputDelegate(DisableInput), new object[] { flag });
            }
            else
                textBox1.ReadOnly = flag;
        }
        private void textBox1_KeyDown(object sender, KeyEventArgs e)
        {
            try
            {
                
                if (e.KeyCode == Keys.Enter && textBox1.ReadOnly == false)
                {
                    ICollection keys = writers.Keys;
                    foreach (object key in keys)
                    {
                        BinaryWriter writer = (BinaryWriter)writers[key];
                        writer.Write("SERVER >> " + textBox1.Text);
                    }
                    textBox2.Text += "\r\nSERVER >> " + textBox1.Text;
                    if (textBox1.Text == "exit")
                        connection.Close();
                    textBox1.Clear();
                }
            }
            catch (SocketException)
            {
                textBox2.Text += "\r\nError Writing Object...";
            }
        }
        private void connectbtn_Click(object sender, EventArgs e)
        {
                ipaddressstring = Serverip.Text;
                portnumber = Convert.ToInt32(portnum.Text);
                readThread = new Thread(RunServer);
                readThread.Start();
                if (readThread.ThreadState == ThreadState.Running)
                {
                    Connstatuslbl.Text = "Connected";
                }
                else
                {
                    Connstatuslbl.Text = "Connectedasd";
                }
               
              
            
        }
        
		
        private void disconnectbtn_Click(object sender, EventArgs e)
        {
                MessageBox.Show(readThread.ThreadState.ToString());
                connection.Shutdown(SocketShutdown.Both);
                connection.Disconnect(true);
            
        }
        
    }
}



how to close this socket and reuse it ?

thanks ..
Posted
Comments
Michel Godfroid 5-May-10 6:29am    
And what is the error you get? And where?

palboy1990 wrote:
how to close this socket and reuse it ?

Which socket?

Without describing the error then all we can do is guess what the problem is.

My first would be that there's no listener.Stop() to match the listener.Start() so the server will run until the app exists and won't release the port until then. How does the server thread stop running?

My second would be that do { ... } while (theReply != "CLIENT >> exit" && connection.Connected); doesn't work the way that it's expected to. What happens if the client never sends anything? That call to ReadString will just sit there blocking the thread. What if the client never sends the magic exit string?

My third guess would be that the problem is hidden by an exception that's never caught; there are a few socket operations that can throw that aren't protected by anything.

My fourth is that the disconnect button click doesn't do what is expected. It looks like it disconnects the last client that connected, but what if more than one connects? Where are the other ones disconnected?

The same comment goes for the Text Box One key down event: it closes the one socket that stored in the global variable but doesn't close any others.

This one's more of a comment: why call Environment.Exit in the Form Closing event? If that's how the threads are being killed - because I don't see any other way of signaling any of them to exit - then that's bad practice. The standard way to have threads exit is to have them periodically check a flag so that they know when they should stop processing and return from their methods. Alternatively set the IsBackground property of the Threads to true so that they don't stop the process from exiting. The proper way to exit from a form is to simply let it close.

[EDIT]
Another comment: there are some variables that can be accessed by more than one thread at at time. They really need some synchronization (ex. lock) so that one thread doesn't modify them while another thread is using them.
[/EDIT]

[EDIT2]
Also, in the GetMessages method it's confusing that the local Socket variable has the same name as the class level Socket variable. That might lead to unintended behavior as well.
[/EDIT2]
 
Share this answer
 
v3
Comments
Wasim Fatair 5-May-10 15:20pm    
you are right ,
then can you help me change the code and help me out =) ?
Wasim Fatair 5-May-10 15:20pm    
i tried alot
and nothing come out with me
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:
C#
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");
        // look for connections until we're told to stop
        while (runServer)
        {
            // if a client is trying to connect . . .
            if (listener.Pending())
            {
                // accept it
                Socket connection = listener.AcceptSocket();
                // other threads may want to access this list at the same time so lock it
                lock (clients)
                {
                    clients.Add(connection);
                }
                // chuck the client off to another thread for monitoring
                Thread clientThraed = new Thread(GetMessages);
                clientThraed.IsBackground = true; // <-- important
                clientThraed.Start(connection); // pass the socket as a parameter instead of using a lookup table
            }
            else // otherwise . . .
            {
                // sleep a bit so that we don't peg the processor
                Thread.Sleep(250);
            }
        }
    }
    catch (Exception error)
    {
        // use error.ToString() instead of error.Message, it shows more info
        MessageBox.Show(error.ToString());
    }
    finally
    {
        // stop the listener, this will allow another socket to bind to the port it was
        // using now that the listener is done with it
        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:
C#
private void GetMessages(object obj)
{
    Socket connection = obj as Socket;

    // the rest of the method . . .
}


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 :)
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900