ネットワークプログラミング Python

ネットワークプログラミングメモ

netaddr ライブラリ

とりあえずインストール

sudo pip install netaddr

そして、

>>> from netaddr import IPNetwork
>>> for i in IPNetwork("192.168.0.0/24"):
...     print i
... 
192.168.0.0
192.168.0.1
192.168.0.2

〜省略〜

192.168.0.254
192.168.0.255

わりと便利。

TCPクライアント

# coding: utf-8

import socket

target_host = '0.0.0.0'
target_port = 1234

# ソケットオブジェクトの生成
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

# サーバへの接続
client.connect((target_host,target_port))

# データの送信
client.send("SYN!")

# データの受信
response = client.recv(4096)

print response

TCPサーバ

# coding: utf-8

import socket
import threading

bind_ip = "0.0.0.0"
bind_port = 1234

# ソケット作成
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

# Bind
server.bind((bind_ip,bind_port))

# Listen
server.listen(3)

print "Listening on %s %d" % (bind_ip,bind_port)

# クライアントからの接続を処理するスレッド
def handle_client(client_socket):

    # クライアントが送信してきたデータを表示
    request = client_socket.recv(1024)
    print "[*] Recieved %s" % request

    # パケットの返送
    client_socket.send("ACK!")

    client_socket.close()

while True:

    client, addr = server.accept()

    print "Accepted connection from %s:%d" % (addr[0],addr[1])

    # 受信データを処理するスレッドの起動
    client_handler = threading.Thread(target=handle_client,args=(client,))
    client_handler.start()

UDPクライアント

# coding: utf-8

import socket

target_host = 'www.google.com'
target_port = 80

# ソケットオブジェクトの生成
client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

# データの受信
client.sendto("AAABBBCCC",(target_host,target_port))

# データの受信
data, addr = client.recvfrom(4096)

print data

参考文献ではスキャナーとかのプログラムが紹介されてておもしろかった。

参考文献

サイバーセキュリティプログラミング ―Pythonで学ぶハッカーの思考

サイバーセキュリティプログラミング ―Pythonで学ぶハッカーの思考

指定ディレクトリ以下の画像ファイル名を再帰的にすべて取得するプログラム (Ruby)

http://carumisu.hatenablog.com/entry/2015/11/03/201748Ruby版。

require "find"
require 'rubygems'
require 'RMagick'

def GetImageList(mydir)
    imageList = []
    Find.find(mydir) do |f|
        if File::ftype(f) == "file"
            begin
                Magick::Image.read(f).first.format
                imageList.push(f)
            rescue
            end
        end
    end
    return imageList
end

def CopyResizedImage(imgList,path)
    a = 0
    imgList.each do |imgPath|
        img = Magick::Image.read(imgPath).first
        img.resize_to_fit(64,64).write(path+"/#{a}.jpg")
        a+=1
    end
end

list = GetImageList(".")
CopyResizedImage(list,"./test")

指定ディレクトリ以下の画像ファイル名を再帰的にすべて取得するプログラム (Python)

os.walkを使えば再帰的にディレクトリ探索ができる.

「今調べている最中のディレクトリ名」「見つかったディレクトリのリスト」「見つかったファイルのリスト」を返すらしい(参考文献より)。

# coding: utf-8
import os,imghdr,shutil

def get_image_list(path):
    file_list = []
    for (root, dirs, files) in os.walk(path): # 再帰的に探索
        for file in files: # ファイル名だけ取得
            target = os.path.join(root,file).replace("\\", "/")  # フルパス取得
            if os.path.isfile(target): # ファイルかどうか判別
                if imghdr.what(target) != None : # 画像ファイルかどうかの判別
                    file_list.append(target) # 画像ファイルであればリストに追加
    return file_list

def copy_list_into_dir(file_list,dir_path):
    num = 0
    for file_name in file_list:
        shutil.copyfile(file_name,dir_path+"/"+str(num)) # testディレクトリにコピー
        num += 1

