スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

MapViewOfFileでERROR_ACCESS_DENIED

Windowsのファイルマッピングの関数のMapViewOfFileでERROR_ACCESS_DENIEDが
返ってくるので、ちょっと悩みました。


pPointer = (char*)MapViewOfFile( hMap, FILE_MAP_READ, high, low, nummap);
if (pPointer == NULL) {
DWORD err = GetLastError();
// ここでerr=5のERROR_ACCESS_DENIEDになる
}


どうやら、4Gを超えるファイルも扱えるように、high,low,nummapを設定し
細切れの範囲でMapViewOfFile()を使っていたため、
ファイルの最後に近い部分で、nummapがファイルの最後を越えてしまったようです。
どうせなら、ERROR_ACCESS_DENIEDじゃなくて、もっとすぐにわかりやすいエラーがいいな。
スポンサーサイト

テンプレートを変えてみた

テンプレートを変えてみたのですが、
右側のサイドバーが、下のフッターの途中まではみだしています。
バグなのか、設定の関係でこうなってしまったのか、
わからなかったので、調べてみたのですが、
はみ出した部分には、何も要素が見つかりません。

もしやと思い、Footerのbackgroundのurlの先をみてみると



のようになっていました。。
わざとはみだした部分が描かれていましたね。



select関数の使い方

socketからの接続や、データの受信を非同期に行うにはselectやepollを使いますが、
ここではselectについて使い方を説明します。

selectはまず、監視するファイルディスクリプタの集合を作成する必要があります。
それは

fd_set rfds;
FD_ZERO(&rfds);

のようにfd_setという型のデータを作成し、それをFD_ZEROで初期化します。
監視するデータは、read,write,exceptの3種類があるのですが、ここではreadだけを考えることにします。
このfd_set に監視するファイルディスクリプタをセットしますが、それは

FD_SET(listensock, &rfds);
FD_SET(sock1, &rfds);
FD_SET(sock2, &rfds);
・・・

のようにFD_SETを使ってセットします。

その後、

struct timeval timeout = { sec, usec };
int result = select(maxfd+1, &rfds, NULL, NULL, &timeout))

のようにして待ち受けます。
ここでsec秒とusecマイクロ秒待ち受けて何もイベントがない場合はタイムアウトとして0が戻ります。

さて、maxfdはFD_SETで監視する対象のファイルディスクリプタで、この場合は、
listensocket,sock1,socket2の中の最大のものになります。
多くのソースではselect()の最初の引数にFD_SETSIZEを指定しているものが多いですが、
FD_SETSIZEはfd_setの配列の数であってファイルディスクリプタの最大値ではないので
厳密には正しくないようですが、通常はファイルディスクリプタは0からFD_SETSIZEくらいの値になるので問題になることは少ないようです。

さて、selectで1以上の値が戻れば、応答できるファイルディスクリプタの個数がその値ということになります。
そしてそれはrfdsの中にセットされて戻ってくるので、

