SSブログ

「オープンソースハードウェアセミナーVol1」レポート Arduino Ethernetライブラリ UDPの実現2 [ATmarquino Arduino]

ether_shield_012.png
ether_shield_013.png
UDPライブラリの続きです。
インスタンスの生成やソケットオープン周りの変更と、データグラムの受信機能を追加しました。
作成したコードは下の方に記載しておきます。

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();
  }
}


Arduinoモニタープログラム参加中
電子部品・半導体の通販サイト - チップワンストップ



マスタリングTCP/IP 入門編 第4版

マスタリングTCP/IP 入門編 第4版

  • 作者: 竹下 隆史
  • 出版社/メーカー: オーム社
  • 発売日: 2007/02/24
  • メディア: 大型本



TCP/IPの絵本 ネットワークっておもしろい!

TCP/IPの絵本 ネットワークっておもしろい!

  • 作者: アンク
  • 出版社/メーカー: 翔泳社
  • 発売日: 2003/12/13
  • メディア: 単行本



nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:[必須]
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

※ブログオーナーが承認したコメントのみ表示されます。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。