if __name__ == "__main__":
    image_list = get_image_list(".") # 画像ファイル名のリスト取得
    copy_list_into_dir(image_list,"./test") # すべてtestディレクトリにコピー

参考文献がとても参考になりました。感謝です。

参考文献

145:ディレクトリ内のファイルを再帰的に処理

NTFSの複数のデータランの先頭アドレスの算出

NTFSでは、MFTレコードにファイルのメタデータを格納していく。 そこに、ファイルのデータ本体の場所の先頭アドレスを示すパラメータがある。

ファイルがフラグメントを起こしてしまうと複数のデータランで構成されてしまう。 そのデータランの内の「ファイルの先頭アドレス」を表すパラメータの計算方法のメモが以下。

計算方法

パラメータの値のMSBが0の場合は、1つ前のデータラン内の「ファイルの先頭アドレス」にそのまま足しこむ。

今回出したいアドレス = 1つ前のデータラン内の「ファイルの先頭アドレス」 + パラメータの値

パラメータの値のMSBが1の場合は、パラメータの値をビット反転してから、1つ前のデータラン内の「ファイルの先頭アドレス」からその反転後の値を引く。

今回出したいアドレス = 1つ前のデータラン内の「ファイルの先頭アドレス」 - ビット反転後のパラメータの値

ビット反転は http://carumisu.hatenablog.com/entry/2015/10/27/114917 で行った。

Android プログラミング メディア

サウンド

public class MediaPlayerEx extends Activity implements View.OnClickListener{

    private final static int WC = LinearLayout.LayoutParams.WRAP_CONTENT;
    private final static String TAG_BGM = "bgm";
    private final static String TAG_SE = "se";
    private MediaPlayer mediaPlayer;
    private SoundPool soundPool;
    private int soundId;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);

//        サウンドプールの生成
        soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC,0);

//        サウンドプールのサウンド読み込み
        soundId = soundPool.load(this,R.raw.fanfare,1);

        LinearLayout layout = new LinearLayout(this);
        layout.setBackgroundColor(Color.WHITE);
        layout.setOrientation(LinearLayout.VERTICAL);
        setContentView(layout);

        layout.addView(makeButton("BGM再生", TAG_BGM));
        layout.addView(makeButton("SE再生", TAG_SE));

    }

    private Button makeButton(String text, String tag) {
        Button button = new Button(this);
        button.setText(text);
        button.setTag(tag);
        button.setOnClickListener(this);
        button.setLayoutParams(new LinearLayout.LayoutParams(WC, WC));
        return button;
    }

    @Override
    public void onClick(View v) {
        String tag = (String)v.getTag();
//        BGM再生/停止
        if(TAG_BGM.equals(tag)){
            if(mediaPlayer == null || !mediaPlayer.isPlaying()){
                playBGM();
            }else{
                stopBGM();
            }
        }else if (TAG_SE.equals(tag)) {
            playSE();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();

        stopBGM();

//        サウンドプールの解放
        soundPool.release();
    }

    private void playBGM(){
        stopBGM();
        try{
//            メディアプレイヤーの生成
            mediaPlayer = MediaPlayer.create(this,R.raw.jupiter);
            mediaPlayer.setLooping(true);
//             メディアプレイヤーの再生
            mediaPlayer.seekTo(0);
            mediaPlayer.start();
        }catch (Exception e){

        }
    }

    private void stopBGM(){
        if(mediaPlayer == null) return;
        try{
//            メディアプレイヤーの停止
            mediaPlayer.stop();
            mediaPlayer.release();
            mediaPlayer = null;
        }catch (Exception e){

        }
    }

    private void playSE(){
//        サウンドプールのサウンドの再生
        soundPool.play(soundId,100,100,1,0,1);
    }
}

ムービー