for (int i = 0; i <= maxfd; i++) {
if (!FD_ISSET(i, &rfds))
continue;
// ここにくるとファイルディスクリプタiについて処理ができる
if (i == listensocket) {
// accept処理
}
 else {
// read処理
}

という感じでひとつずつ調べることになります。

結局selectに渡すためのrfdsを毎回作成する必要があって、select内では渡されたファイルディスクリプタを全部調べることになり、その結果を呼び出しもとが、どのファイルディスクリプタがONになっているのかを渡したファイルディスクリプタについて全部スキャンして調べるということをしないといけないので、効率はよくない感じですね。

http://chattera.net/

Windows7 64bitのVisualC++6.0でデバッグの中止をするとプロセスが残る問題

Windows7 64bitのVisualC++6.0でデバッグの中止をするとプロセスが残るという問題があって
残ったプロセスはタスクマネージャでも終了しないので、
VisualStudioを一旦終了して再起動しないといけないという厄介なもので、
どうしたもんだろうと悩んでいたのですが、解決策がありました。

http://blog.livedoor.jp/hayaokitaro/archives/51891919.html

こちらも参考にしてください。
http://social.msdn.microsoft.com/Forums/en/vsdebug/thread/a9914982-ff0f-4981-b1f3-f0c936fec74e


これによるとDr.Hoibyという人が作ったパッチをあてたTLLOC.dllを入れ替えるといいみたいです。
適用条件はSP6があたっていることです。

試しにやってみたらちゃんとプロセスが終了してくれました。
世の中はまだVisualC++6.0を現役で使う人が多いんですね。

マイナス0

あるとき、doubleの変数をprintfしたときに、

-0

というように出力され、最初は非常に小さいマイナスの数値がこういった感じで
出力されたのかと思っていましたが、実際は違いました。
この変数を16ダンプすると
0x8000000000000000
という値になります。
これをNanやInfの一種かとも思ったのですが、れっきとしたマイナス0という数値なんですね。
IEEE754では64bitの浮動小数点は、

  1. 1bitの符号

  2. 11bitの指数部

  3. 52bitの仮数部


からなるとしていて、
マイナス0の数の場合は、符号がマイナスで指数部と仮数部が共にゼロという感じですね。
ちなみに、プラスゼロはすべてのBitがゼロです。

あと、どのようにしてこのデータがつくられたんだろうと思っていたのですが、

double v = -1.0*0.0;

で簡単に作ることができました。

http://chattera.net/

doubleの非数値

VCのdoubleで非数値の時にどういうbitになっているのかを調べてみました。


#include <ymath.h>


で定義されている5つの値
_Denorm, _Hugeval, _Inf, _Nan, _Snan
をダンプしてみました。
その結果が







_Nan._D-1.#IND0xfff8000000000000
_Inf._D1.#INF0x7ff0000000000000
_Denorm._D4.94066e-3240x0000000000000001
_Hugeval._D1.#INF0x7ff0000000000000
_Snan._D-1.#INF0xfff0000000000000


のようになります。
面白いものですね。

selectとepollの違い

ここのチャットサーバはsocketのIOを行うために、selectまたはepollを使っています。
実際はコンパイルオプションでどちらかにするかを決めているのですが、
epollの方が速いので実質的にはepollを使っていることになります。

さて、selectとepollの違いですが以下のような感じです。

select


selectは以前のkernelから実装されている方式で、アプリケーションに呼ばれる度に監視下のディスクリプタセットをkernelに渡し、kernelは渡されたリストに対しstateを更新して送り返します。送り返されたディスクリプタからready状態のディスクリプタをピックアップするためにアプリケーションはファイルディスクリプタを一つ一つ見に行かないといけないため、O(n)の計算量が必要となります。そのため、管理するファイルディスクリプタの数が増えるとパフォーマンスが落ちます。また管理できる数が限られているため、その数を超えるときには利用できません。

epoll


Linux Kernel 2.6から追加された方式で、ディスクリプタのstateがkernel内で管理されます。select(2)やpoll(2)の様に呼ばれる度にディスクリプタセットをkernelに送る必要もなく、無駄にディスクリプタセットをループする必要がなくなります。またkernelが管理しているので、変わったものに対して通知できるので、kernelの負担を下げることになります。O(1)の計算量で計算できるようです。

こういった特徴からepollが多く使われているようです。

http://chattera.net/

プログラムでモニターの電源をOFFにする

余談ですが、いままでPCを離れるときに、モニターの電源を切っていたのですが、
うちのPCのモニターの電源スイッチの反応が悪くなったので、
プログラムで無操作時のモニター電源OFFができないものかと探していたら
こちらのページにありました。

ディスプレイの電源を切る方法

バイナリもおいてありますが、動作の仕組みとソースもあります。
それによると、
HWND_BROADCASTを使ってWM_SYSCOMMANDメッセージをwp=SC_MONITORPOWER, lp=1 とlp=2で2回ポストするとできるそうです。


#include <windows.h>
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd )
{
Sleep(1000);
PostMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, 1) ;
Sleep(100);
PostMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, 2) ;
return 0;
}


