我的任务是设计一个相当简单的TCP/IP服务器,它必须接受来自多个客户端的连接.它需要用C#编写,我使用的是.NET 4.5.也就是说,我不确定.NET 4.5中TCP/IP服务器/客户端可扩展性的当前"最先进"是什么.
我确实看到了这篇文章:如何编写可扩展的基于Tcp/Ip的服务器.但这与.NET 2.0和3.5有关,并没有提到async/await模式.
我能够以"旧方式"编写服务器...但我想知道"新方式"是什么.
编辑:其他问题.
我很难处理Java垃圾收集问题,并解释日志.
我的应用程序要求GC不需要超过2秒,理想情况下小于100毫秒.
根据以前的一些建议,我正在尝试以下命令行选项:
 java -XX:MaxGCPauseMillis=100 -XX:NewRatio=9 -XX:+UseConcMarkSweepGC  -XX:+CMSIncrementalMode -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -server -Xmx9g -Xms9g 
该应用程序具有大量长期存储的对象,这些对象保存在ConcurrentLinkedHashMap中.我偶尔会看到长时间停顿,最糟糕的情况是长达10秒(这是下面的GC日志中的第二个)!
以下是我得到的一些输出:
16938.968: [GC 16938.968: [ParNew: 153343K->17022K(153344K), 7.8608580 secs] 6184328K->6122510K(9420160K) icms_dc=7 , 7.8614100 secs] [Times: user=0.63 sys=0.01, real=7.86 secs] 
16947.087: [GC 16947.087: [ParNew: 153342K->17022K(153344K), 7.2604030 secs] 6258830K->6198642K(9420160K) icms_dc=7 , 7.2609780 secs] [Times: user=0.44 sys=0.00, real=7.27 secs] 
16954.614: [GC 16954.614: [ParNew: 153342K->17024K(153344K), 8.4307620 secs] 6334962K->6274625K(9420160K) icms_dc=7 , 8.4313150 secs] [Times: user=0.62 sys=0.01, real=8.43 secs] 
16963.310: [GC 16963.310: [ParNew: 153344K->17023K(153344K), 6.2588760 secs] 6410945K->6350748K(9420160K) icms_dc=7 , 6.2594290 secs] [Times: user=0.48 …当以1024块的数据块读取数据时,如何继续从接收大于1024字节的消息的套接字读取,直到没有数据为止?我应该只使用BeginReceive来读取数据包的长度前缀,然后一旦检索到它,使用Receive()(在异步线程中)读取数据包的其余部分?或者还有另一种方式吗?
我认为Jon Skeet的链接有解决方案,但是有一些关于该代码的speedbump.我使用的代码是:
public class StateObject
{
    public Socket workSocket = null;
    public const int BUFFER_SIZE = 1024;
    public byte[] buffer = new byte[BUFFER_SIZE];
    public StringBuilder sb = new StringBuilder();
}
public static void Read_Callback(IAsyncResult ar)
{
    StateObject so = (StateObject) ar.AsyncState;
    Socket s = so.workSocket;
    int read = s.EndReceive(ar);
    if (read > 0) 
    {
        so.sb.Append(Encoding.ASCII.GetString(so.buffer, 0, read));
        if (read == StateObject.BUFFER_SIZE)
        {
            s.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0, 
                    new AyncCallback(Async_Send_Receive.Read_Callback), so);
            return;
        }
    }
    if (so.sb.Length > 0)
    {
        //All …我写了一个简单的TCP客户端和服务器.问题在于客户.
我在阅读服务器的整个响应时遇到了一些麻烦.我必须让线程休眠以允许发送所有数据.
我已经尝试了几次将此代码转换为一个循环,直到服务器完成发送数据.
// Init & connect to client
TcpClient client = new TcpClient();
Console.WriteLine("Connecting.....");
client.Connect("192.168.1.160", 9988);
// Stream string to server
input += "\n";
Stream stm = client.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(input);
stm.Write(ba, 0, ba.Length);
// Read response from server.
byte[] buffer = new byte[1024];
System.Threading.Thread.Sleep(1000); // Huh, why do I need to wait?
int bytesRead = stm.Read(buffer, 0, buffer.Length);
response = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine("Response String: "+response);
client.Close();
我在一台具有16Gb RAM,8核处理器和Java 1.6的机器上运行内存密集型应用程序,所有这些都运行在CentOS 5.2版(最终版)上.精确的JVM详细信息是:
java version "1.6.0_10"
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot(TM) 64-Bit Server VM (build 11.0-b15, mixed mode)
我正在使用以下命令行选项启动应用程序:
java -XX:+UseConcMarkSweepGC -verbose:gc -server -Xmx10g -Xms10g ...
我的应用程序公开了一个JSON-RPC API,我的目标是在25ms内响应请求.不幸的是,我看到延迟超过1秒,似乎是垃圾收集造成的.以下是一些较长的例子:
[GC 4592788K->4462162K(10468736K), 1.3606660 secs]
[GC 5881547K->5768559K(10468736K), 1.2559860 secs]
[GC 6045823K->5914115K(10468736K), 1.3250050 secs]
这些垃圾收集事件中的每一个都伴随着延迟的API响应,其持续时间与显示的垃圾收集的长度非常相似(在几毫秒内).
以下是一些典型示例(这些示例均在几秒钟内生成):
[GC 3373764K->3336654K(10468736K), 0.6677560 secs]
[GC 3472974K->3427592K(10468736K), 0.5059650 secs]
[GC 3563912K->3517273K(10468736K), 0.6844440 secs]
[GC 3622292K->3589011K(10468736K), 0.4528480 secs]
问题是我认为UseConcMarkSweepGC可以避免这种情况,或者至少使它非常罕见.相反,超过100毫秒的延迟几乎每分钟发生一次或更多(尽管超过1秒的延迟相当罕见,可能每10或15分钟一次).
另一件事是我认为只有一个FULL GC会导致线程被暂停,但这些似乎不是完整的GC.
可能需要注意的是,大多数内存都是由使用软引用的LRU内存缓存占用的.
任何帮助或建议将不胜感激.
我们需要为使用C#开发的应用程序开发某种缓冲区管理.
从本质上讲,应用程序会在设备进入时接收消息(在很短的时间内可能存在很多消息).我们需要在某种缓冲池中将它们排队,以便我们可以以托管方式处理它们.
我们考虑以256字节块分配一块内存(所有消息都小于该值),然后使用缓冲池管理来获得可用于传入消息的可用缓冲池以及准备处理的缓冲池.
因此,流程将是"获取缓冲区"(处理它)"释放缓冲区"或"将其保留在池中".我们还需要知道缓冲区何时填满.
潜在地,我们还需要一种方法来"窥视"缓冲区,以查看池中优先级最高的缓冲区是什么,而不是总是获取下一个缓冲区.
在.NET中是否已经支持此功能,或者是否有一些我们可以使用的开源代码?
我需要同时发送和接收。
哪个选项会更好:
或者
或者还有其他解决方案吗?
我预计最多有大约 50 个双向连接。这导致选项 #1 中有 50 个线程,选项 #2 中有 100 个线程。
是否有正当理由不TcpListener用于实现高性能/高吞吐量TCP服务器而不是SocketAsyncEventArgs?
我已经实现了这个高性能/高吞吐量的 TCP 服务器,它使用SocketAsyncEventArgs了一个大的预先分配的byte数组和SocketAsyncEventArgs用于接受和接收的池来处理那些固定缓冲区,使用一些低级的东西和闪亮的智能组合在一起,经历了各种各样的麻烦带有一些 TPL 数据流和一些 Rx 的代码,它工作得很好;在这项工作中几乎是教科书 - 实际上我已经从其他人的代码中学到了 80% 以上的这些东西。
但是也存在一些问题和顾虑:
byte数组):使用SocketAsyncEventArgs池需要预先分配。因此,为了处理 100000 个并发连接(更糟糕的情况,即使在不同的端口上),一大堆 RAM 无用地徘徊在那里;预先分配(即使这些条件只是在某些时候满足,服务器每天应该能够处理 1 或 2 个这样的峰值)。TcpListener实际上效果很好:我实际上已经进行TcpListener了测试(使用了一些技巧,例如AcceptTcpClient在专用线程上使用,而不是 async
版本,然后将接受的连接发送到 a
ConcurrentQueue而不是Task就地创建s 等)和最新版本的 . NET,它运行得非常好,几乎与SocketAsyncEventArgs.那么为什么我没有看到TcpListener在任何地方使用并且每个人(包括我自己)都在使用SocketAsyncEventArgs?我错过了什么吗?
我有一个循环,需要创建一个未指定和无限数量的后台线程.然后线程将简单地运行完成,但有些可能需要取消.
我最初计划通过声明一个backgroundWorker,将其添加到列表,然后新建BackgroundWorker以再次开始该过程来完成此操作.但是因为List.Add方法通过引用传入的对象运行,我认为当我新建原始BackgroundWorker时,List引用的线程将丢失(或更糟).
我的第二个想法是简单地将我的newed值赋给数组中的元素(array [i] = new BackgroundWorker()),但这并不适合无限量的线程.
有没有人有任何关于管理这些单独线程的好方法的建议?提前致谢.
c# ×6
sockets ×4
.net ×3
java ×2
networking ×2
async-await ×1
asynchronous ×1
blocking ×1
buffer ×1
jvm ×1
performance ×1
pool ×1
stream ×1
tcpclient ×1
tcplistener ×1
tcpserver ×1