日期:2014-05-19  浏览次数:20819 次

异步Socket,如何进行并发数量测试?
写了一个异步socket的服务程序,现在如何做并发数量的测试?
我在本机上同时启动了200个客户端,运行正常,但是超过300就开始有连接不上的情况发生,我的机器2.8CPU   1G内存.
同时在两台机器上各运行200个客户端,还是各有一部分的连接不上的情况.
请问,我的服务程序的并发数量就只能是300以下了吗?
并发数量跟什么有关系,如何做测试呢?请有经验的高手指点一下.

------解决方案--------------------
大概是端口的流量有限,在同一台机器启动这么多客户端,会导致一些客户端连接超时。
------解决方案--------------------
估计和你的处理有很大关系,你试试只连接不做任何处理,应该可以到几千个连接呢
------解决方案--------------------
异步socket的服务程序对客户端的承受能力应该不止这二三百个,我们做的类似的socket服务接收的客户连接数目都远大与这个数目.

服务器的性能和你做程序的手法有很大关系,如果写的不好,很可能客户数目多的时候就不行了. 比如: 如果为每一个客户连接都单独生成一个线程,那么有二三百个客户连接后服务器就离死不远了. 或者虽然是异步接受了客户端的工作请求,但工作请求需要访问共享资源,有大量时间异步的线程处于等lock的状态,这样一来性能也会很差.
------解决方案--------------------
这个事情要分两部分说:

1. Socket的Receive可以起一个线程,也可以用BeginReceive,后者是在有大量连接的时候采用的方法. Code Project 上有很多这种例子,比如这个就不错:

http://www.codeproject.com/cs/internet/socketsincs.asp

接受到新的连接后不能创建一个线程来维护它,这样性能很差,一个程序如果开几百了线程就离死不远了. 最好的方法是用Socket的异步功能: BeginXXXXX/EndXXXXX

比如:

public void SetupRecieveCallback( Socket sock )
{
try
{
AsyncCallback recieveData = new AsyncCallback( OnRecievedData );
sock.BeginReceive( m_byBuff, 0, m_byBuff.Length,
SocketFlags.None, recieveData, sock );
}
catch( Exception ex )
{
MessageBox.Show( this, ex.Message, "Setup Recieve Callback failed! " );
}
}

public void OnRecievedData( IAsyncResult ar )
{
// Socket was the passed in object
Socket sock = (Socket)ar.AsyncState;

// Check if we got any data
try
{
int nBytesRec = sock.EndReceive( ar );
if( nBytesRec > 0 )
{
// Wrote the data to the List
string sRecieved = Encoding.ASCII.GetString( m_byBuff,
0, nBytesRec );

// WARNING : The following line is NOT thread safe. Invoke is
// m_lbRecievedData.Items.Add( sRecieved );
Invoke( m_AddMessage, new string [] { sRecieved } );

// If the connection is still usable restablish the callback
SetupRecieveCallback( sock );
}
else
{
// If no data was recieved then the connection is probably dead
Console.WriteLine( "Client {0}, disconnected ",
sock.RemoteEndPoint );
sock.Shutdown( SocketShutdown.Both );
sock.Close();
}
}
catch( Exception ex )
{
MessageBox.Show( this, ex.Message, "Unusual error druing Recieve! " );
}
}


此方法还有一个好处是.NET底层的Socket类库在你用异步时可以聪明到最大限度地利用通讯硬件上的线程和资源,对节省CPU资源很有帮助.

------解决方案--------------------
第二个问题是当接收了客户传来的Message之后(无论用上边我说的哪一种方法)应该如何处理:

最简单的方法就是直接在接收的线程上,但如果你的服务器处理客户请求的操作比较复杂,时间很长,而且需要对共享资源加锁读写,就回产生大量线程同时并存的情况,这对服务器的性能有很大影响.

我自己在处理这个问题的时候是在接收到客户传来的Message之后不直接处理,而是把它抛到一个队列里,这样一来接收线程就迅速释放; 另外整个服务器有一个单独的线程来处理队列里所有客户端的消息. 此方法在实际应用中效果相当不错.

如果感兴趣,可以看一下我 Blog 里的那篇文章,有源代码:

http://blog.csdn.net/RedGoldFish