へ~という感じですね。

チャットサーバのsocket

チャットのシステムはsocketで接続していますので、チャットサーバは多くのチャットクライアントからの接続を待ち受けるサーバ型のsocketとして動作しないといけないです。
これをC言語で作成しているのですが、その方法について記述します。
(ある種備忘録的なものです)

サーバ型のsocketの作成方法は

  1. socket()関数でPF_INET, SOCK_STREAM, IPPROTO_TCPを指定して待ち受け用のsocketハンドルを作成する。

  2. fcntl()関数でF_SETFL, O_NONBLOCKを指定して、そのsocketハンドルをブロッキングしないモードにする。

  3. struct sockaddr_in bind_addressの構造体に、待ち受けのポート番号を指定して、bind()関数を呼び出し、待ち受けの指定をする。

  4. listen()関数を呼び出し、待ち受けを開始する。


という順番ですね。
以下で使っているsetsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &trueval, sizeof(trueval)は
前回システム終了時から再起動の間隔が短くて、待ち受けのポートがまだ開いてない場合でも
そのポートを再利用できるようにするというおまじないです。
これらをまとめるとソースは以下のような感じになります。


int fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fd == -1) {
printerror("socket %s", strerror(errno));
exit(1);
}

struct sockaddr_in bind_address;
memset(&bind_address, 0, sizeof(bind_address));
bind_address.sin_family = AF_INET;
bind_address.sin_addr.s_addr = INADDR_ANY;
bind_address.sin_port = htons(port);
if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
printerror("O_NONBLOCK %s", strerror(errno));
exit(1);
}
int trueval = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &trueval, sizeof(trueval)) == -1) {
printerror("setsockopt SO_REUSEADDR %s", strerror(errno));
exit(1);
}
if (bind(fd, (struct sockaddr *) &bind_address, sizeof(bind_address)) == -1) {
printerror("bind %s", strerror(errno));
exit(1);
}
if (listen(fd, backlog) == -1) {
printerror("bind %s", strerror(errno));
exit(1);
}


この後に、実際に待ち受けのsocketに接続が行われたときの処理を行うのですが、
その処理は、すでに接続してあるsocketからデータが送られてきた場合と非同期に発生するので
一つの関数で何が起こったかを調べることになります。
ここのチャットサーバでは、その関数にselect()という関数とepoll()という関数の2種類を使えるようにしています。

(続く)

http://chattera.net/

WordPressのページごとのリクエスト

WordPressでは、リクエストが行われるごとに、そのページで使うであろう情報をSQLで取ってきて
そのページに即したテンプレートを使って表示するということをしているみたいですね。
そこで、どのテンプレートからでも呼ばれるheader.phpに

</div>
request:<?php print_r($wp_query->request);?><br>
found_posts:<?php print_r($wp_query->found_posts);?><br>
</div>

を入れてみると、どのページでも、そこで使われたSQLと、結果の件数が表示されます。
例えばブログの一覧ページだと

request:SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts
WHERE 1=1 AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
ORDER BY wp_posts.post_date DESC LIMIT 0, 5
found_posts:14

ブログの個別ページだと

request:SELECT wp_posts.* FROM wp_posts
WHERE 1=1 AND wp_posts.ID = 126 AND wp_posts.post_type = 'post'
ORDER BY wp_posts.post_date DESC
found_posts:1

固定ページだと

request:SELECT wp_posts.* FROM wp_posts
WHERE 1=1 AND (wp_posts.ID = '23') AND wp_posts.post_type = 'page'
ORDER BY wp_posts.post_date DESC
found_posts:1

のようになります。
これを眺めていると、WordPressがMySQLのDBにどんな感じで記事を格納していて、どうやって検索し、どうやって表示しようとしているか、垣間見れる気がして面白いですね。

