VB.NETでNTPサーバから時刻を取得する

VB.NETでNTPサーバから時刻を取得する方法を説明します。

NTPサーバは適当なところを選んでください。
ポート123 UDPでNTPパケットを送信して、レスポンスを受け取ります。
40から43バイト目が世界協定時になっています。
これは、1900/01/01からの秒数になっていると思われます。
それを元に現在の時刻を取得します。

これを使うと、コンピュータのシステム時刻にかかわりのない時計を作ることができます。

以下がソースコードです。



Dim sNTPServer As String
Dim btNTP_Packet(47) As Byte
Dim btRecv(50) As Byte
Dim strRetPage As String = Nothing
Dim objHost As System.Net.IPAddress
Dim objIPEndPoint As System.Net.IPEndPoint
Dim objSocket As System.Net.Sockets.Socket

'NTPサーバ
sNTPServer
objHost = System.Net.Dns.Resolve(sNTPServer).AddressList(0)
'ポートは123でUDP
objIPEndPoint = New System.Net.IPEndPoint(objHost, 123)
objSocket = New System.Net.Sockets.Socket( _
System.Net.Sockets.AddressFamily.InterNetwork, _
System.Net.Sockets.SocketType.Dgram, _
System.Net.Sockets.ProtocolType.Udp)
'接続
objSocket.Connect(objIPEndPoint)
If objSocket.Connected = False Then
MessageBox.Show("接続できません。")
Exit Sub
End If
'NTPパケット
'最初は11 後は0
btNTP_Packet(0) = &HB
'NTPパケットを送信
objSocket.Send(btNTP_Packet)
'受信
objSocket.Receive(btRecv)
objSocket.Close()

Dim dteUTC As Date
Dim dteNow As Date
Dim decUTC As Decimal
Dim decDay As Decimal
Dim decHour As Decimal
Dim decMinute As Decimal
Dim decSec As Decimal

'世界協定時
'1900/01/01からの秒
decUTC = CDec(btRecv(40)) * 2 ^ (8 * 3) _
+ CDec(btRecv(41)) * 2 ^ (8 * 2) _
+ CDec(btRecv(42)) * 2 ^ 8 _
+ CDec(btRecv(43))

'1900/01/01からの日にちを計算
decDay = decUTC \ (24 * CLng(60 * 60))
decSec = decUTC Mod (24 * CLng(60 * 60))
'時
decHour = decSec \ (60 * 60)
decSec = decSec Mod (60 * 60)
'分
decMinute = decSec \ 60
'秒
decSec = decSec Mod 60

dteUTC = DateAdd(DateInterval.Day, decDay, CDate("1900/01/01"))
dteUTC = DateAdd(DateInterval.Hour, decHour, dteUTC)
dteUTC = DateAdd(DateInterval.Minute, decMinute, dteUTC)
'現在の時刻
dteNow = dteUTC.ToLocalTime

posted by VB.NET+MSDE+ActiveReports at 14:33 | Comment(0) | TrackBack(21) | ネットワーク

net timeでエラー

net timeコマンドで、LAN内のPCと時刻同期をする時にエラーになることがあります。

確認する点は2点です。
ファイアーウォールの設定と共有フォルダです。

まず、システムエラー53が発生しました。 ネットワークパスが見つかりません。
と表示される場合は、ファイアーウォールが有効になっていて、
例外の「ファイルとプリンタの共有」にチェックが入っていません。

この場合は、「ファイルとプリンタの共有」にチェックをいれてください。

しかし、この設定を変えても、
システムエラー5が発生しました。
アクセスが拒否されました。
というエラーが出ることがあります。
これは、ファイアーウォールを無効にしても、同じエラーがでます。
この場合、一旦、時刻を合わせたいPCに共有フォルダを作成すると、
net timeコマンドが使用可能になります。
さらに、その後で、共有を解除しても大丈夫です。

この状態で、ファイアーウォールを有効な状態で「ファイルとプリンタの共有」のチェックをはずしすと、また、システムエラー53が発生します。
posted by VB.NET+MSDE+ActiveReports at 15:14 | Comment(0) | TrackBack(0) | ネットワーク

再起動しないでIPアドレスを再取得する

IPアドレスを自動取得にしておくと、
接続先のルーターを切り替えた場合、
サブネットが違うので、インターネットや
ローカルエリアのネットワークに接続できなくなります。
放置しておくと、いつの間にか
新しいIPアドレスを取得していることもありますが、
ルーターを差し替えて、すぐにネットワークに接続したいのなら、
コンピュータを再起動するか、固定IPの設定をすることになり、
面倒です。



