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)
收藏
Oct
26

[转]“初从文”的几个版本
作者:Qiu       没有评论

1、初从文,三年不中;后习武,校场发一矢,中鼓吏,逐之出;遂学医,有所成。自撰一良方,服之,卒。

2、初从文,三年不中;后习武,校场发一矢,中考官,乱棒逐之出; 遂学医,有所成。自撰一良方,服之,卒。后变鬼,立志列仙班,求道法,需参欢喜禅,得为神!

3、初从文,廿六乃成,负债十万。觅生计,十年无休,披星戴月秉烛达旦,蓄十万。不足购房,遂投股市,翌年缩至万余,抑郁成疾。医保曰,不符大病之条例,拒赔。乃倾其所有入院一周,无药自愈。友怜之,赊三鹿一包,冲而饮,卒。

4、80后者,初从文,未及义务教育之免费,不逮高等学校之分配,适值扩招,过五关,斩六将,硕博相继,数年乃成,负债十万。觅生计,十年无休,披星戴月,秉烛达旦,蓄十万。楼市暴涨,不足购房,遂投股市,翌年缩至万余,抑郁成疾。医保曰,不符大病之条例,拒赔。

5、初从文,不第;遂习色,三十乃成,偶得佳片一二。觅驸马,十年无休,披星戴月秉烛达旦,阅人无数,然无所获,抑郁成疾。医保曰,不符大病之条例,拒赔。乃倾其所有入院一周,无药自愈。友怜之,赊三鹿一包,冲而饮,卒。

推荐(0)
收藏
Oct
15

[已解决] DataTemplate 双向绑定必须指定Path或XPath
作者:Qiu       没有评论

问题:

在cs代码中,为TreeView添加节点,并指定了DataTemplate,提示:双向绑定必须指定Path或XPath

xaml代码如下:

        <DataTemplate x:Key="DataTemplate_Edit">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="20"></ColumnDefinition>
                    <ColumnDefinition Width="100*"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <Label></label>
                <TextBox Grid.Column="1" Text="{Binding}"  Width="100" ></TextBox>
            </Grid>
        </DataTemplate>

解决方法:

<TextBox Grid.Column="1" Text="{Binding Path=.}"  Width="100" ></TextBox>

推荐(0)
收藏
Sep
30

[SQL] 全文检查之“被忽略的词”错误
作者:Qiu       没有评论

关键字
字段名:keyword
关键字:在线客服,产品

 查询语句
select * from 文章
where 关键字!='' and CONTAINS(关键字, '在线客服)

返回结果
全文操作运行失败。查询子句只包含被忽略的词。

原因及解决
“在”属于干扰词,可以通过修改干扰词列表忽略这个字
而 sql默认没有中文(简体、繁体)干扰词列表,一般情况下windows\system32下可以找到简体、繁体中文干扰词列表
将 windows\System32\noise.chs (繁体为.cht) 复制到sql安装目录 Microsoft SQL Server\MSSQL\FTDATA\SQLServer\Config
使用记事本打开,删除“在”,重启mssqlserver服务,再次执行查询语句,成功找到数据。 阅读全文... 

推荐(0)
收藏
Sep
21

[WPF] 绑定byte[]到Image控件
作者:Qiu       评论已关闭

        private void BindPicture(Image img, byte[] bytes)
        {
            MemoryStream str = new MemoryStream(bytes);
            BitmapImage myBitmapImage = new BitmapImage();
            myBitmapImage.BeginInit();
            myBitmapImage.StreamSource = str;
            myBitmapImage.EndInit();
            img.Source = myBitmapImage;
            myBitmapImage = null;
        }

推荐(0)
收藏
Jul
19

渺小的人类,无尽的宇宙
作者:Qiu       3条评论

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018taiyangyuyizhizuidahengxingbijiao
019
020
021
022
023
024
025
026
027
028
029
030

推荐(1)
收藏
Jul
03

通过日志恢复SQL Server数据
作者:Qiu       没有评论

前提:

  1. 拥有一个完整的备份
  2. 备份后没有清理过日志

步骤:

  1. 备份日志,执行脚本
    BACKUP LOG 数据库名 TO DISK='c:database_log.bak' WITH FORMAT
    GO
  2. 还原数据库(或还原到新建的数据库),还原时选择停用数据库
  3. 还原事务到某个时间段
    RESTORE LOG 数据库名 FROM DISK='c:database_log.bak' WITH RECOVERY,STOPAT='2009-7-2 22:30:00'
    GO

ps. 还原事务超级耗时间,服务器1<4G内存>执行28G的log文件耗时3.5小时,服务器2<1G内存>执行13G的log文件,7.5个小时还没完成

推荐(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