.Net的存档

Feb
01

关于 “在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架...
作者:Qiu         没有评论

以前在网上找到的一篇c#异步socket的文章,在使用过程中老是发现消息丢失、消息被截断、串消息的问题,近日看代码时无意中发现一个重大BUG,如下:

 

/// <summary>
/// 接受数据完成处理函数,异步的特性就体现在这个函数中,
/// 收到数据后,会自动解析为字符串报文
/// </summary>
/// <param name="iar">目标客户端Socket</param>
protected virtual void ReceiveData(IAsyncResult iar)
{
Socket client = (Socket)iar.AsyncState;

try
{
//如果两次开始了异步的接收,所以当客户端退出的时候
//会两次执行EndReceive

int recv = client.EndReceive(iar);

if( recv == 0 )
{
//正常的关闭
CloseClient(client, Session.ExitType.NormalExit);
return;
}

string receivedData = _coder.GetEncodingString( _recvDataBuffer, recv );

//发布收到数据的事件
if(RecvData!=null)
{

...............................

以上代码是异步socket接收消息的方法,每个连接都会有一个线程来进行消息的接收,但是,_recvDataBuffer 却是全局变量:

/// <summary>
/// 接收数据缓冲区
/// </summary>
private byte[] _recvDataBuffer;  

如果是放在client中,那是没有问题的,我们做的程序客户端只有一个socket连接,连接到server端,所以不会有问题。但是,在server端就不行了,多个消息接收方法使用了同一个消息接收缓冲区,在多个并发下,经常发生一些不可思议的情况。

我的解决方法:

定义:

/// <summary>
/// 消息接收缓冲区列表,线程安全
/// </summary>
private Hashtable RecvDataHash = Hashtable.Synchronized(new Hashtable());

AcceptConn方法:

//定义该连接的数据接收缓冲区
byte[] myData = new byte[DefaultBufferSize];
RecvDataHash.Add(client, myData);
//开始接收
client.BeginReceive(myData, 0, myData.Length, SocketFlags.None,new AsyncCallback(ReceiveData), client);

ReceiveData方法的修改:

Socket client = (Socket)iar.AsyncState;
//获得该连接的数据接收缓冲区
byte[] mydata = RecvDataHash[client] as byte[];
string receivedData = _coder.GetEncodingString(mydata, recv);
//.....................消息处理

//继续接收
client.BeginReceive(mydata, 0, mydata.Length, SocketFlags.None, new AsyncCallback(ReceiveData), client);
 

以上修改仅供参考。

推荐(0)
收藏
Nov
24

Thread状态
作者:Qiu         没有评论

 

  public static void DumpThreadState (Thread t 
  {
    Console.Write("Current state: ");
    if ((t.ThreadState & ThreadState.Aborted== ThreadState.Aborted)
      Console.Write("Aborted ");
    if ((t.ThreadState & ThreadState.AbortRequested== ThreadState.AbortRequested)
      Console.Write("AbortRequested ");
    if ((t.ThreadState & ThreadState.Background== ThreadState.Background)
      Console.Write("Background ");
    if ((t.ThreadState & (ThreadState.Stopped | ThreadState.Unstarted | ThreadState.Aborted)) == 0)
      Console.Write("Running ");
    if ((t.ThreadState & ThreadState.Stopped== ThreadState.Stopped)
      Console.Write("Stopped ");
    if ((t.ThreadState & ThreadState.StopRequested== ThreadState.StopRequested)
      Console.Write("StopRequested ");
    if ((t.ThreadState & ThreadState.Suspended== ThreadState.Suspended)
      Console.Write("Suspended ");
    if ((t.ThreadState & ThreadState.SuspendRequested== ThreadState.SuspendRequested)
      Console.Write("SuspendRequested ");
    if ((t.ThreadState & ThreadState.Unstarted== ThreadState.Unstarted)
      Console.Write("Unstarted ");
    if ((t.ThreadState & ThreadState.WaitSleepJoin== ThreadState.WaitSleepJoin)
      Console.Write("WaitSleepJoin ");
  }

推荐(0)
收藏
Nov
10

用于IP库的二分算法
作者:Qiu         没有评论

也许存在问题吧,没经过测试

阅读全文...

推荐(0)
收藏
Jun
30

WinForm 输入法全角的问题:ImeMode的原罪
作者:Qiu         没有评论

问题:
在winform中,输入法为打开状态,切换光标所在的文本框,输入法变为全角
在网上找了半天,都是添加代码解决,经测试,无效。

原因:
查找原因的过程中,发现文本框属性 ImeMode,大部分文本框的 ImeMode为 On,难道是上一个版本的开发人员为了“易用性”而设置的?

解决:
修改为 NoControl ,问题解决。

推荐(0)
收藏
得到OpenID
使用OpenID提供商
35OpenID 35OpenID MyOpenID MyOpenID Flickr Flickr
Google Google Yahoo Yahoo! AOL AOL
Blogger Blogger LiveJournal LiveJournal Verisign Verisign
ClaimID ClaimID Technorati Technorati Vidoop Vidoop
OpenID OpenID 帮助
您还没有登录,请登录后继续操作。
提示:您必需打开Cookie才能使用本系统
请输入您的 OpenID OpenID 登录:
例如:http://yourname.openid.35.com
close