简体   繁体   中英

Efficient multiple tcp clients with intervals

I have been writing a command line program in C# that uses multiple tcp clients that all connect to the same server. Each client resides in it's own thread. At the moment I am trying to work out an effective method of spreading say 5 requests a second efficiently between let's say 4 threads.

My code currently looks like the following but I still end up with requests overlapping each other. Does anyone have any idea how to prevent these overlaps effectively?

// Max connections is 4, interval is 200
// Loop once to give tcp clients chance to connect
var tcpClients = new TcpClient[_maxConnections];

for(int i = 0; i < _maxConnections; i++)
{
    tcpClients[i] = new TcpClient();
    tcpClients[i].Connect(host, port);
}

// Loop again to setup tasks
for(int i = 0; i < _maxConnections; i++)
{
   Task.Factory.StartNew(TcpHandler, tcpClients[i]);

   // Sleep so every task starts separate from each other.
   Thread.Sleep(_interval);
}

And then the TcpHandler code looks like:

public static void TcpHandler(Object o)
{
    // active is already declared
    while(_active)
    {
        var tcpClient = (TcpClient) o;

        // .. do some send and receive...

        Console.WriteLine("Something here..");

        Thread.Sleep(_interval * _maxConnections);
    }
}

So as you can see I am sleeping to provide sufficient space between each thread executing yet now and then they still overlap.

How can I make this threads run parallel without any overlap and limit to 5 times a second spread across all 4?

Or am I going about this all wrong?

Presuming each client requires a separate thread, and that only one thread may be communicating with the server at a given time (no overlap), a lock in the TcpHandler method should suffice:

// Max connections is 4, interval is 200
// Loop once to give tcp clients chance to connect
var tcpClients = new TcpClient[_maxConnections];
// dedicated lock object
static readonly object lockObject = new object();

And then in your TcpHandler method

public static void TcpHandler(Object o)
{
    // active is already declared
    while(_active)
    {
        //DO NON-SOCKET RELATED STUFF HERE
        // ... code ...
        //
        //DO SOCKET RELATED STUFF HERE
        lock(lockObject)
        {
            var tcpClient = (TcpClient) o;

            // .. do some send and receive...

            Console.WriteLine("Something here..");

            Thread.Sleep(_interval * _maxConnections);
        }
    }
}

I am not quite sure why you are doing this but I have used System.Timers (actually an array of timers) in windows services and have staggered the start (intervals).

In the Elapse event maybe you could use a lock(myobject) { } so they don't overlap?

Gina

I think you are using sleep to manage connection times.. Why not instead setup a "Maximum connection delay" then use BeginConnect and a Timer to look after the connection.

eg.

//setup a timer variable
TCPClient connectionOpening;

_connecting = true;
_connected = false;

connectionOpening = tcpClient;
timer.change(5000, Infinite)
tcpClient.BeginConnect(ClientConnectCallback, tcpClient)

void ClientConnectCallback(iasyncresult ar)
{ 
    _timer.change(infinite, infinite);
    TCPClient tcp = (TCPClient)ar.AsyncState;
    try
    {
        //if we have timed out because our time will abort the connect
        tcp.EndConnect(ar);
        _connected = true;
        _connecting = false;
        //we are now connected... do the rest you want to do.
        //get the stream and BeginRead etc.

    }
    catch (Exception ex) // use the proper exceptions IOException , socketException etc
    {
        if (!_connecting)
        {
            //We terminated the connection because our timer ticked.
        }
        else
        {
            //some other problem that we weren't expecting
        }
    }

void TimerTick(object state)
{
    _connecting = false;
    _connected = false;
    connectionOpening.Close();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM