吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 569|回复: 11
收起左侧

[求助] 【C#】异步多线程 求助

[复制链接]
lizf2019 发表于 2024-8-16 18:12
本帖最后由 lizf2019 于 2024-8-16 19:24 编辑

正在测试自己的服务器的抗打能力,因为市面上
直接可用的不太好找,遂想自己写一个




参考的代码测试后觉得难以使用,求助大佬如何实现这个:
1. C#每秒创建十个线程,每个线程通过不同代{过}{滤}理ip执行对url循环访问,之后每个线程在被创建的30s后自动销毁
2.每创建10个线程之前 使用Getip()更新ip库,之后每个代{过}{滤}理ip【格式为 ip:port 】从字符串数组
Myip[]中调用:  Myip[n]   n大于等于0小于等于9
3.代码是测自己服务器承受能力用的,如果有更好的模拟访问等方法欢迎大佬指出{:301_997:}

以下为ip格式,我通过

string[] ipPortPairs;
ipPortPairs = ipPortString.Split(' ');


将其存入数组



115.209.48.179:37608 116.7.173.115:31843 116.7.201.221:35131 119.132.91.47:39837 222.189.81.116:35243 175.146.211.176:34454 121.234.46.195:34738 111.72.196.138:33973 42.57.150.201:39846 111.72.134.86:40290




免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
为之奈何? + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

刺心 发表于 2024-8-16 18:24
[C#] 纯文本查看 复制代码
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

public class ServerStressTest
{
    // 可配置的常量
    private const int ThreadCount = 10; // 每秒创建的线程数
    private const int RequestTimeoutSeconds = 30; // 每个请求的超时时间(秒)
    private const int DelayBetweenBatches = 1000; // 每批线程之间的延迟时间(毫秒)
    private const string RequestUrl = "http://your-url-here.com"; // 要访问的URL
    private static readonly string[] Myip = new string[10]; // 代{过}{滤}理IP数组

    private static int ipIndex = 0;

    public static void Main()
    {
        // 初始化 Myip 数组
        for (int i = 0; i < Myip.Length; i++)
        {
            Myip[i] = $"127.0.0.{i + 1}:8080"; // 示例IP:端口
        }

        StartProxyRequests();
    }

    public static void StartProxyRequests()
    {
        Task.Run(async () =>
        {
            while (true)
            {
                List<Task> tasks = new List<Task>();

                for (int i = 0; i < ThreadCount; i++)
                {
                    UpdateIpPortPairs(); // 每次循环前更新 IP 库
                    tasks.Add(CreateRequestTask());
                }

                await Task.WhenAll(tasks);
                await Task.Delay(DelayBetweenBatches); // 等待指定的延迟时间后继续创建新的一批任务
            }
        });
    }

    private static Task CreateRequestTask()
    {
        return Task.Run(async () =>
        {
            string ipPort = GetNextIpPort(); // 获取下一个 IP:Port
            var cts = new CancellationTokenSource(TimeSpan.FromSeconds(RequestTimeoutSeconds)); // 设置超时为30秒

            using (HttpClientHandler handler = new HttpClientHandler())
            {
                handler.Proxy = new System.Net.WebProxy($"http://{ipPort}");
                handler.UseProxy = true;

                using (HttpClient client = new HttpClient(handler))
                {
                    try
                    {
                        Console.WriteLine($"使用代{过}{滤}理 {ipPort} 发送请求...");

                        // 发送请求
                        var response = await client.GetAsync(RequestUrl, cts.Token);
                        string result = await response.Content.ReadAsStringAsync();

                        Console.WriteLine($"来自 {ipPort} 的响应: {result.Substring(0, 100)}");
                    }
                    catch (TaskCanceledException)
                    {
                        Console.WriteLine($"代{过}{滤}理 {ipPort} 的任务已取消。");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"代{过}{滤}理 {ipPort} 的任务发生错误: {ex.Message}");
                    }
                }
            }
        });
    }

    private static string GetNextIpPort()
    {
        lock (Myip)
        {
            string ipPort = Myip[ipIndex];
            ipIndex = (ipIndex + 1) % Myip.Length;
            return ipPort;
        }
    }

    private static void UpdateIpPortPairs()
    {
        // 在这里更新 Myip 数组
        // 例如,可以从某个服务或数据库中获取新的代{过}{滤}理 IP 地址
        Console.WriteLine("更新IP库...");
    }
}
 楼主| lizf2019 发表于 2024-8-16 19:26
