简体   繁体   English

间隔有效的多个tcp客户端

[英]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. 我一直在用C#编写一个命令行程序,该程序使用都连接到同一服务器的多个tcp客户端。 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. 目前,我正在尝试一种有效的方法,例如在4个线程之间有效地传播5个请求。

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: 然后,TcpHandler代码如下所示:

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? 如何使该线程并行运行而没有任何重叠,并限制所有4个线程每秒传播5次?

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: 假设每个客户端都需要一个单独的线程,并且在给定时间(不重叠),只有一个线程可以与服务器通信,则TcpHandler方法中的lock就足够了:

// 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 然后在您的TcpHandler方法中

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). 我不太确定为什么要这样做,但是我在Windows服务中使用了System.Timers(实际上是一组定时器),并且错开了开始时间(间隔)。

In the Elapse event maybe you could use a lock(myobject) { } so they don't overlap? 在Elapse事件中,您可以使用lock(myobject){},以使它们不重叠?

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. 我认为您正在使用睡眠来管理连接时间。为什么不改而设置“最大连接延迟”,然后使用BeginConnectTimer来照顾连接。

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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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