2013-11-27 27 views
0

我正在测试一些基于tcp ip的服务器,我的测试客户端在.net下的c#中。TCPClient中的NullReferenceException当连接到服务器的循环中

我的测试客户端类是一些琐碎的异步套接字代码:

public void Connect() 
    { 
     try 
     { 
      _tcpClient.BeginConnect(IPAddress, Port, OnConnectCallBack, null); 
     } 
     catch (Exception exc) 
     { 
      Debug.Assert(false, exc.Message); 
     } 
    } 

private void OnConnectCallBack(IAsyncResult ar) 
    { 
     try 
     { 
      _tcpClient.EndConnect(ar); 

     } 
     catch (Exception exc) 
     { 
      Debug.WriteLine("Connection error: " + exc.Message); 
     } 
    } 

_tcpClient是TcpClient的实例。

我一次试图与服务器建立几个(100)连接来进行压力测试。如果我在通话连接之间增加50毫秒的睡眠时间,它就像一个魅力。但是,当我尝试在foreach(...)迭代中连接而没有在连接之间添加睡眠时,OnConnectCallBack抛出异常:在System.dll中发生了第一次机会异常'System.NullReferenceException'。连接错误:对象引用未设置为对象的实例。有时我得到目标机器拒绝连接异常。

设置断点后,我发现它来自于_tcpClient:它的方法和属性值都不可见,它们都具有空引用异常值,并且其Client属性为null。

在TestClient.OnConnectCallBack(IAsyncResult的AR)C:... \ TestClient.cs(82) 在LazyAsyncResult.Complete(IntPtr的userToken)
在ContextAwareResult.CompleteCallback(对象状态)
在ExecutionContext.runTryCode(在RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode代码,CleanupCode backoutCode对象的UserData)
,在ExecutionContext.RunInternal(的ExecutionContext的ExecutionContext,ContextCallback回调对象的UserData)
,对象状态)
在ExecutionContext.Run(的ExecutionContext的ExecutionContext,ContextCallback回调,对象状态,博齐墩果ignoreSyncCtx)
在ExecutionContext.Run(的ExecutionContext的ExecutionContext,ContextCallback回调,对象状态)
在ContextAwareResult.Complete(IntPtr的userToken)
在LazyAsyncResult.ProtectedInvokeCallback(对象结果,IntPtr的userToken)
在LazyAsyncResult.InvokeCallback(对象结果)
在QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
在ThreadPoolWorkQueue.Dispatch()
在_ThreadPoolWaitCallback.PerformWaitCallback()

+1

如果你没有延迟,BusyConnect()中的'TcpClient'忙于防止再次入侵?目标机器错误可能是服务器没有足够的队列插槽在listen()中等待的结果。 – Pekka

+0

嗨佩卡!谢谢! “BusyConnect()”是什么意思? – Tom

+0

对不起。我的意思是'BeginConnect()'。由于操作是异步的,所以在任何情况下都可能不安全地调用该方法。你不能解释你是否试图强调在功能上检查服务器的测试。如果它是第一个,你可以为每个连接使用'TcpClient'的单独实例。 – Pekka

回答

2

此行为出现在我的oppinion中,这是异步方法BeginnConnect在同一个TcpClient实例上的多次调用的结果,无需等待已建立的连接。

根据你的压力测试的目的,你有(至少)两种可能性:

  1. 如果你想强调多TcpClients可以创建TcpClients列表和迭代此列表应用程序致电BeginConnect。您应该将参数TcpClient的实例传递给回调函数中的此实例。

  2. 要用快速连接强调应用程序,但一次只能调用一个,请拨打Connect而不是BeginnConnect。这将阻塞该线程,直到连接建立。之后您直接致电Close断开连接。由于这部署了TcpClient,您必须先创建一个新实例,然后再次致电Connect

0

没有看到你的代码如何使用这种方法(提示:发布你的代码),很难确定的问题。

根据你的解释,我猜你试图在多个并发操作中使用TcpClientTcpClient不支持并发操作;您可以使用BeginXXXEndXXX对异步执行操作,但异步处理不等于并发处理。

为每个并发操作创建一个实例TcpClient来解决您的问题。这可以通过每次循环运行时创建一个来轻松实现。