try{
//            ビデオビューの生成
            VideoView videoView = new VideoView(this);
            videoView.requestFocus();
            videoView.setMediaController(new MediaController(this));
            setContentView(videoView);

//            動画の再生
            videoView.setVideoURI(Uri.parse("android.resource://"+
                getPackageName()+"/"+R.raw.ultra));
            videoView.start();
        }catch (Exception e){
            android.util.Log.e("",e.toString());
        }

音声認識

@Override
    public void onClick(View v) {
//        音声認識の実行
        try{
            Intent intent = new Intent(
                    RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
            intent.putExtra(
                    RecognizerIntent.EXTRA_LANGUAGE_MODEL,
                    RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
            intent.putExtra(
                    RecognizerIntent.EXTRA_PROMPT,
                    "RecognizeSpeechEx");
            startActivityForResult(intent,REQUEST_CODE);
        }catch (Exception e){
            toast(e.getMessage());
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//        音声認識の結果の取得
        if(requestCode == REQUEST_CODE || requestCode == RESULT_OK){
            String str = "";
            ArrayList<String> results = data.getStringArrayListExtra(
                    RecognizerIntent.EXTRA_RESULTS);
            for(int i=0;i<results.size();i++){
                str += results.get(i)+" ";
            }
            editText.setText(str);
        }
        super.onActivityResult(requestCode,resultCode,data);
    }

音声合成

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        LinearLayout layout = new LinearLayout(this);
        layout.setBackgroundColor(Color.WHITE);
        layout.setOrientation(LinearLayout.VERTICAL);
        setContentView(layout);

        editText = new EditText(this);
        editText.setText("This is TEST");
        editText.setLayoutParams(new LinearLayout.LayoutParams(MP, WC));
        layout.addView(editText);

        layout.addView(makeButton("音声合成", "speech"));

//        音声合成の準備
        tts = new TextToSpeech(this,this);

    }

    private Button makeButton(String text, String tag) {
        Button button = new Button(this);
        button.setText(text);
        button.setTag(tag);
        button.setOnClickListener(this);
        button.setLayoutParams(new LinearLayout.LayoutParams(WC, WC));
        return button;
    }

    @Override
    public void onInit(int status) {
        if(status == TextToSpeech.SUCCESS){
//            音声合成のロケール指定
            Locale locale = Locale.ENGLISH;
            if(tts.isLanguageAvailable(locale) >= TextToSpeech.LANG_AVAILABLE){
                tts.setLanguage(locale);
            }else{
                toast("Unsupported Language");
            }
        }else if(status == TextToSpeech.ERROR){
            toast("TextToSpeech.ERROR");
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

//        音声合成の終了
        if(tts != null) tts.shutdown();
    }

    @Override
    public void onClick(View v) {
        String str = editText.getText().toString();
        if(str.length() == 0)return;
//        スピーチの停止
        if(tts.isSpeaking()) tts.stop();

//        スピーチの再生
        tts.setSpeechRate(1.0f);
        tts.speak(str,TextToSpeech.QUEUE_FLUSH,null);
    }

参考文献

Android プログラミング デバイス制御2

カメラ

まず、Manifest.xmlの変更。

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

~省略~

android:screenOrientation="landscape"  >

Acitvityのほう。

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

//        フルスクリーンの設定
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(new CameraView(this));
    }

Viewのほう。

public class CameraView extends TextureView implements
        TextureView.SurfaceTextureListener, Camera.PictureCallback{

    private Camera camera; // カメラ

    public CameraView(Context context){
        super(context);
//        テクスチャービューのリスナー登録
        setSurfaceTextureListener(this);
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
//        カメラの初期化
        try{
            camera = Camera.open();
            if(camera == null) camera = Camera.open(0);
            camera.setPreviewTexture(surface);
            camera.startPreview();
        }catch (Exception e){

        }
    }

//    サーフェステクスチャサイズ変更時に呼ばれる
    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
    }

//    サーフェステクスチャ更新時に呼ばれるs
    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
    }

//    サーフェステクスチャに呼ばれる
    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        camera.setPreviewCallback(null);
        camera.stopPreview();
        camera.release();
        camera = null;
        return true;
    }

