问题是这样的:
Socket客户端方面,偶用3个线程,分别是
1、Write():读取二进制文件、
2、Packet():打包缓冲区待发数据、
3、Send():发送缓冲区已打包数据。
自定义bufferManager类使用了lock和Monitor来控制线程的状态。
用Stream类辅助复制本地文件来测试bufferManager类准确无误,
说明bufferManager类没有问题,但是把写文件代码改为Socket
异步发送数据时,问题就来了,因为sendCallback(IAsyncResult ar)并不受
bufferManager类中的lock和Monitor来控制,不停地发送,
很快其速度就超过了读取和打包的速度,导致错误:
“NullReferenceException:未将对象引用设置到对象的实例”
请各位出手相助,如何解决这个问题?
部分代码如下:private void Write()
{
// 将二进制数据写入缓冲区bufferManager
}
private void Packet()
{
// 将缓冲区bufferManager中的待发数据打包(添加自定义协议)
}
private void Send()// 将缓冲区bufferManager中已打包数据异步发送
{
Socket handler = _session.ClientSocket;
//从缓冲区中循环读取
//while(sentSize<fileSize)
//{
byte[] data = bufferManager.GetSendBuffer();
int sSize = data.Length;//实际应该取数据有效长度,这里简单使用data.Length只为代码清晰易读
if(sSize>0)
{
//测试bufferManager类时,这里用Stream类来将数据写盘
handler.BeginSend(data, 0, data.Length, SocketFlags.None, //开始异步发送
 new AsyncCallback(sendCallback), handler);
}
sentSize += sSize;
//}
//bufferManager.SentDone = true;
}/// <summary>
/// 异步发送回调函数
/// </summary>
/// <param name="ar">包含要发送的数据流及数据包的包头</param>
private void sendCallback(IAsyncResult ar)
{
try
{
Socket socket = (Socket)ar.AsyncState; //得到包含Socket的对象
int sent = socket.EndSend(ar); if(sentSize<fileSize)//sentSize:已发送文件的字节数;fileSize:发送文件的字节长度
{
byte[] data = bufferManager.GetSendBuffer(); int sSize = data.Length;//实际应该取数据有效长度,这里简单使用data.Length只为代码清晰易读 if(sSize>0)
{
socket.BeginSend(data, 0, data.Length, SocketFlags.None, //开始异步发送
 new AsyncCallback(sendCallback), socket);
}
sentSize += sSize;
}
else
{
bufferManager.SentDone = true;
}
}
catch(Exception ex)//NullReferenceException
{
//NullReferenceException:未将对象引用设置到对象的实例。
}
}另外,服务端方面,担心短连接因频繁连接和断开影响效能,改为长连接。如一个连接
相应启动一线程,又担心线程开太多影响性能。因此,打算按用户数建Socket连接池,
同时开30个线程,将池中Socket平均分配给30个线程负责,以减少线程数、降低新建线
程和对象的开销、减轻服务器担负,提高用户体验。
大家对这种作法有什么建议和看法?

解决方案 »

  1.   

    SORRY,表述有点问题,应该是:用3个线程分别执行3个函数.线程1执行Write():读取二进制文件、线程2执行Packet():打包缓冲区待发数据、线程3执行Send():发送缓冲区已打包数据。
      

  2.   

    简单处理方法:sendCallback方法在发送数据之前,判断一下有没有数据,或者判断一下返回的数据是否为null,等于null则什么都不发送,
      

  3.   

    谢谢.这个方法偶之前考虑过了,也不是不可行,主要是bufferManager类已经做了相关的判断,而偶想要的是从线程的角度或更便于实现的方式去考虑解决这个问题.
      

  4.   

    将Send()的BeginSend改为Send,这样就好控制了。
      

  5.   

    异步发送改同步发送,就客户端而言,还是可以接受的。3个线程也都能方便的控制,之前偶就已经实现了。只是服务器改同步接收就不能接受了,况且偶用30个线程去处理N个Socket连接。解决这个异步发送问题,异步接收也就解决了。还请高人关注
      

  6.   

    Send完一个包再Send下一个包不行吗,为什么要异步?
      

  7.   

    每个线程用一个while,
    当有数据的时候才去操作,没有的时候一直循环,但是每次循环都要加适当的休眠
    取数据的时候考虑用一个公共队列,
    至少是以前是这样用过,没问题
      

  8.   

    主要是异步的问题,能贴些代码参考吗,THX.