「ローカル エリア接続のプロパティ」を変更する[1]





「ローカル エリア接続のプロパティ」を変更する[2]


で書いた方法でも簡単にIPアドレスを変更することは出来ますが、
これらは、固定IPの設定の場合です。

今回は自動取得の設定のまま、なんとかする方法です。

スタート→すべてのプログラム→
アクセサリ→コマンド プロンプト
で ipconfig/release と入力しEnter
これで一旦、IPアドレスが解放されます。
次に、 ipconfig/renew と入力しEnter
以上で、新しいIPアドレスが取得でき、インターネットや
ローカルエリアのネットワークにも接続できます。
posted by VB.NET+MSDE+ActiveReports at 16:59 | Comment(0) | TrackBack(0) | ネットワーク

VB.NETでPOSTを連続して行うと失敗する

VB.NETでPOSTやPUTを連続して行うと失敗することがあります。
VB.NETでPOSTにより、データを送受信するためには、
HttpWebRequestとHttpWebResponseを使います。
その方法のソースコードは、いろいろなところで紹介されています。
実際に、それらのソースコードを利用して、プログラムをすれば、うまくいきます。
しかし、環境によりうまくいかない場合があります。

具体的には、2度目の、WebRequest.GetRequestStreamのところで、固まってフリーズしたようになって、しばらくするとタイムアウトエラーが出てしまいます。
そのため、複数のファイルを順次アップロードする処理がうまくいきません。
私が実際になってしまったのは、WindowsXP Home SP2に.Net Framework2.0がインストールされているときで、.Net Framework2.0をアンインストールしたら治ってしまいました。
もう1つダメだったのは、Windows Vista Businessです。
しかし、WindowsXP Pro SP2で.Net Framework2.0がインストールされている環境で大丈夫だったこともあるので、何が問題なのかわかりません。

いろいろ検索していたら、うまくいく方法を見つけました。
それは、WebRequestをAbortすることです。
WebRequestをAbortしないと、何かを占有しているために、
新たに、GetRequestStreamが出来ずに固まるようです。

こんな感じです。

Dim sURI As String
Dim objReq As WebRequest
'データをバイト配列に変換したもの
Dim bytePost As Byte()
Dim objStream As Stream

'Requestオブジェクトを作成
objReq = WebRequest.Create(sURI)
objReq.Method = "POST"
objReq.ContentType = "application/x-www-form-urlencoded"
objReq.ContentLength = bytePost.Length
objStream = objReq.GetRequestStream
objStream.Write(bytePost, 0, bytePost.Length)
objStream.Close()
'ここでAbortする
objReq.Abort()
posted by VB.NET+MSDE+ActiveReports at 18:24 | Comment(0) | TrackBack(0) | ネットワーク

Windows Vistaでリモートデスクトップ接続の設定をする

Windows Vistaには、4つのエディションがあります。
Windows Vista Home Basic、Windows Vista Home Premiumは
リモートデスクトップはクライアントの機能のみで、
Windows Vista Business、Windows Vista Ultimateの場合に
リモートアクセスが可能になります。

スタート→コントロールパネル→リモート アクセスの許可で
リモート デスクトップを実行しているコンピュータからの
接続を許可するを選択します。

接続するユーザーは、クライアント側にも同じユーザーを
作らないとうまくいかないかもしれません。

セキュリティのことを考えると、リモート デスクトップのリッスンポートを
変更しておいた方が良いです。

「リモートデスクトップ接続のTCPポート変更」

Windows Vistaの場合、レジストリエディタは、
スタートをクリックして、検索の開始のところに、
regeditと入力して、虫眼鏡をクリックします。

レジストリの設定を変えてから、再起動しないと、
リッスンポートの設定が変わらないようです。
さらに、ファイアウォールの設定で、該当するポートを開ける必要があります。

スタート→コントロールパネル→Windows ファイアウォールによるプログラムの許可

すでに「リモートデスクトップ」という項目がありますが、
リッスンポートを変えるとダメなので、ポートの追加で
適当な名前をつけて、ポート番号を入力し、TCPにチェックを入れてOKを押します。
posted by VB.NET+MSDE+ActiveReports at 15:06 | Comment(0) | TrackBack(0) | ネットワーク