WP-PageNaviとWp Pagenavi Styleのプラグイン

WP-PageNaviとWp Pagenavi Styleのプラグインをインストールしてみました。
WP-PageNaviはサイトの下によくあるページ移動ができるナビゲーションです。
Wp Pagenavi StyleはWP-PageNaviをあらかじめ用意してあるスタイルから選べるようになっている
プラグインです。
結構簡単にかっこいいページナビができますね。

使い方は簡単で、ページナビを入れたい部分に

<?php wp_pagenavi(); ?>

を入れます。

見た目はこんな感じです。
WP PageNavi Sample

でもWP-PageNaviはsingleのページには配置しても表示されませんね。
そういうものなんですかね。
このあたりはもっと研究してみないとわかりません。

http://chattera.net/
http://chattera.net/chaberilist.php

SyntaxHighlighterを使ったソース表示

SyntaxHighlighterを使ってソースをきれに表示する方法をやってみました。
直前の記事はこれを使って表示してみました。

これは備忘録です。

まず
http://alexgorbatchev.com/SyntaxHighlighter/
から最新版をダウンロードして、解凍する。
この記事を書いた時点ではバージョンは3.0.83なので
今後バージョンがかわると、方法も変わるかもしれないので注意。

FC2の管理画面の、ツールのファイルアップロードで
styles/shCore.css
をアップロードする。

つづいて
scripts/shCore.js
と、使いそうな言語のscript/shBrushXXX.js
をいくつかアップロードする。

次にテンプレートの設定画面からHTMLを編集する。
HTMLはheadの中に
<link href="http://blog-imgs-56.fc2.com/c/h/a/chattera/shCoreDefault.css" type="text/css" rel="stylesheet">

を記述し
bodyの中に
<script type="text/javascript" src="http://blog-imgs-56.fc2.com/c/h/a/chattera/shCore.js"></script>
<script type="text/javascript" src="http://blog-imgs-56.fc2.com/c/h/a/chattera/shBrushPhp.js"></script>
<script type="text/javascript" src="http://blog-imgs-56.fc2.com/c/h/a/chattera/shBrushXml.js"></script>
<script type="text/javascript" src="http://blog-imgs-56.fc2.com/c/h/a/chattera/shBrushSql.js"></script>
<script type="text/javascript" src="http://blog-imgs-56.fc2.com/c/h/a/chattera/shBrushPerl.js"></script>
<script type="text/javascript" src="http://blog-imgs-56.fc2.com/c/h/a/chattera/shBrushJScript.js"></script>
<script type="text/javascript" src="http://blog-imgs-56.fc2.com/c/h/a/chattera/shBrushJava.js"></script>
<script type="text/javascript" src="http://blog-imgs-56.fc2.com/c/h/a/chattera/shBrushCss.js"></script>
<script type="text/javascript" src="http://blog-imgs-56.fc2.com/c/h/a/chattera/shBrushCpp.js"></script>
<script type="text/javascript" src="http://blog-imgs-56.fc2.com/c/h/a/chattera/shBrushBash.js"></script>
<script type="text/javascript">SyntaxHighlighter.all();SyntaxHighlighter.config.bloggerMode = true;</script>

をいくつか記述する。
パス中の「blog-imgs-56.fc2.com/c/h/a/chattera」ここのブログのパスなので各自にあわせて修正する。
最後の行の、SyntaxHighlighter.config.bloggerMode = true;がないと一行になってしまい、
BRもつくのでみにくくなってしまう。

記事を書く際には

<pre class="brush: java;">
javaコード
</pre>

のようにclassで言語を指定する。指定できるものは大体言語名を小文字にしたものであるが
http://alexgorbatchev.com/SyntaxHighlighter/manual/brushes/
に細かくのっている。

またpreの中はエスケープしないといけないが、個別にかきかえるのは面倒なので
http://www.mapee.jp/tools/pretagmaker/
というような便利なサイトを使うとよい。

WordPressに自動投稿

