uIPのイベント
uIPで簡単なHTTPクライアントを書いてみる。
大げさなものではなくGETしてそれを画面に出力するだけ。
まずはuIPのドキュメント通りに、各状態に合わせたハンドラを呼んでやる
void NetServer::DoEvent() { if (uip_aborted()) { AbortedHandler(); } if (uip_timedout()) { TimeoutHandler(); } if (uip_closed()) { ClosedHandler(); } if (uip_connected()) { ConnectedHandler(); } if (uip_acked()) { AckedHandler(); } if (uip_newdata()) { NewDataHandler(); } if (uip_rexmit() || uip_newdata() || uip_acked() || uip_acked() || uip_connected() || uip_poll()) { SendDataHandler(); }
次にそれぞれのハンドラを定義してやります。
今回は実験なので、効率とか誰がメモリ解放するのかとか、エラーのときは?とかは一切考えていません。
void NetServer::ConnectedHandler() { printf("%s\n", __FUNCTION__); struct server_state* s = (struct server_state *)uip_conn->appstate; const char* message = "GET /file HTTP/1.0\r\nServer:192.168.100.2\r\n\r\n"; s->message = new char[strlen(message) + 1]; strcpy(s->message, message); s->length = strlen(message) + 1; } void NetServer::AckedHandler() { printf("%s\n", __FUNCTION__); struct server_state* s = (struct server_state *)uip_conn->appstate; s->length -= uip_conn->len; s->message += uip_conn->len; if(s->length == 0) { printf("send done\n"); } } void NetServer::NewDataHandler() { printf("%s\n", __FUNCTION__); for (dword i = 0; i < GetDataLength(); i++) { printf("%c", (char)uip_appdata[i]); } } void NetServer::SendDataHandler() { printf("%s\n", __FUNCTION__); struct server_state* s = (struct server_state *)uip_conn->appstate; if (s->length != 0) { uip_send((volatile u8_t*)s->message, s->length); } }
フローとしては
1. 接続が完了すると ConnectedHandlerが呼ばれる
2. GETを発行するために、GET文字列と長さを格納
3. 送信
4. ackedが返ってきてまだ未送信分がある場合や、再送の必要があれば再送信します。
5.uip_newdata()が1だったらデータが返ってきています。
これを踏まえたうえで次のエントリーへ。