//  タッチ時に呼ばれる
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN){
//            カメラのスクリーンショットの取得
            camera.takePicture(null,null,this);
        }
        return true;
    }

    public void onPictureTaken(byte[] data, Camera camera){
        try{
//            ファイル名の生成
            SimpleDateFormat format = new SimpleDateFormat(
                    "'IMG'_yyyyMdd_HHmmss'.jpg'", Locale.getDefault());
            String fileName = format.format(new Date(System.currentTimeMillis()));

//            SDカードへの保存
            String path = Environment.getExternalStorageDirectory()+"/"+fileName;
            saveToSD(data,path);

//            ギャラリーへの登録
            MediaScannerConnection.scanFile(this.getContext(),
                    new String[]{path},new String[]{"image/jpeg"},null);
            toast("撮影完了");
        }catch (Exception e){
            toast(e.toString());
        }

//        プレビューの再開
        camera.startPreview();
    }

//    SDカードへの保存
    private void saveToSD(byte[] w,String path) throws Exception{
        FileOutputStream out = null;
        try{
            out = new FileOutputStream(path);
            out.write(w);
            out.close();
        }catch (Exception e){
            if(out != null) out.close();
            throw e;
        }
    }

    private void toast(String text){
        if(text == null) text = "";
        Toast.makeText(getContext(),text, Toast.LENGTH_LONG).show();
    }

}

参考文献

NTFSのタイムスタンプ

どうやらNTFSでは1601年1月1日0時0分からの100ナノ秒単位でタイムスタンプを計算しているらしい。

バイナリエディタなどで16進数で表現されたときにMACTimeなどを読めるように変換するときのプログラムのメモ.

# coding: utf-8
import datetime

val = 0x01d11121d618281a #16進数で表現された時刻
s100nano = 0x989680 # 100ナノ秒単位での1秒

d = datetime.datetime(1601, 1, 1, 0, 0, 0)

# 経過秒数を足して、日本時間に修正
print d + datetime.timedelta(seconds=val/s100nano,hours=9)

Android プログラミング デバイス制御

センサ

public class SensorEx extends Activity implements SensorEventListener{

    private final static String BR = System.getProperty("line.separator");
    private final static int WC = LinearLayout.LayoutParams.WRAP_CONTENT;
    private TextView textView;
    private SensorManager manager;

//    回転行列
    private float[] inR = new float[16];
    private float[] outR = new float[16];

    private float[] accValues = new float[3]; //加速度
    private float[] magValues = new float[3]; //地磁気
    private float[] oriValues = new float[3]; //端末の傾き
    private boolean accEnabled = false; // 加速度センサーの有無
    private boolean magEnabled = false; // 地磁気センサーの有無

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        LinearLayout layout = new LinearLayout(this);
        layout.setBackgroundColor(Color.WHITE);
        layout.setOrientation(LinearLayout.VERTICAL);
        setContentView(layout);

