2009-09-02

SendMessage Problem.

用CSocket编写程序,由于它不支持(或者说是很不方便)多线程,所以在工作线程中干完活之后,调用SendMessage通知窗口线程(CSocket所在的线程),在窗口线程将结果发送给服务器。没想到,这样一个问题让我困扰了两天。

程序写好后,进行压力测试。程序在小流量(100K)是表现正常,在大流量(1M)时会有丢包现象。由于服务器要同时接受来自4个客户端的消息,每一个消息包括3个数据包,每一个包设置为1M,客户端另起一个线程发送。用Timer控制,100ms的周期,所以理论上一秒将发送120M的数据,而且要开10个线程来分别发送这些消息,每一个发送12M。客户端显示发送正常,而服务器端丢包,情况不一。

首先,我认为是服务器接受的问题,查找了很久,没有发现什么问题。只能归咎于使用了CSocket + CSocketFile + CArchive架构,微软的东西很好用,但是口碑不好,网上诟病的人很多。但我一直感觉不是它们的问题;

后来,考虑是不是接收端的Buffer给快速的网络接收给冲掉了?还是不太相信,协议栈没这么脆弱。郁闷中......

今天上午准备暂且放弃这个问题,就随便看看客服端的代码。仔细检查了一下工作线程,发现有一些线程同步问题没有考虑。我有一个任务链表,在窗口线程中添加,在工作线程后完成任务后删除。感觉可能是这里出问题了,加上临界区,调试,问题还是依旧。

如是将线程函数一行一行的看了看,终于将目前聚焦到SendMessage函数上来。其实不用PostMessage函数,而用SendMessage函数是因为我需要在函数调用后做delete工作。SendMessage以前用过,直观的感觉是它是阻塞的,要到消息处理后在返回。所以感觉好像不需要同步,那么多个线程同时向一个窗口线程发送消息,情况会怎样?心理一惊,赶紧加上临界区,调试,Success!!

Oh,my god. Google吧,果然SendMessage调用窗口函数,是重入的!我的客户端在在测试时间之内,总共调用了30次SendMessage,重入的结果是客户端的输出缓冲被覆盖了。而客户端的SendMessage正常返回,所以我打印出已经发送的消息。CSocket也没有任何错误提示消息,所以让我误认为是服务器端的问题。

关于SendMessage的解释,再次认真学习,不可一知半解,呵呵。

1. 窗口函数(是个回调函数)的代码什么时候都可以被系统(调用者一般是user32模块)调用。比如在窗口过程中,向自己的窗口SendMessage(***); 那么执行过程是怎样的?我们知道,SendMessage是要等到消息发送并被目标窗口执行完之后才返回的。那么窗口在处理消息,然后又等待刚才发送到本窗口的消息被处理后之后(SendMessage返回)才继续往下执行,程序不就互相死锁了吗?其实是不会的。Windows设计一套适合SendMessage的算法,他判断如果发送的消息是属于本线程创建的窗口的,那么直接由user32模块调用窗口函数(可能就有窗口重入),并将消息的处理结果结果返回。
NOTE: 由于窗口的可重入性。在win32 SDK程序中应尽量少用全局变量和静态变量,因为在窗口函数执行过程中可能窗口重入,如果重入后将这些变量改了,但你的程序在窗口重入返回之后继续执行,可能就是使用已经改变的全局或静态变量。在MFC中(所有窗口的窗口函数基本上都是AfxWndProc),按照类的思想进行了组织,一般变量都是类中的,好管理的多。

2. PostMessage只把消息放入队列,不管其他程序是否处理都返回,然后继续执行,这是个异步消息投放函数。而sendmessage必须等待其他程序处理消息完了之后才返回,继续执行,这是个同步消息投放函数。而且,PostMessage的返回值表示postmessage函数执行是否正确;而SendMessage的返回值表示其他程序处理消息后的返回值。这点大家应该都明白。

3. 如果在同一个线程内,PostMessage发送消息时,消息要先放入线程的消息队列,然后通过消息循环Dispatch到目标窗口。SendMessage发送消息时,系统直接调用目标窗口的消息处理程序,并将结果返回。SendMessage在同一线程中发送消息并不入线程消息队列。 如果在不同线程内, 最好用PostThreadMessage代替PostMessage, 他工作的很好。SendMessage发送消息到目标窗口所属的线程的消息队列,然后发送消息的线程等待(事实上,他应该还在做一些监测工作,比如监视QS_SENDMESSAGE标志),直到目标窗口处理完并且结果返回,发送消息的线程才继续运行。这是SendMessage的一般情况,事实上,处理过程要复杂的多。比如,当发送消息的线程监测到有别的窗口SendMessage一个消息到来时,他直接调用窗口处理过程(重入),并将处理结果返回(这个过程不需要消息循环中GetMessage等的支持)。

4. 如果发送的消息码在WM_USER之下(非自定义消息)且消息参数中带有指针,那么PostMessage,SendNotifyMessage,SendMessageCallback这些异步消息发送函数将会调用失败。 最好不要用PostMessage发送带有指针参数的消息。

16 条评论:

匿名 说...

Isoncognicern http://buy-suhagra.wikidot.com http://neurontin.wikidot.com http://comprare-kamagra.wikidot.com Isoncognicern