pingが通らない(ファイアーウォールの設定)

WindowsXPで、pingが通らないことがあります。
他のPCに対して、ping送信すると、応答が帰ってくるのに、
他のPCからping送信すると、レスポンスがない。
ファイアーウォールをOFFにすると、pingが通るようになって、
ファイアーウォールをONにすると、pingが通らなくなるということがあります。

IPアドレスを自動取得にしているのがいけないのかと思って、
固定IPにして、DMSサーバも正しく設定してみてもだめです。
ファイアーウォールをOFFにすると、pingが通るようになって、
ファイアーウォールをONにすると、pingが通らなくなるということは、
どう考えても、ファイアーウォールの設定です。

こんな現象が起きている場合は、
ファイアーウォールの設定で、
詳細設定タブ→ローカルエリア接続を選択→
ICMPの設定→エコー要求の着信を許可するにチェック→OK
と設定します。
以上のように設定すれば、pingが通るようになります。
ただ、設定してなくてもpingが通るようになっていることがほとんどです。

自分でOSをインストールしたときは、最初からping出来ますが、
OSがインストール済みのパソコンを買うと、たまに
このようにpingが通らなくなっていることがあります。

posted by VB.NET+MSDE+ActiveReports at 00:41 | Comment(0) | TrackBack(0) | ネットワーク

YahooやGoogleで時刻同期する


NTPサーバを使用して、時刻同期を使用としても、
エラーになって同期できないことがあります。
特に、日付と時刻のプロパティの
インターネット時刻で時刻合わせを使用とすると、
たいていエラーになってしまいます。

それなら、NTPサーバで時刻同期をするのをやめて、
他のところと時刻を合わせればよいです。
YahooやGoogle、MSNなど安定してアクセス可能な
Webページにアクセスして、そこから時刻を取得します。
時刻はHTTPヘッダにのってきます。


        'URL
        Dim sURL As String
        '日付の文字列
        Dim sDate As String
        '日付
        Dim dteDate As Date
        Dim objReq As HttpWebRequest
        Dim objRes As HttpWebResponse
        '試しにYahoo Japanでやってみる。
        sURL = "http://www.yahoo.co.jp/"

        'Webページを取得
        objReq = CType(WebRequest.Create(sURL), HttpWebRequest)
        objRes = CType(objReq.GetResponse(), HttpWebResponse)

        'ヘッダ情報から日付を取得
        sDate = objRes.Headers("Date")

取得した時刻はGMT(グリニッジ標準時)です。
日本の場合は、時差は9時間です。

posted by VB.NET+MSDE+ActiveReports at 03:09 | Comment(0) | TrackBack(0) | ネットワーク

netコマンドが使えない


コマンドプロンプトで、
net start MSSQLSERVER
と入力して、Enterを押すと、

なぜか、

'net' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

と、エラーになってしまうことがあります。
この場合、普通はシステム環境変数を確認します。

マイコンピュータを右クリック

プロパティ

詳細設定

環境変数
で、システム環境変数の Path をダブルクリックし、
変数値に %SystemRoot%;%SystemRoot%\System32;%SystemRoot%\System32\Wbem
を追加してOKを押します。

しかし、システム環境変数が正しいのに、netコマンドがエラーになることがあります。
その場合は、net.exeが存在しない場合があります。
WindowsXPの場合は、C:\WINDOWS\system32に
net.exeとnet1.exe があります。
それらがなくなっている場合、他のコンピュータからコピーするとなおります。
これは、あくまでやってみたらうまくいったという程度の話です。
どうにも困っている場合は、役に立つかもしれません。

posted by VB.NET+MSDE+ActiveReports at 18:41 | Comment(0) | TrackBack(0) | ネットワーク

「ローカル エリア接続のプロパティ」を変更する[2]

固定IPの設定を切り替えて使いたいときに
「ローカル エリア接続のプロパティ」を
変更するのは面倒です。

前回は設定を保存したファイルを
バッチファイルで呼び出しました。
↓↓↓↓↓
「ローカル エリア接続のプロパティ」を変更する[1]

今回はバッチファイルそのものに設定内容を書き込んで実行します。

ファイルの内容は以下の通りです。

