/**** ファイル名 : MainWindow.h ****/
#ifndef MAINWINDOW #define MAINWINDOW //--------------------------------------------------------------------- #include <Be.h> #include <be/net/socket.h> //--------------------------------------------------------------------- #define MAINWINDOW_TITLE "Network" #define MAINWINDOW_POSITION_LEFT 100 #define MAINWINDOW_POSITION_TOP 100 #define MAINWINDOW_POSITION_WIDTH 400 #define MAINWINDOW_POSITION_HEIGHT 128 #define MAINWINDOW_WINDOWSTYLE (B_TITLED_WINDOW) //--------------------------------------------------------------------- #define MSG_CONNECT 'cnnb' #define MSG_LISTEN 'lstb' #define MSG_SEND 'sndb' //--------------------------------------------------------------------- class BAppMainView : public BView { public: BStringView *strview; BTextControl *textctrl; BButton *connectbtn; BButton *listenbtn; BButton *sendbtn; BAppMainView(BRect frame); }; //--------------------------------------------------------------------- class BAppMainWindow : public BWindow { private: int nsock; public: BAppMainView *mainview; //----------------------------------------------------------------- BAppMainWindow(BRect frame,const char *title); virtual void MessageReceived(BMessage *msg); //----------------------------------------------------------------- bool QuitRequested(); //----------------------------------------------------------------- void sock_connect(void); void sock_listen(void); void sock_send(void); }; //--------------------------------------------------------------------- #endif
/**** ファイル名 : MainWindow.cpp ****/
//--------------------------------------------------------------------- #include "MainWindow.h" //--------------------------------------------------------------------- BAppMainWindow::BAppMainWindow(BRect frame,const char *title) :BWindow(frame,title,MAINWINDOW_WINDOWSTYLE,0) { mainview=new BAppMainView(Bounds()); AddChild(mainview); nsock=-1; } //--------------------------------------------------------------------- void BAppMainWindow::MessageReceived(BMessage *msg) { switch(msg->what) { case MSG_SEND: sock_send(); break; case MSG_CONNECT: sock_connect(); break; case MSG_LISTEN: sock_listen(); break; default: BWindow::MessageReceived(msg); } } //--------------------------------------------------------------------- BAppMainView::BAppMainView(BRect frame) :BView(frame,"bappmainview",B_FOLLOW_ALL,B_WILL_DRAW) { BRect viewrect(Bounds()); connectbtn=new BButton(BRect(viewrect.right-144,8, viewrect.right-80,28),"connectbtn", "Connect",new BMessage(MSG_CONNECT), B_FOLLOW_RIGHT | B_FOLLOW_TOP); AddChild(connectbtn); listenbtn=new BButton(BRect(viewrect.right-72,8, viewrect.right-8,28),"listenbtn", "Listen",new BMessage(MSG_LISTEN), B_FOLLOW_RIGHT | B_FOLLOW_TOP); AddChild(listenbtn); sendbtn=new BButton(BRect(viewrect.right-72,98, viewrect.right-8,118),"sendbtn", "Send",new BMessage(MSG_SEND), B_FOLLOW_RIGHT | B_FOLLOW_TOP); AddChild(sendbtn); textctrl=new BTextControl(BRect(8,38,viewrect.right-8,58),"textctrl", NULL,"Default",NULL, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); AddChild(textctrl); strview=new BStringView(BRect(8,68,viewrect.right-8,88),"strview", "NoData", B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); AddChild(strview); textctrl->SetEnabled(false); sendbtn->SetEnabled(false); } //--------------------------------------------------------------------- void BAppMainWindow::sock_connect(void) { struct sockaddr_in sa; int r; mainview->connectbtn->SetEnabled(false); mainview->listenbtn->SetEnabled(false); nsock=socket(AF_INET, SOCK_STREAM, 0); sa.sin_family=AF_INET; sa.sin_port=htons(10000); sa.sin_addr.s_addr=inet_addr("127.0.0.1"); memset(sa.sin_zero,0,sizeof(sa.sin_zero)); r=connect(nsock,(struct sockaddr *)&sa,sizeof(sa)); if(r!=-1) { mainview->strview->SetText("Connect"); mainview->textctrl->SetEnabled(true); mainview->sendbtn->SetEnabled(true); } } //--------------------------------------------------------------------- void BAppMainWindow::sock_listen(void) { int ssock; struct sockaddr_in sa; int sa_size; size_t rec; char buf[256]; struct timeval tv; struct fd_set fds; mainview->connectbtn->SetEnabled(false); mainview->listenbtn->SetEnabled(false); ssock=socket(AF_INET,SOCK_STREAM,0); sa.sin_family=AF_INET; sa.sin_port=htons(10000); sa.sin_addr.s_addr=INADDR_ANY; memset(sa.sin_zero,0,sizeof(sa.sin_zero)); bind(ssock,(struct sockaddr *)&sa,sizeof(sa)); listen(ssock,5); sa_size=sizeof(sa); nsock=accept(ssock,(struct sockaddr *)&sa, &sa_size); closesocket(ssock); do{ tv.tv_sec=2; tv.tv_usec=0; FD_ZERO(&fds); FD_SET(nsock,&fds); select(32,&fds,NULL,NULL,&tv); } while(FD_ISSET(nsock,&fds)==0); rec=recv(nsock,buf,sizeof(buf),0); if(rec<=0) { closesocket(nsock); nsock=-1; strcpy(buf,"Disconnect"); } mainview->strview->SetText(buf); } //--------------------------------------------------------------------- void BAppMainWindow::sock_send(void) { int r; mainview->textctrl->SetEnabled(false); mainview->sendbtn->SetEnabled(false); r=send(nsock,mainview->textctrl->Text(), strlen(mainview->textctrl->Text())+1,0); if(r==-1) { closesocket(nsock); nsock=-1; mainview->strview->SetText("Disconnect"); } } //--------------------------------------------------------------------- bool BAppMainWindow::QuitRequested() { if(nsock!=-1) closesocket(nsock); be_app->PostMessage(B_QUIT_REQUESTED); return true; }; //---------------------------------------------------------------------
データをセットして送る部分は後回しにして、受信処理でそのデータを受け取る部分から作ってみましょう。//--------------------------------------------------------------------- struct RecThreadData { int sock; BWindow *owner; }; //---------------------------------------------------------------------
receive_dataの戻り値、引数として使用しているcode、senderですが、今回はデバッグ目的で使用する程度で、処理には絡みませんので、説明は割愛します。int sock; BWindow *Owner; RecThreadData rdata; int32 sender; int32 code; code=receive_data((thread_id *)&sender,(void *)&rdata,sizeof(rdata)); Owner=rdata.owner; sock=rdata.sock;
となっています。do { tv.tv_sec=2; tv.tv_usec=0; FD_ZERO(&fds); FD_SET(nsock,&fds); select(32,&fds,NULL,NULL,&tv); } while(FD_ISSET(nsock,&fds)==0); rec=recv(nsock,buf,sizeof(buf),0); if(rec<=0) { closesocket(nsock); nsock=-1; strcpy(buf,"Disconnect"); }
としてMainWindow.hに定義しておきます。#define MSG_CLOSED 'clsd' #define MSG_RECV 'recv'
receive_data関数で必要な情報の取得をしたら、do-whileでrecv関数が失敗するまでループを繰り返して、その中で受信処理を繰り返します。受信処理では、select関数でソケットの状態を監視し、受信状態になったらrecv関数でデータを受信します。recv関数が失敗したらMSG_CLOSEDメッセージを、成功したら受信したデータをメッセージに付加したうえでMSG_RECVメッセージを発行します。どちらのメッセージにも、受け取った側が判断しやすいようにソケットを付加しておきます。//--------------------------------------------------------------------- int32 rec_thread(void *Dummy) { int sock; BWindow *Owner; struct timeval tv; struct fd_set fds; BMessage *sendmsg; unsigned char buf[1024]; ssize_t rec; RecThreadData rdata; int32 sender; int32 code; code=receive_data((thread_id *)&sender,(void *)&rdata,sizeof(rdata)); Owner=rdata.owner; sock=rdata.sock; do{ do{ tv.tv_sec=2; tv.tv_usec=0; FD_ZERO(&fds); FD_SET(sock,&fds); select(32,&fds,NULL,NULL,&tv); } while(FD_ISSET(sock,&fds)==0); rec=recv(sock,buf,sizeof(buf),0); if(rec<=0) { sendmsg=new BMessage(MSG_CLOSED); sendmsg->AddInt32("socket",sock); Owner->PostMessage(sendmsg); delete sendmsg; } else { sendmsg=new BMessage(MSG_RECV); sendmsg->AddInt32("socket",sock); sendmsg->AddData("data",B_ANY_TYPE,(void *)buf,rec); Owner->PostMessage(sendmsg); delete sendmsg; } } while(rec>0); return rec; } //---------------------------------------------------------------------
このように、rdataに必要なデータをセットし、spawn_thread関数でrec_threadを作成、send_data関数で必要なデータを渡したらスレッドを開始します。struct RecThreadData rdata; rdata.sock=nsock; rdata.owner=(BWindow *)this; strcpy(threadname,"ClientRecvThread"); recthread=spawn_thread(rec_thread,threadname, B_NORMAL_PRIORITY,NULL); send_data(recthread,63,(void *)&rdata,sizeof(rdata)); resume_thread(recthread);
//--------------------------------------------------------------------- void BAppMainWindow::sock_connect(void) { struct sockaddr_in sa; int r; mainview->connectbtn->SetEnabled(false); mainview->listenbtn->SetEnabled(false); nsock=socket(AF_INET, SOCK_STREAM, 0); sa.sin_family=AF_INET; sa.sin_port=htons(10000); sa.sin_addr.s_addr=inet_addr("127.0.0.1"); memset(sa.sin_zero,0,sizeof(sa.sin_zero)); r=connect(nsock,(struct sockaddr *)&sa,sizeof(sa)); if(r!=-1) { struct RecThreadData rdata; mainview->strview->SetText("Connect"); mainview->textctrl->SetEnabled(true); mainview->sendbtn->SetEnabled(true); rdata.sock=nsock; rdata.owner=(BWindow *)this; strcpy(threadname,"ClientRecvThread"); recthread=spawn_thread(rec_thread,threadname, B_NORMAL_PRIORITY,NULL); send_data(recthread,63,(void *)&rdata,sizeof(rdata)); resume_thread(recthread); } } //--------------------------------------------------------------------- void BAppMainWindow::sock_listen(void) { int ssock; struct sockaddr_in sa; int sa_size; mainview->connectbtn->SetEnabled(false); mainview->listenbtn->SetEnabled(false); ssock=socket(AF_INET,SOCK_STREAM,0); sa.sin_family=AF_INET; sa.sin_port=htons(10000); sa.sin_addr.s_addr=INADDR_ANY; memset(sa.sin_zero,0,sizeof(sa.sin_zero)); bind(ssock,(struct sockaddr *)&sa,sizeof(sa)); listen(ssock,5); sa_size=sizeof(sa); nsock=accept(ssock,(struct sockaddr *)&sa, &sa_size); closesocket(ssock); if(nsock!=-1) { struct RecThreadData rdata; mainview->strview->SetText("Connect"); mainview->textctrl->SetEnabled(true); mainview->sendbtn->SetEnabled(true); rdata.sock=nsock; rdata.owner=(BWindow *)this; strcpy(threadname,"ServerRecvThread"); recthread=spawn_thread(rec_thread,threadname, B_NORMAL_PRIORITY,NULL); send_data(recthread,63,(void *)&rdata,sizeof(rdata)); resume_thread(recthread); } } //---------------------------------------------------------------------
メッセージから受信データを取り出すだけです。case MSG_RECV: { char *buf; ssize_t leng; msg->FindData("data",B_ANY_TYPE,(const void **)&buf,&leng); mainview->strview->SetText(buf); } break;
圧縮ファイル R5 Intel環境で確認 |
Be8thApp20001223.zip |
ソースファイル | BaseApp.h |
main.cpp | |
MainWindow.cpp | |
MainWindow.h |