        textView = new TextView(this);
        textView.setText("SensorEx");
        textView.setTextSize(24);
        textView.setTextColor(Color.BLACK);
        textView.setLayoutParams(new LinearLayout.LayoutParams(WC, WC));
        layout.addView(textView);

//        センサマネージャの取得
        manager = (SensorManager)getSystemService(
                Context.SENSOR_SERVICE);
    }

    @Override
    protected void onResume() {
        super.onResume();

//        センサの取得
        List<Sensor> sensors = manager.getSensorList(Sensor.TYPE_ALL);
        for(Sensor sensor:sensors){
            int type = sensor.getType();
//            加速度センサのリスナー登録
            if(type == Sensor.TYPE_ACCELEROMETER){
                manager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_UI);
                accEnabled = true;
            }
            // 地磁気センサのリスナー登録
            if(type == Sensor.TYPE_MAGNETIC_FIELD){
                manager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_UI);
                magEnabled = true;
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();

        if(accEnabled || magEnabled){
            manager.unregisterListener(this);
            accEnabled = false;
            magEnabled = false;
        }
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if(event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) return;

//        センサのタイプ取得
        int type = event.sensor.getType();

//        加速度センサの情報の格納
        if(type == Sensor.TYPE_ACCELEROMETER){
            accValues = event.values.clone();
        }
        // 地磁気センサの情報の格納
        else if(type == Sensor.TYPE_MAGNETIC_FIELD){
            magValues = event.values.clone();
        }

        if(accEnabled && magEnabled){

//            回転行列の計算
            SensorManager.getRotationMatrix(inR,null,accValues,magValues);
//            端末の向きに応じた軸の変更
            SensorManager.remapCoordinateSystem(inR,
                    SensorManager.AXIS_X, SensorManager.AXIS_Y, outR);
//          端末の傾きの計算
            SensorManager.getOrientation(outR, oriValues);
//          ラジアンを度に変換
            oriValues[0] = (float)Math.toDegrees(oriValues[0]);
            oriValues[1] = (float)Math.toDegrees(oriValues[1]);
            oriValues[2] = (float)Math.toDegrees(oriValues[2]);
        }

//        文字列表示
        StringBuffer sb = new StringBuffer();
        sb.append("SensorEx>" + BR);
        if(accEnabled){
            sb.append("加速度[x軸]:"+fm(accValues[0])+BR);
            sb.append("加速度[y軸]:"+fm(accValues[1])+BR);
            sb.append("加速度[z軸]:"+fm(accValues[2])+BR+BR);
        }
        if(accEnabled && magEnabled) {
            sb.append("ピッチ[x軸]:" + fm(oriValues[0]) + BR);
            sb.append("ロール[y軸]:"+fm(oriValues[1])+BR);
            sb.append("アジマス[z軸]:"+fm(oriValues[2])+BR+BR);
        }
        textView.setText(sb.toString());
    }

//    センサの制度の変更時に呼ばれる
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

//    数値のフォーマット
    private String fm(float value){
        return (value <= 0) ? ""+value:"+"+value;
    }
}

位置情報

まず、Manifest.xmlに書き込む。

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

次にコード。

ublic class LocationEx extends Activity implements LocationListener {

    private final static String BR = System.getProperty("line.separator");
    private final static int WC = LinearLayout.LayoutParams.WRAP_CONTENT;
    private TextView textView;
    private LocationManager manager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        LinearLayout layout = new LinearLayout(this);
        layout.setBackgroundColor(Color.WHITE);
        layout.setOrientation(LinearLayout.VERTICAL);
        setContentView(layout);

        textView = new TextView(this);
        textView.setText("LocationEx");
        textView.setTextColor(Color.BLACK);
        textView.setTextSize(24);
        textView.setLayoutParams(new LinearLayout.LayoutParams(WC, WC));
        layout.addView(textView);

//        ロケーションマネージャの取得
        manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    }

//    アクティビティ再開時に呼ばれる
    @Override
    protected void onResume() {
        super.onResume();
//        ロケーションマネージャのリスナー登録
        manager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
    }

//    アクティビティ一時停止に呼ばれる
    @Override
    protected void onPause() {
        super.onPause();
//        ロケーションマネージャの設定
        manager.removeUpdates(this);
    }

//    位置情報変更を通知する時に呼ばれる
    @Override
    public void onLocationChanged(Location location) {
        textView.setText("LocationEx>" + BR +
        "緯度"+location.getLatitude()+BR+
        "軽度"+location.getLongitude());
    }

//  位置情報取得有効化を通知する時に呼ばれる
    @Override
    public void onProviderEnabled(String provider) {
    }

//  位置情報取得無効化を通知する時に呼ばれる
    @Override
    public void onProviderDisabled(String provider) {

    }

//    位置情報状態変更を通知する時に呼ばれる
    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {

    }
}

参考文献