刺心 发表于 2024-8-16 18:24
[mw_shl_code=csharp,true]using System;
using System.Collections.Generic;
using System.Net.Http;

好像有点问题 image.png
jidesheng6 发表于 2024-8-16 21:27
你测试服务器压力的话,我更建议你用python的locust框架进行测试,你有c#的基础上手python不会特别难;比你自己费劲写效果要好很多,你想模拟多少就模拟多少,公司服务器做压力测试的时候直接全断开了。给你参考下写法,不是特别难,稍微研究下就行。

image.png

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
lizf2019 + 1 + 1 感谢指点

查看全部评分

zlqhysy 发表于 2024-8-16 21:45
都是高手呀
katelya 发表于 2024-8-16 21:48
用Apache JMeter或locust进行压力测试试试?
cfnm123 发表于 2024-8-16 21:59
本帖最后由 cfnm123 于 2024-8-16 22:01 编辑

[Asm] 纯文本查看 复制代码
using System;
using System.Diagnostics;
using System.Net.Http;
using System.Net.Http.Json;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

class Program
{
    private static readonly SemaphoreSlim semaphore = new SemaphoreSlim(100, 100);
    private static readonly string[] Myip;
    private static readonly IHost host;
    private static readonly HttpClient httpClient;
    private static readonly ILogger logger;
    private static readonly string url = "http://your-target-url-here";

    static Program()
    {
        // 初始化代{过}{滤}理IP列表
        string ipPortString = "115.209.48.179:37608 116.7.173.115:31843 116.7.201.221:35131 119.132.91.47:39837 222.189.81.116:35243 175.146.211.176:34454 121.234.46.195:34738 111.72.196.138:33973 42.57.150.201:39846 111.72.134.86:40290";
        Myip = ipPortString.Split(' ');

        host = Host.CreateDefaultBuilder()
            .ConfigureServices((context, services) =>
            {
                services.AddLogging(builder => builder.AddConsole());
                services.AddHttpClient();
            })
            .Build();

        logger = host.Services.GetRequiredService<ILogger<Program>>();
        httpClient = host.Services.GetRequiredService<IHttpClientFactory>().CreateClient();
    }

    static async Task Main(string[] args)
    {
        for (int i = 0; i < 10; i++)
        {
            await UpdateIpListAsync();
            await CreateThreadsAsync();
            await Task.Delay(1000); // 每秒创建一次
        }

        logger.LogInformation("All threads have been created.");
        Console.ReadKey();
    }

    static async Task CreateThreadsAsync()
    {
        for (int i = 0; i < 10; i++)
        {
            int index = i;
            var task = ExecuteRequestAsync(index);
            await task;
        }
    }

    static async Task ExecuteRequestAsync(int index)
    {
        var handler = new HttpClientHandler
        {
            Proxy = new WebProxy(Myip[index]),
            UseProxy = true
        };

        using var client = new HttpClient(handler);

        try
        {
            var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); // 设置30秒超时
            var cancellationToken = cancellationTokenSource.Token;

            while (!cancellationToken.IsCancellationRequested)
            {
                await semaphore.WaitAsync(cancellationToken);

                try
                {
                    var stopwatch = Stopwatch.StartNew();
                    var response = await client.GetAsync(url, cancellationToken);
                    stopwatch.Stop();

                    if (response.IsSuccessStatusCode)
                    {
                        logger.LogInformation($"Thread {index} made a request to {url} at {DateTime.Now.ToString("HH:mm:ss.fff")}. Response time: {stopwatch.ElapsedMilliseconds} ms.");
                    }
                    else
                    {
                        logger.LogWarning($"Thread {index} received a non-success status code: {response.StatusCode}.");
                    }
                }
                catch (OperationCanceledException)
                {
                    logger.LogInformation($"Thread {index} was canceled.");
                }
                catch (Exception ex)
                {
                    logger.LogError(ex, $"Error in thread {index}: {ex.Message}");
                }
                finally
                {
                    semaphore.Release();
                    await Task.Delay(1000, cancellationToken); // 控制每个线程的请求频率
                }
            }
        }
        finally
        {
            logger.LogInformation($"Thread {index} has been terminated.");
        }
    }

    static async Task UpdateIpListAsync()
    {
        // 这里可以添加逻辑来获取新的代{过}{滤}理IP列表
        logger.LogInformation("Updating IP list...");
        await Task.Delay(100); // 假设这里有一些延迟
    }
}

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
lizf2019 + 1 + 1 感谢指点