匿名 说...

Gyperlarlibra [url=http://manatee-boating.org/members/achat-Kamagra-sans-ordonnance.aspx]Kamagra acquisto on-line safeKamagra ohne Rezept[/url] Kamagra [url=http://manatee-boating.org/members/Where--to-buy-Vicodin-ES-online-without-prescription.aspx]how long does vicodin stay in your system[/url] Vicodin ES [url=http://clr-h.jp/members/Acquisto-Kamagra-on-line-senza-ricetta.aspx]Kamagra messico[/url] Kamagra [url=http://manatee-boating.org/members/Where--to-buy-Prednisone-online-without-prescription.aspx]interaction prednisone[/url] Prednisone [url=http://boxesandarrows.com/person/100181-acquistocialissenzaricetta]cheap cialis[/url] Cialis occumbBon

匿名 说...

RaistUrifsraw [url=http://thinkmobile.it/members/Viagra-quanto-costa-in-farmacia-Compra-Viagra-in-Italia/default.aspx]buy viagra online[/url] Viagra [url=http://usr-ict.cs.unicam.it/members/Levitra-senza-ricetta-comprare-Levitra-prescrizione-medica.aspx]viagra cialis levitra[/url] Levitra [url=http://usr-ict.cs.unicam.it/members/Viagra-senza-ricetta-comprare-Viagra-prescrizione-medica.aspx]generic viagra[/url] Viagra [url=http://sicilia.tostring.it/members/Comprare-Levitra-online-senza-ricetta/default.aspx]buy levitra[/url] Levitra Illituddy

匿名 说...

RaistUrifsraw [url=http://sicilia.tostring.it/members/Comprare-Viagra-online-senza-ricetta/default.aspx]cheap viagra[/url] Viagra [url=http://thinkmobile.it/members/Cialis-quanto-costa-in-farmacia-Compra-Cialis-in-Italia/default.aspx]cheap cialis[/url] Cialis [url=http://usr-ict.cs.unicam.it/members/Kamagra-senza-ricetta-comprare-Kamagra-prescrizione-medica.aspx]farmacia Kamagra[/url] Kamagra [url=http://sicilia.tostring.it/members/Comprare-Levitra-online-senza-ricetta/default.aspx]cialis levitra[/url] Levitra mournrofemige

匿名 说...

RaistUrifsraw [url=http://thinkmobile.it/members/Kamagra-quanto-costa-in-farmacia-Compra-Kamagra-in-Italia/default.aspx]farmacia Kamagra[/url] Kamagra [url=http://sicilia.tostring.it/members/Comprare-Levitra-online-senza-ricetta/default.aspx]viagra cialis levitra[/url] Levitra MiffNeift

匿名 说...

RaistUrifsraw [url=https://launchpad.net/~buy-bactrim-without-prescription]what is bactrim[/url] Bactrim [url=https://launchpad.net/~buy-codeine-online-without-prescription]diflucan codeine[/url] Codeine [url=https://launchpad.net/~buy-ambien-without-prescription]buy ambien[/url] Ambien [url=https://launchpad.net/~buy-ativan-without-prescription]flomax ativan[/url] Ativan

匿名 说...

Aleroxyclonry [url=http://wiki.openqa.org/display/~buy-cipro-without-no-prescription-online]Buy Cipro without no prescription online[/url] [url=http://wiki.openqa.org/display/~buy-flomax-without-no-prescription-online]Buy Flomax without no prescription online[/url]

匿名 说...

私は日本語を一ヶ月習っています。 [url=http://ci2s.org/viagura.htm]バイアグラ 服用[/url] バイアグラ

匿名 说...

welches abstraktes Denken viagra bestellen viagra kaufen [url=http//t7-isis.org]cialis preis[/url]

匿名 说...

The adulthood of bloke would unquestionably bonk to enthral shield up the power to appear to mishap c keel upwards the oldest [url=http://onlineviagrapill.com]viagra[/url]. This benumb, in all chances modified to adjunct your ball, was the fluff up square-dealing a conventional [url=http://ativanpill.com]ativan[/url]. There are multifarious medial years gink, who burden with blood to the imbroglio of erectile dysfunction and the caboose range reorganize [url=http://cialis-love.com]buy cialis[/url].

匿名 说...

Don’t judge a man until you have walked a mile in his boots.

匿名 说...

[url=http://www.freewebs.com/duloxetine-online/]order cymbalta
[/url] cymbalta vs lexapro
xeristar cialis
buy generic duloxetine

匿名 说...

[url=http://amoxicilline.webs.com/]amoxicillin 500mg uk
[/url][url=http://acheter-amoxicilline.webs.com/]amoxicilline dans infection urinaire
[/url] amoxicilline kiespijn
clamoxyl grossesse
amoxicilline vidal

匿名 说...

simply stopping by to say hi

匿名 说...

[url=http://www.microgiving.com/profile/ribavirin]copegus 200 mg
[/url] purchase rebetol online
virazole 200 mg online
rebetol 200 mg

匿名 说...

[url=http://buy-methylprednisolone.webspawner.com/]methylprednisolone names
[/url] online Methylprednisolone 8 mg
medrol pack how many days
methylprednisolone tablets usp 4 mg dosage