netsh interface ip set address name = "ローカル エリア接続" source = static addr = aaa.aaa.aaa.aaa mask = bbb.bbb.bbb.bbb[改行]
netsh interface ip set address name = "ローカル エリア接続" gateway = ccc.ccc.ccc.ccc gwmetric = 1[改行]
netsh interface ip set dns name = "ローカル エリア接続" source = static addr = ddd.ddd.ddd.ddd[改行]
netsh interface ip add dns name = "ローカル エリア接続" addr = eee.eee.eee.eee index=2[改行]

aaa.aaa.aaa.aaa はIPアドレス
bbb.bbb.bbb.bbb はサブネットマスク
ccc.ccc.ccc.ccc はデフォルトゲートウェイ
ddd.ddd.ddd.ddd は優先DNSサーバー
eee.eee.eee.eee は代替DNSサーバー
を入力してください。

代替DNSサーバーがない場合は、4行目を削除してください。

posted by VB.NET+MSDE+ActiveReports at 16:17 | Comment(0) | TrackBack(0) | ネットワーク
固定IPの設定を切り替えて使いたいときに
「ローカル エリア接続のプロパティ」を
変更するのは面倒です。

Windows 2000/XPでは、netshコマンドというものがあります。

現在の「ローカル エリア接続のプロパティ」の設定を保存するには、
コマンドプロンプトで、

C:\>netsh -c interface dump > 任意のファイル名

です。

上で指定したファイル名で設定が保存されます。
出来る場所は、C:\Documents and Settings\ユーザー名
です。

保存した設定に変更するには、

C:\>netsh -c interface dump > 設定を保存したファイル名

これをバッチファイルにして使えば、簡単に切り替えることができます。

posted by VB.NET+MSDE+ActiveReports at 08:31 | Comment(0) | TrackBack(0) | ネットワーク

LANでサーバーPCと時刻同期する

LANでサーバーPCと時刻同期する方法を3つ考えました。

1、コマンドプロンプトで net time を使う。

        Dim sPCName As String
        Shell("cmd.exe /C ""net time \\" & sPCName & " /set /yes""", AppWinStyle.Hide)


2、NetRemoteTODでサーバーPCの時刻を取得し、
  その時刻にあわせる。

NetRemoteTODでサーバーPCの時刻を取得する

3、共有フォルダにファイルを作成して、
  そのタイムスタンプをみてあわせる。

2と3は時刻を取得した後、

        Dim dteServerTime As Date
        Microsoft.VisualBasic.TimeString = Format(dteServerTime, "HH:mm:ss")

posted by VB.NET+MSDE+ActiveReports at 10:43 | Comment(0) | TrackBack(0) | ネットワーク

VB.NETでWake On LAN

パソコンの電源を入れたいときは
マジックパケットをブロードキャストすれば良いです。

マジックパケットと言っても、
&HFF を6回
MACアドレスを16回
送信するだけです。


        Dim sMac As String 'マックアドレス
        Dim btPacket() As Byte = New Byte(17 * 6 - 1) {} '送出するパケット
        Dim sMacArray(5) As String 'マックアドレス
        Dim btMac(5) As Byte
        Dim iCounter As Integer
        Dim iMacCounter As Integer
        Dim objeClient As New System.Net.Sockets.UdpClient()

        'マックアドレスを1バイトずつに分ける================
        sMacArray(0) = sMac.Substring(0, 2)
        sMacArray(1) = sMac.Substring(2, 2)
        sMacArray(2) = sMac.Substring(4, 2)
        sMacArray(3) = sMac.Substring(6, 2)
        sMacArray(4) = sMac.Substring(8, 2)
        sMacArray(5) = sMac.Substring(10, 2)
        For iCounter = 0 To 5
            btMac(iCounter) = Long.Parse(sMacArray(iCounter), Globalization.NumberStyles.HexNumber)
        Next
        'パケットヘッダ &HFF を6回 =========================
        For iCounter = 0 To 5
            btPacket(iCounter) = &HFF
        Next
        'MACアドレスを16回 ================================
        For iCounter = 1 To 16
            For iMacCounter = 0 To 5
                btPacket(iCounter * 6 + iMacCounter) = btMac(iMacCounter)
            Next
        Next
        'なぜ、ポートが40000なのか忘れました=================
        objeClient.Connect(Net.IPAddress.Broadcast, 40000)
        'パケットをブロードキャスト==========================
        objeClient.Send(btPacket, btPacket.Length)

posted by VB.NET+MSDE+ActiveReports at 17:30 | Comment(2) | TrackBack(0) | ネットワーク