Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
TCPListener与单个客户端程序(C#)之间的高性能套接字通信_C#_Sockets_Tcplistener - Fatal编程技术网

TCPListener与单个客户端程序(C#)之间的高性能套接字通信

TCPListener与单个客户端程序(C#)之间的高性能套接字通信,c#,sockets,tcplistener,C#,Sockets,Tcplistener,我有一个TCPListener服务器在专用端口侦听,并且只有一个客户机与服务器连接。客户端与服务器建立连接,并以60秒的间隔继续发送心跳消息,以使其保持活动状态。此外,它还发送不同类型的请求消息(每个消息的前4个字节保留为消息大小),服务器接收并将套接字传递给任务(异步),该任务执行一个漫长的过程,包括DB I/O,并使用相同的套接字返回响应。它一直工作正常,但最近客户端开始异步发送1000个请求。服务器以良好的速度响应初始请求,但在处理大约100个请求后,响应速度变慢。我征求您的专家意见,以便

我有一个TCPListener服务器在专用端口侦听,并且只有一个客户机与服务器连接。客户端与服务器建立连接,并以60秒的间隔继续发送心跳消息,以使其保持活动状态。此外,它还发送不同类型的请求消息(每个消息的前4个字节保留为消息大小),服务器接收并将套接字传递给任务(异步),该任务执行一个漫长的过程,包括DB I/O,并使用相同的套接字返回响应。它一直工作正常,但最近客户端开始异步发送1000个请求。服务器以良好的速度响应初始请求,但在处理大约100个请求后,响应速度变慢。我征求您的专家意见,以便作出有力的回应

class ServerA
{
    .......
    .......
private void StartServer()
{
    ......
    socket = tcpListener.AcceptSocket();
    Process(socket);
    .......
}

private void Process(Socket clientSocket)
{
    while(true)
    {
       byte[] msg = new byte[1024 * 1024];
       int totalMsgLength = clientSocket.Receive(msg);

       ClientRequest req = new ClientRequest();

       byte[] request = new byte[totalMsgLength];
       Buffer.BlockCopy(msg, 0, request, 0, totalMsgLength);
       req.HandleRequest(clientSocket, request); 

    }
}
}

class ClientRequest
{
byte[] request;
Socket clientSocket;

public void HandleRequest(Socket clientSocket,byte[] request)
{
    try
    {
        this.request = request;
        this.clientSocket = clientSocket;
        Task.Run(() =>
        {
            Entertain(null);
        });                
    }
    catch (Exception ex)
    {
        .....
    }
}

private void Entertain(object callback)
{
    request = admin.PerformAction(ref request); //Long process
    clientSocket.Send(request); 
}
}

我可以想象,尽管我们不能确定,这很大程度上是由于1MiB缓冲区,然后是一个大小合适的缓冲区,您可以分配每次读取;将其扩展到每秒1000次,是的:这会造成很大的伤害。有效的缓冲区管理很困难,简单的方法只适用于小容量的工作

不过,老实说,我更关心盲人;意思:你提到了TCP,TCP是一个流协议,而不是数据包协议;在您接收缓冲区的方式和发送的内容之间没有任何关联-就每条消息的结束位置而言,尤其是对于高容量/高频率而言;你需要一个“框架”协议。否则,您发送到
HandleRequest
的可能是不完整的消息、多条消息等


您还应该有一个
中断totalMsgLength,请在循环中选择code>,谢谢您的快速响应。为了保持问题的简单,我尽量少编写代码,这显然造成了一些混乱。客户端发送定义良好的ISO8583消息,并且在每个消息的开头发送消息的长度,所以服务器读取套接字并根据消息长度进行分解。不过,我正在研究你的1MiB建议。会让你了解最新情况。再次感谢。我根据您的建议进行了更改,并在UAT部署了升级,但遗憾的是,性能没有任何改进。同样的程序在我的笔记本电脑上运行得很快(i5+4核+12 GB内存),因为所有1000个请求都在不到2分30秒的时间内得到响应,而在UAT服务器上(8个处理器+24 GB内存)执行同样的程序大约需要15分钟。有没有其他的建议来隔离这个问题?@S.ATTA.M没有更多的背景和能力来重新解释;然而,问题是:本地定时是否基于与本地机器的对话?延迟和/或带宽可能是这里的瓶颈,如果您使用Loopback,您将不会对其进行类似的测量是的,整个开发环境设置在一台机器上,不像UAT环境中的3台机器通过LAN连接。(服务器、客户端和Oracle数据库)。如前所述,实际问题是延迟,延迟开始得很好,但随着时间的推移会增加,同时处理10批请求,每批包含1000个请求。这个项目是巨大的,所以我并没有解释一切,以避免分心,并保持读者对真实问题的关注。但是,如果您需要更多信息,请随意询问。@S.ATTA.M您无法通过代码修复延迟;您可以缓解延迟问题,但这需要非常具体的设计方法,如消息管道,即客户端可能会发出5个请求,然后等待5个响应,而不是“请求、响应、请求、响应”(对于5个请求)。然而,这比从示例代码中可以合理回答的要复杂得多;细节真的很重要。顺便说一句:你没有保护
clientSocket。从并发写入中发送
,这很糟糕,谢谢你的专家意见;您的建议是,如何避免这种不好的做法?因为您使用的是同步写入:
lock(clientSocket){clientSocket.Send(request);}
您认为有必要吗?每次从“ClientRequest”类的新对象调用方法()时,我相信它已经是线程安全的了。@jdweng re chunks:我在回答中提出了同样的问题,但(请参阅注释)显然这只是来自简化代码;另外:请参阅“巨型帧”-每个数据包的大小可以超过1500字节