「オープンソースハードウェアセミナーVol1」レポート Arduino Ethernetライブラリ UDPの実現2 [ATmarquino Arduino]
インスタンスの生成やソケットオープン周りの変更と、データグラムの受信機能を追加しました。
作成したコードは下の方に記載しておきます。
UDPの送受信を確認する為には、なんらかのUDPデータグラムを送ってくれる相手が必要です。
そこでパケットモニタ(PacMon)が仕掛けられているPCに自前で作成したDAYTIMEサーバーを起動しておきます。
このサーバーは、内容はなんでも良いのですがUDPでアクセスされると、そのアクセス元に現在の時刻を返信します。受信した内容は一切関知していません。
パケットモニタでハイライトされているパケットがその時刻の返信です。
TCPソケットとの併用を確認する為に、例のWEBサーバーの中にUDPの送受信プログラムを埋め込んでしまいました。なんと雑な!。
使い方ですが、インスタンス生成時に
Udp udp = Udp( 5000 );
とすれば指定したポート番号を自分のポート番号として使用します。
Udp udp = Udp();
とすればエフェメラルポートの開始番号1024を自分のポート番号として使用します。
問題なのは複数のインスタンスを生成した場合のポート番号の排他制御をまだ実装していない点ですね。今後に”期待”しましょう。
udp.Open();
と記述すれば現行のポート番号を自分のポート番号として使用します。ちょっと説明し辛いのですが、大域変数に現在設定されているポート番号の領域が取られていて、その変数を自ポート番号として利用すると言う事です。
udp.Open( 5000 );
と記述すれば5000を自ポート番号として利用すると言う事です。
どちらのOpenの場合も、現行ポート番号は自動的にインクリメントされます。
あとは実際に記述したスケッチを見れば判ると思います。
修正したudp.cppです。
extern "C" { #include "types.h" #include "w5100.h" #include "socket.h" } #include "Ethernet.h" #include "Udp.h" Udp::Udp() { _port = 1024; } Udp::Udp( uint16_t port ) { _port = port; } uint8_t Udp::Open() /*エフェメラルポートの利用*/ { _sock = GetSockNum(); if( _sock != (-1) ) { socket( _sock, Sn_MR_UDP, _port, 0 ); if( ++_port == 0 ) _port = 1024; return 1; } return 0; } uint8_t Udp::Open( uint16_t port ) /*ポート番号をBINDして使う*/ { _sock = GetSockNum(); if( _sock != (-1) ) { socket( _sock, Sn_MR_UDP, port, 0 ); return 1; } return 0; } void Udp::Close() { close( _sock ); } void Udp::sendTo( const uint8 * buf, uint16 len, uint8 * dip, uint16 dport ) { sendto( _sock, buf, len, dip, dport ); } int16 Udp::recvFrom( uint8 * buf, uint16 len, uint8 * dip, uint16 *dport ) { return recvfrom( _sock, buf, len, dip, dport ); } int Udp::GetSockNum() { int sock = (-1); for( int i = 0; i < MAX_SOCK_NUM; i++ ) { uint8_t s = getSn_SR( i ); if( s == SOCK_CLOSED ) { sock = i; break; } } return sock; }
修正したudp.hです。
#ifndef Udp_h #define Udp_h class Udp { private: uint8_t _sock; uint16_t _port; int GetSockNum(); public: Udp(); Udp( uint16_t port ); uint8_t Open(); uint8_t Open( uint16_t port ); void Close(); void sendTo( const uint8 * buf, uint16 len, uint8 * addr, uint16 port ); int16 recvFrom( uint8 * buf, uint16 len, uint8 * addr, uint16 *dport ); }; #endif
修正したWEBサーバーのスケッチの一部です。
#include <Ethernet.h> #include <ctype.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <avr/pgmspace.h> #define LINE_STRING_SIZE 128 #define ECHO_PORT 7 #define DAYTIME_PORT 13 char *line; char meth[10],url[30],ver[20]; long access_count; const byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; const byte ip[] = { 192, 168, 100, 177 }; const byte gateway[] = { 192, 168, 100, 1 }; const byte dip[] = { 192, 168, 100, 13 }; Server server( 8888 ); Udp udp = Udp( 5000 ); /*UDP socketの生成*/ //Udp udp = Udp(); /*UDP socketの生成*/ void setup() { Ethernet.begin( (uint8_t *)mac, (uint8_t *)ip, (uint8_t *)gateway ); server.begin(); Serial.begin( 38400 ); line = (char *)malloc( LINE_STRING_SIZE ); } void loop() { byte server_ip[4]; uint16 dport; int16 rcv_size; char buffer[ 32 ]; Client client = server.available(); if( client ) { while( client.connected() ) { if( udp.Open() ) { udp.sendTo( (const uint8 *)"udp test start.", sizeof("udp test start."), (uint8 *)dip, DAYTIME_PORT ); delay( 100 ); while( (rcv_size = udp.recvFrom( (uint8 *)buffer, sizeof(buffer) - 1, (uint8 *)server_ip, &dport )) == (-1) ) delay( 1 ); buffer[ rcv_size ] = '\0'; Serial.println( buffer ); Serial.print( "from ip=" ); for( int i = 0; i < sizeof(server_ip) / sizeof(server_ip[0]); i++ ) { Serial.print( server_ip[i], DEC ); Serial.print( "." ); } Serial.print( " from port=" ); Serial.print( dport, DEC ); Serial.println(); udp.Close(); } else { Serial.println( "UDP Open NG." ); } char *dst = HTTPGets( client, line, LINE_STRING_SIZE ); char *argv[ 10 ]; int div_num = split( dst, argv, sizeof(argv) / sizeof(argv[0]) ); /*文字列分割*/ strncpy( meth, argv[ 0 ], sizeof(meth) ); strncpy( url, argv[ 1 ], sizeof(url) ); strncpy( ver, argv[ 2 ], sizeof(ver) ); break; } while( client.connected() ) { char *dst = HTTPGets( client, line, LINE_STRING_SIZE ); if( dst != NULL && *dst == '\0' ) /*改行のみの行を検出*/ { index_html( client ); break; } } delay( 1 ); client.stop(); } }
2009-06-06 13:34
nice!(0)
コメント(0)
トラックバック(0)
コメント 0