查看全部评分

FitContent 发表于 2024-8-16 22:41

”创建线程又关闭线程“ 的操作可以简化。根据楼主的第一个描述,当程序跑起来时,会有 20 个线程在工作,所以我用的是线程池,共创建 20 个线程。

还有,以下代码是结合 AI 写的。

using System;
using System.Net;
using System.Threading;
using System.Collections.Concurrent;

class Program
{
    /// <summary>
    /// 最大的线程数
    /// </summary>
    private const int maxThread = 20;
    /// <summary>
    /// 要访问的 URL
    /// </summary>
    private const string targetUrl = "http://xxx.com";
    /// <summary>
    /// 存储 IP 地址的队列,被线程共享
    /// </summary>
    private static readonly ConcurrentQueue<string> MyIp = new();
    /// <summary>
    /// 用于获取 IP 时的锁
    /// </summary>
    private static readonly object locker_for_getip = new();

    static void Main()
    {
        // 循环创建线程到线程池中
        for (int i = 0; i < maxThread; i++)
        {
            ThreadPool.QueueUserWorkItem(FetchUrl, i);
        }

        Console.WriteLine("Press any key to exit...");
        Console.ReadKey();
    }

    /// <summary>
    /// 发起网络请求的线程函数
    /// </summary>
    /// <param name="state"></param>
    private static async void FetchUrl(object? state)
    {
        if (state is int thread_id)
        {

            while (true)
            {
                if (MyIp.TryDequeue(out var ipAddr))
                {
                    Console.WriteLine($"Thread {thread_id} get Ip: {ipAddr}");
                    var proxy = new WebProxy(ipAddr, true);
                    var client = new HttpClient(new HttpClientHandler { Proxy = proxy, UseProxy = true });
                    await client.GetAsync(targetUrl);

                    Thread.Sleep(1000);
                }
                else
                {
                    // 没有可用的 IP 地址,调用 GetIP 方法获取新的 IP 地址
                    GetIP();
                }
            }
        }
    }

    /// <summary>
    /// 更新 IP
    /// </summary>
    /// <param name="state"></param>
    private static void GetIP()
    {
        if (MyIp.IsEmpty)
        {
            lock (locker_for_getip)
            {
                // 双重判断
                if (MyIp.IsEmpty)
                {
                    Console.WriteLine("Start get ip");
                    // 获取 ip,为了本地测试,使用 localhost 了
                    string[] ips = ["localhost:3000", "localhost:3000", "localhost:3000", "localhost:3000", "localhost:3000"];
                    foreach (var ip in ips)
                    {
                        MyIp.Enqueue(ip);
                    }
                }
            }
        }
    }

}

这是本机的测试结果,使用 python -m http.server 3000 开启了一个本地的服务器进行测试。

image-20240816224006420.png

免费评分

参与人数 1吾爱币 +2 热心值 +1 收起 理由
lizf2019 + 2 + 1 谢谢@Thanks!

查看全部评分

wxk0248 发表于 2024-8-16 23:32
压测自己写不是很费劲么,为什么不用现成的,比如Jmetter
 楼主| lizf2019 发表于 2024-8-17 01:51
wxk0248 发表于 2024-8-16 23:32
压测自己写不是很费劲么,为什么不用现成的,比如Jmetter

主要是要实时从接口获取代{过}{滤}理ip
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 11:28

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表