开发者

Multiple Threads to the same TCP Socket

I am a .NET Developer and am new to Socket Programming.

I wrote a program which sends some data to the client using a TCP Socket using .NET Socket Library.

The client requires a custom Keep Alive Message every 40 secs to keep the connection alive.

So, I wrote main program that establishes a connection with the client. With-in this main program, I create a thread and pass the instance of Socket Class that was created earlier. This thread is responsible for sending the keep alive messages to the client while the main thread is responsible for sending the data.

It all works good. But if for some reason socket connection is time out, the program will never recover? I put the logic for both the threads to exit and new connnection to be established but it will always give an error - ' The connection with the host is aborted' or something similar.

Am i doing something wrong?

I need to have two threads connected to the same socket. One thread is responsible for sending the data and other is responsible for sending the keep alive messages. What should be the best approach for this?

No, I am not trying to use the same socket. I break away from the for loop and clntSock.close()...

Here is the code :

I have mainThread that calls handleClient. handleClient Creates another thread.

class DispatchLoop
{
    ILogger logger;
    TcpListener listener;
    IProtocolFactory protoFactory;

    public DispatchLoop(TcpListener listener, ILogger logger, IProtocolFactory protoFactory)
    {
        this.logger = logger;
        this.listener = listener;
        this.protoFactory = protoFactory;
    }

    public void mainThread()
    {
        // Run forever, accepting and handling each connection
        for (; ; )
        {
            try
            {
                Socket clntSock = listener.AcceptSocket(); // Block waiting for connection
                PoolDispatcher._stopper.Reset();
                clntSock.ReceiveTimeout = 10000;
                IProtocol protocol = protoFactory.createProtocol(clntSock, logger);
                protocol.handleClient();
            }
            catch (SocketException se)
            {
                logger.writeEntry("(Run Dispatcher) Exception = " + se.Message);
            }
        }
    }
}

    public void handleClient()
    {
        entry.Add("Main Thread Entered : Client address and Port = " + clntSock.RemoteEndPoint + ", Thread Number = " + Thread.CurrentThread.GetHashCode());

        //Kick Starting Keep Alive Thread
        KeepAlive ka = new KeepAlive(clntSock, logger);
        Thread thread = new Thread(new ThreadStart(ka.SendKeepAlive));
        thread.Start();
        try
        {
            int recvMsgSize; // Size of received message
            byte[] rcvBuffer = new byte[BUFSIZE]; // Receive buffer
            byte[] messageBuffer = new byte[1024];
            XDocument _messageXDoc;
            FlightInfoExtended _flightInfoExtended;
            try
            {
                LogEntry(entry);
                for (; ; )
                {
                    try
                    {
                        //Read from the Queue 
                        var _queue = new IBMQueue();
                        var message = _queue.ReceiveMessage();

                        if (message.Length > 0)
                        {
                            entry.Add("Sending the GOS Message to the client : " + message);
                            messageBuffer = Encoding.ASCII.GetBytes(message);

                            if (clntSock.Connected)
                            {
                                clntSock.Send(messageBuffer, 0, messageBuffer.Length, SocketFlags.None);
                                recvMsgSize = clntSock.Receive(rcvBuffer, 0, rcvBuffer.Length, SocketFlags.None);
                                SaveGOSMessage(_auditMessage);
                            }
                            else
                            {
                                PoolDispatcher._stopper.Set();
                                LogFailureStatus("No Socket Connection");
                                Thread.Sleep(30000);
                                break;
                            }
                        }
                    }
                    catch (SocketException se)
                    {
                        PoolDispatcher._stopper.Set();
                        LogFailureStatus(se.Message);
                        Thread.Sleep(30000);
                        break;
                    }
                    catch (Exception e)
                  开发者_开发百科  {
                    }
                    LogEntry(entry);
                }
            }
            catch (Exception se)
            {
                entry.Add(String.Format("{0}: {1}", se.Source, se.Message));
            }
        }
        catch (Exception se)
        {
            entry.Add(String.Format("{0}: {1}", se.Source, se.Message));
        }

        clntSock.Close();

        logger.writeEntry(entry);
    }



public class KeepAlive
{
    ArrayList entry;
    private ILogger logger;
    private Socket clntSock;
    public const int BUFSIZE = 1024;

    public KeepAlive(Socket clntSock, ILogger logger)
    {
        this.logger = logger;
        this.clntSock = clntSock;
        entry = new ArrayList();
    }

    void LogEntry(ArrayList _entry)
    {
        logger.writeEntry(_entry);
        entry.Clear();
    }

    public void SendKeepAlive()
    {
        entry.Add("Keep Alive Thread Entered : Client address and Port = " + clntSock.RemoteEndPoint + ", Thread Number = " + Thread.CurrentThread.GetHashCode());

        var message= "Some Keep Alive Message";

        try
        {
            byte[] messageBuffer = new byte[1024];
            LogEntry(entry);
            for (; ; )
            {
                //Check if main thread died
                if ( PoolDispatcher._stopper.WaitOne(100, false))  
                {                                 
                    break;
                }

                if (clntSock.Connected)
                {
                    entry.Add("Sending the Keep Alive Message... " + message);
                    messageBuffer = Encoding.ASCII.GetBytes(message);
                    clntSock.Send(messageBuffer, 0, messageBuffer.Length, SocketFlags.None);
                }
                else
                {
                    entry.Add("Socket Connection is not active. Keep Alive not sent");
                    break;
                }
                LogEntry(entry);
                Thread.Sleep(30000);
            }
        }
        catch (SocketException se)
        {
            entry.Add(String.Format("{0}: {1}", se.ErrorCode, se.Message));
        }
        catch (ObjectDisposedException ode)
        {
            entry.Add("Connection to the socket lost. Child Thread Aborted");
        }
        LogEntry(entry);
    }
}


Its easy to approach just integrate the two module .i.e server and Client in single thread and spawn read write thread for each instance,for each Socket with by IP address (not by same Port)

http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient%28v=VS.90%29.aspx & http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener%28v=VS.90%29.aspx

use this alone it works perfect. I completed this thing,Hope its helps u.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