せっかくなので、WordPressに自動投稿するスクリプトがあったのでやってみました。
以下のような感じです。
ただしこれは文字化けするんですね。


<?php
require_once("XML/RPC.php"); //XML-RPC package
$GLOBALS['XML_RPC_defencoding'] = "UTF-8";
$wp_blogid = "";
$wp_host = "www.example.com";
$wp_xmlrpc_path = "/wordpress/xmlrpc.php";
$wp_user = "user";
$wp_passwd = "pass";
$kiji_mode = 0;
$kiji_title = "WordPress Auto Post Title";
$kiji_honbun = "WordPress Auto Post Contents.<br /><br /><br />";

$bm = new BlogManager();
$bm->post_blog($kiji_mode,$kiji_title,$kiji_honbun);
class BlogManager {
function post_blog($kiji_mode,$kiji_title,$kiji_honbun) {
global $wp_blogid,$wp_xmlrpc_path,$wp_host,$wp_user,$wp_passwd;
echo "XML_RPC_client\n";
$c = new XML_RPC_client( $wp_xmlrpc_path, $wp_host, 80 );
$blogid = new XML_RPC_Value($wp_blogid, 'string');
$username = new XML_RPC_Value($wp_user, 'string');
$passwd = new XML_RPC_Value($wp_passwd, 'string');
$content = new XML_RPC_Value(array(
'title' => new XML_RPC_Value($kiji_title, 'string'),
'description'=> new XML_RPC_Value($kiji_honbun, 'string'),
'dateCreated'=> new XML_RPC_Value(date("Ymd\TH:i:s",time()), 'dateTime.iso8601')
), 'struct');
$publish = new XML_RPC_Value($kiji_mode, 'boolean');
$message = new XML_RPC_Message('metaWeblog.newPost',array($blogid, $username, $passwd, $content, $publish) );
$this->send_message($c,$message);
}
function send_message($c,$message){
echo "send";
$result = $c->send($message);
if( !$result ){
exit('Could not connect to the server.');
}else if( $result ->faultCode() ){
exit('XML-RPC fault ('.$result ->faultCode().'): '
.$result ->faultString());
}
return $result ;
}
}
?>


いろいろ探してみたら、class-IXR.phpというのを使った文字化けしないスクリプトがありました
こんな感じです。



<?php
/*wp-includesからファイルをコピペ*/
require_once("class-IXR.php");

$host = "http://example.com/wordpress";
$base_uri = $host. "/xmlrpc.php";
$encoding = 'UTF-8';
$method = 'metaWeblog.newPost';//wp.newPostは動きませんでした
$title = "自動投稿 タイトル";
$description = "自動投稿 本文";
$user = 'user';
$pass = 'pass';
$params = array(1,
$user,
$pass,
array(
"title" => $title,
"description" => $description,
),
1,
);
$client = new IXR_Client($base_uri);

if (!$client->query($method, $params)) {
echo $client->getErrorCode().":".$client->getErrorMessage()."\n";
exit();
}
?>



これをつかって、なにかやってみようかな。

http://chattera.net/
http://chattera.net/chaberilist.php



WordPressをインストールしてみた

せっかくPHPを5.3にしたので、WordPress3.5をインストールしてみました。

まず、mysqlがインストールされていなかったので、mysqlからですが、
yum -y install mysql-server
で簡単にインストール完了。
WordPress用のデータベースもcreatedatabaseですぐにできました。

WordPressもzipで取得したものを解凍してインストール完了です。
いろいろいじっていて、なかなか面白いですが、
まだ公開できるようなものはできてないので、
面白いのができれば公開してみたいと思います。

http://chattera.net/
プロフィール

chattera.net

Author:chattera.net
フリーでソフト開発の仕事をしています。
自作したこのチャットシステムは、何か世の中に役に立つこともあるかと思いますので、お呼びがかかるとうれしいですね。

連絡先は chatteranet@gmail.com です。

また、ソフト開発関連のお誘いもうけたまわっております。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。