ソケット通信

Java同士でTCP/IPを用いた通信を行う

Javaのクライアントでは、Socketクラスでサーバのアドレスとポート番号を指定してインスタンスを作ります。 このSocketインスタンスからInput/Output Streamが得られます。 これに対して、read()とかwrite()とかすれば通信出来ます。 例えばデータを読み書きしてくれるホストがあれば、クライアントは以下のようにアクセスすることができます。

Socket socket = new Socket("192.168.0.10",5550); //引数1は相手(ホスト)のアドレス、次はポート番号
OutputStream oStream = socket.getOutputStream();
InputStream iStream = socket.getInputStream();
//中略 
oStream.write(data, 0, 10); //byte配列のdataの最初から10バイト送信
iStream.read(data, 0, 10); //byte配列のdataに10バイト読み込み

簡単ですね。一方、サーバの場合は、ServerScocketクラスをインスタンス化して、このインスタンスに.accept()メソッドを送ると、クライアントからの接続を待つことになります。

ServerSocket serverSocket = new ServerSocket(5550); //5550はポート番号
Socket socket = serverSocket.accept(); //クライアントからの接続を待ちます

accept()メソッドの戻り値がSocketになっているので、 あとはクライアントと同様にStreamを作ってread(), write()するだけです。

OutputStream oStream = socket.getOutputStream();
InputStream iStream = socket.getInputStream();
//中略 
oStream.write(data, 0, 10); //byte配列のdataの最初から10バイト送信
iStream.read(data, 0, 10); //byte配列のdataに10バイト読み込み

受け取った値を2倍して返すサーバ

では実際の例をみてみましょう。これはクライアントから1バイトのデータを受け取って、その値を2倍にして返すサーバです。

import java.net.*;
import java.io.*;

public class ByteDoubler {

public static void main(String[] args){

        int port_no = 5550;             //ポート番号とりあえず5550にする
        byte data[] = new byte[8];
        int sleep_time = 10; //待ち時間 

        try{
                //サーバソケットを作る
                ServerSocket serverSocket = new ServerSocket(port_no);
                //クライアントからの接続を待つ
                Socket socket = serverSocket.accept();
                
                //出力・出力ストリームを取得
                OutputStream oStream = socket.getOutputStream();
                InputStream iStream = socket.getInputStream();
                
                //クライアントからのデータが来るまで待つ
                while(iStream.available() == 0) Thread.sleep(sleep_time);
                iStream.read(data,0,1);//1バイト読む
                System.out.println("received data = " + data[0]);
                data[0]=(byte)(data[0] * 2); //2倍する
                oStream.write(data,0,1);
                oStream.flush();
                
                socket.close();         //ソケットを閉じる
        } catch (InterruptedException e) {
                System.out.println("Error in Thread.sleep");
        } catch(IOException e) {
                System.out.println("Error in socket communication");
        }
       
}//end of main

}//end of Class

このサーバに12を送って24を受け取るクライアント

このサーバに12という1バイトのデータを送り結果を受け取るクライアントは以下のように書けます。

import java.net.*;
import java.io.*;

public class ByteSender {

public static void main(String[] args){

        int port_no = 5550;             //ポート番号とりあえず5550にする
        String hostName = "localhost";  //サーバが同じマシンで動いている場合。実際には"192.168.0.xx"など
        byte data[] = new byte[8];
        int sleep_time = 10; //待ち時間 

        try{
                Socket socket = new Socket(hostName, port_no);// ソケットを生成
                OutputStream oStream = socket.getOutputStream();
                InputStream iStream = socket.getInputStream();
                
                data[0]=12;
                System.out.println("sending a number" + data[0]);
                oStream.write(data,0,1); //sending data[0]
                oStream.flush();
                
                //サーバからのデータが来るまで待つ
                while(iStream.available() == 0) Thread.sleep(sleep_time);
                System.out.println(iStream.read());
                
                socket.close();         //ソケットを閉じる
        } catch (InterruptedException e) {
                System.out.println("Error in Thread.sleep");
        } catch(IOException e) {
                System.out.println("Error in socket communication");
        }
        
}//end of main

}//end of Class

結果は次のようになります。

$ java ByteSender
sending a number12
24

ゼロを受け取るまで2倍返しを続けるサーバ

もうすこしサーバらしく、ずっと動いているような例を考えてみます。 数値をもらうとひたすら2倍返しするサーバです。 ただし0をもらうとサーバが終了するようにしてみました。 サーバプログラムは次のようになります。

import java.net.*;
import java.io.*;

public class ByteDoubler {

public static void main(String[] args){

        int port_no = 5550;             //ポート番号とりあえず5550にする
        byte data[] = new byte[8];
        int sleep_time = 10; //待ち時間

        try{
                //サーバソケットを作る
                ServerSocket serverSocket = new ServerSocket(port_no);
                //クライアントからの接続を待つ
                Socket socket = serverSocket.accept();
                
                //出力・出力ストリームを取得
                OutputStream oStream = socket.getOutputStream();
                InputStream iStream = socket.getInputStream();
                
                data[0]=99;//クライアントのデータが0になるまで繰り返す
                while(data[0]!=0) {
                        //クライアントからのデータが来るまで待つ
                        while(iStream.available() == 0) Thread.sleep(sleep_time);
                        iStream.read(data,0,1);//1バイト読む
                        System.out.println("received data = " + data[0]);
                        data[0]=(byte)(data[0] * 2);//2倍する
                        oStream.write(data,0,1);
                        oStream.flush();
                }
                
                socket.close();         //ソケットを閉じる
        } catch (InterruptedException e) {
                System.out.println("Error in Thread.sleep");
        } catch(IOException e) {
                System.out.println("Error in socket communication");
        }
        
}//end of main

}//end of Class

キーボード入力された数値をサーバに送るクライアント

このサバーに接続して、ユーザからキー入力を受け付けて、その数値をサーバに送り、 結果を受け取って表示するクライアントを書いてみました。 0を送るとサーバは終了するので、クライアントもそのとき終了するようにしました。

import java.net.*;
import java.io.*;

public class ByteSender {

public static void main(String[] args){ 

        int port_no = 5550;             //ポート番号とりあえず5550にする
        String hostName = "localhost";  //アドレスは自分自身
        byte data[] = new byte[8];
        int sleep_time = 10; //待ち時間
        
        //キーボード入力用
        BufferedReader keyinput = new BufferedReader(new InputStreamReader(System.in));
        
        try{
                Socket socket = new Socket(hostName, port_no);// ソケットを生成
                OutputStream oStream = socket.getOutputStream();
                InputStream iStream = socket.getInputStream();
                
                data[0]=99;
                while(data[0]!=0){
                        System.out.println("input a number (<127). Type 0 to end.");
                        data[0]=(byte)Integer.parseInt(keyinput.readLine());
                        System.out.println("sending a number" + data[0]);
                        oStream.write(data,0,1); //sending data[0]
                        oStream.flush();
                
                        if(data[0]!=0) {
                                //サーバからのデータが来るまで待つ
                                while(iStream.available() == 0) Thread.sleep(sleep_time);
                                System.out.println(iStream.read());
                        }//end if
                }//end while
                
                socket.close();         //ソケットを閉じる
        } catch (InterruptedException e) {
                System.out.println("Error in Thread.sleep");
        } catch(IOException e) {
                System.out.println("Error in socket communication");
        }
        
}//end of main

}//end of Class

これを稼働して、10,20,30,0という数字を入力すると以下のようになります。

$ java ByteSender
input a number (<127). Type 0 to end.
10
sending a number10
20
input a number (<127). Type 0 to end.
20
sending a number20
40
input a number (<127). Type 0 to end.
30
sending a number30
60
input a number (<127). Type 0 to end.
0
sending a number0
$

このサーバは、0を受け取ると終了します。 実際のサーバでは、クライアントへのサービスが終了したら、次のクライアントのアクセスを待つのが普通です。 次のwebサーバの例ではそのようにしてみましょう。

また、このサーバは、一つのクライアントが接続すると、ほかのクライアントが接続できなくなります。これを避けるためには、クライアントが接続すると別のスレッドを作って、マルチスレッドで対応します。 次のwebサーバの例では、クライアントへの対応が短時間で終了するので、複数接続は考えていません。

手抜きなwebサーバ

上記のサーバはwebサーバにもなります。 webサーバにしておくとブラウザやcurlコマンドなどで簡単にアクセスできます。 いろいろな状況やセンサの結果などを簡単にクライアントに返すときに利用できると思います。 クライアントからはGETというリクエストが送られてきて、そのほかいろいろな条件が指定されるのですが、 いっさい無視して、勝手にテキストを返す例です。 クライアントからのリクエストは空行で終了するので、それを検出すると返答します。

import java.net.*;
import java.io.*;

public class SimpleWebServer {
public static void main(String[] args){

	int port_no = 8080;             //待ち受けポート番号8080にする
	int sleep_time = 100; //待ち時間 

	try{
		//サーバソケットを作る
		ServerSocket serverSocket = new ServerSocket(port_no);
		for(;;) {
			//クライアントからの接続を待つ
			Socket socket = serverSocket.accept();

			//出力・出力ストリームを取得
			OutputStream oStream = socket.getOutputStream();
			InputStream iStream = socket.getInputStream();

			//クライアントからのデータが来るまで待つ
			while(iStream.available() == 0) Thread.sleep(sleep_time);
			Thread.sleep(sleep_time);

			//クライアントから空行(\r\n\r\n)が来るまで待つ
			//(タイムアウトしてもやっぱり送り返すことにしている)
			//デバッグ用にクライアントからのデータを表示するバージョン
			/*
			byte[] data = new byte[1024];
			for (int i=0; iStream.available() != 0; i++){
				data[i] = (byte)iStream.read(); 
				if(data[i] != '\r') continue; else i++;
				data[i] = (byte)iStream.read();
				if(data[i] != '\n') continue; else i++;
				data[i] = (byte)iStream.read(); 
				if(data[i] != '\r') continue; else i++;
				data[i] = (byte)iStream.read(); 
				if(data[i] != '\n') continue;
				else break;
			}
			System.out.println (new String(data, "US-ASCII"));
			*/
			while (iStream.available() != 0) {
				if(iStream.read()!='\r') continue;
				if(iStream.read()!='\n') continue;
				if(iStream.read()!='\r') continue;
				if(iStream.read()!='\n') continue;
				else break;
			}
			
			String reply = "HTTP/1.0 200 OK\r\ntext/html\r\n\r\n";
			reply += "hello this is a test \r\n"; //返送したいメッセージ、HTMLなど
			oStream.write(reply.getBytes(),0,reply.length());
			oStream.flush();
			socket.close();         //ソケットを閉じる
		}	
	} catch (InterruptedException e) {
		System.out.println("Error in Thread.sleep");
	} catch(IOException e) {
		System.out.println("Error in socket communication");
	}//end of try

}//end of main

}//end of Class

もうすこし高級なクラスを使う

ここではOutput/InputStreamを使ったのでバイト配列を送れるだけです。 Javaのファイル操作などでご存知のように、これからもっと高機能なクラスを利用出来ます。 たとえば

//OutputStreamからOutputStreamWriterを作り, さらにBufferedWriterを得る
BufferedWriter bWriter = 
                new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

とすればBufferつきのstreamを作れますし、

//OutputStreamからPrintWriterを作る
PrintWriter osStr = new PrintWriter(socket.getOutputStream(), true);

とすればprint()メソッドが使えて変数値を簡単に送るstreamも作れます。

入力についても、

//InputStreamからInputStreamReaderを作ってBufferedReaderを作る
InputStream iStream = socket.getInputStream();
BufferedReader bReader = new BufferedReader(new InputStreamReader(iStream));

とすればread()やreadLine()が使えます。ただreadLineは、サーバが改行を送るまでブロックされてしまうので注意です。

さらにはせっかくJava使っているので、URLというクラスを使えば、

//URLからInputStream, InputStreamReader, BufferedReaderを作る
URL targetURL = new URL("http://localhost:8080/");
InputStream istream = targetURL.openStream();
InputStreamReader isreader = new InputStreamReader(istream, "JISAutoDetect");
BufferedReader breader = new BufferedReader(  isreader );

としてreadLineが使えるようになります。こうすると、上記のwebサーバにアクセスするプログラムは以下になります。

手抜きなwebクライアント(URLクラス編)

webサーバプログラムが返すテキスト行を受け取ります。

public class URLTest {
	public static void main (String argv[]) {
		try {
			URL targetURL = new URL("http://localhost:8080/");
			InputStream istream = targetURL.openStream();
			InputStreamReader isreader = new InputStreamReader(istream, "JISAutoDetect");
			BufferedReader breader = new BufferedReader(  isreader );
		
			String line;
			while((line=breader.readLine()) != null) System.out.println(line);
		
		} catch (IOException e) {
			System.out.println("error...");
		}
	}
}

手抜きなwebクライアント(ソケット編)

上のURLクラス編で解決なのですが、ソケットレベルから 手抜きなwebクライアントを書いてみました。 上記の手抜きなWebサーバが動いていれば、そこからメッセージを受け取れます。またcurl風に、

java WebClient www.ocha.ac.jp:80

と書けば、そこからもダウンロードします。サーバの応答を冒頭に含んでいるので、本物のcurlとは結果が違います。またファイル名の指定やバイナリーのデータにも対応していませんのでjpegファイルなどはダウンロードできません。ちなみに、curl localhost:8080/filename としたときのfilenameは、GETコマンドあとに現れるので、これを使ってサーバが異なる結果を返すこともできそうです。

import java.net.*;
import java.io.*;

public class WebClient {

public static void main(String[] args){

        int port_no = 8080;             //ポート番号とりあえず8080にする
        String hostName = "localhost";  //サーバが同じマシンで動いている場合。実際には"192.168.0.xx"など
        int sleep_time = 50; //待ち時間 

		if(args.length >= 1) {
			int colon = args[0].lastIndexOf(':');
			if(colon == -1) {
				hostName = args[0];
			} else {
				hostName = args[0].substring(0,colon);
				port_no = Integer.parseInt(args[0].substring(colon + 1));
			}
		}
		
		try{
                Socket socket = new Socket(hostName, port_no);// ソケットを生成
                OutputStream oStream = socket.getOutputStream();
				PrintWriter pWriter = new PrintWriter(oStream, true);
                InputStream iStream = socket.getInputStream();
				BufferedReader bReader = new BufferedReader(new InputStreamReader(iStream));
				
				pWriter.print("GET / HTTP/1.1\r\n"); //curlのメッセージを真似ました
				pWriter.print("User-Agent: siio_client\r\n");
				pWriter.print("Host: " + hostName + ":" + port_no + "\r\n");
				pWriter.print("Accept: */*\r\n\r\n"); //空行がデータ送れの合図
				pWriter.flush();
                
                //サーバからのデータが来るまで待つ
                while(iStream.available() == 0) Thread.sleep(sleep_time);
				Thread.sleep(sleep_time);
				
				String result="";
				char[] cbuf = new char[256];
				int num = cbuf.length;
				while(num == cbuf.length ) {
					num = bReader.read(cbuf, 0, cbuf.length);
					result += String.valueOf(cbuf,0,num);
				}
				System.out.println(result);
                
                socket.close();         //ソケットを閉じる
        } catch (InterruptedException e) {
                System.out.println("Error in Thread.sleep");
        } catch(IOException e) {
                System.out.println("Error in socket communication");
        }
        
}//end of main

}//end of Class

以下はけこたんがまとめました。

nc(NetCat)コマンドの使い方

nc(NetCat)コマンドを使ってUDPソケット通信をした話

ソケット通信のプログラムにバグがある時、受信側と送信側のどちらが正しい動作していないのかを調べるのに使える。

受信側のIPアドレスを調べる

Macの場合、 システム環境設定→ネットワーク にアクセスすることで見られる

network.png

受信側

ターミナル上で

 nc -4ul 12345

を実行する。 オプションは、それぞれ

-4 IPv4
-u UDPモード
-l listenモード

を表している。

12345はポート番号。適当な番号を指定する。

送信側

ターミナル上で

 nc -u 192.168.108.147 12345

を実行する。

192.168.108.147の部分には、受信側のIPアドレスを指定する。

12345はポート番号。受信側と同じ番号を指定する。

送信側で値を入力すると、受信側で表示される。

Pythonでsocket

http://d.hatena.ne.jp/miho36/20100420/1271753758

AndroidとPC(openFramworks)でUDP/IPを用いた通信を行う

次は、AndroidからPCにデータを送る例です。

送信側(Android (Java))

  1. permissionの設定を行う
    • まず、
      <uses-permission android:name="android.permission.INTERNET"/>
      AndroidManifest.xmlに追加する。
  2. ボタンの配置を行う
    • 『sendボタンが押されたら、テキストボックスに入力された文字列を送信し、quitボタンが押されたら、アプリを終了する』という動作を行うために、EditTextとButtonを配置する。
  3. MainActivityに基本的な設定を書く
    • ソケット通信は、MainActivityの中で行えないため、MainActivityには基本的な設定だけ書く。
      DatagramSocket sendSocket = new DatagramSocket();
      で、ソケットを作り、
      sendSocket.close();
      で、ソケットを閉じる。
  4. AsyncTaskをExtendしたclassの中でメッセージを送信する
    • DatagramPacket packet =
              new DatagramPacket(msg, msg.length, inetAddress, param.port);
      で送るパケットを生成する。
      param.socket.send(packet);
      でパケットを送る。

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.udptest"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="16" />

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.udptest.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

layout/activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.udptest.MainActivity"
    tools:ignore="MergeRootFrame" >

    <EditText
        android:id="@+id/inputText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="94dp"
        android:ems="10"
        android:inputType="text" >

        <requestFocus />
    </EditText>

    <Button
        android:id="@+id/sendButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/inputText"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="50dp"
        android:text="@string/send_button" />

    <Button
        android:id="@+id/quitButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/sendButton"
        android:layout_below="@+id/sendButton"
        android:layout_marginTop="78dp"
        android:text="@string/quit_button" />

</RelativeLayout>

MainActivity.java

package com.example.udptest;

import java.net.DatagramSocket;
import java.net.SocketException;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends ActionBarActivity {

  private DatagramSocket sendSocket = null;
  EditText inputText;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (savedInstanceState == null) {
      getSupportFragmentManager().beginTransaction()
          .add(R.id.container, new PlaceholderFragment()).commit();
    }

    Button sendButton = (Button)findViewById(R.id.sendButton);
    sendButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        sendMessage(inputText.getText().toString());
      }
    });
    Button quitButton = (Button)findViewById(R.id.quitButton);
    quitButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        finish();
      }
    });

    inputText = (EditText)findViewById(R.id.inputText);
  }

  @Override
  protected void onResume() {
    super.onResume();
    try {
      sendSocket = new DatagramSocket();
    } catch (SocketException e) {
      e.printStackTrace();
    }
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {

    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
      return true;
    }
    return super.onOptionsItemSelected(item);
  }

  /**
   * A placeholder fragment containing a simple view.
   */
  public static class PlaceholderFragment extends Fragment {

    public PlaceholderFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
      View rootView = inflater
          .inflate(R.layout.fragment_main, container, false);
      return rootView;
    }
  }

  @Override
  public void onStop() {
    super.onStop();
    sendSocket.close();
  }

  public void sendMessage(String body) {
    udpParam param = new udpParam();
    param.body = body;
    param.socket = sendSocket;
    UDPSendRequest request = new UDPSendRequest();
    request.execute(param);
  }

  class udpParam {
    String body = "";
    String address = "192.168.108.147";
    int port = 60000;
    DatagramSocket socket = null;
    }
}

UDPSendRequest.java

package com.example.udptest;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

import android.os.AsyncTask;
import android.util.Log;

import com.example.udptest.MainActivity.udpParam;

public class UDPSendRequest extends AsyncTask<udpParam, Void, Boolean> {
  private String TAG = "UDBSendRequest";
  private udpParam param;

  @Override
  protected Boolean doInBackground(udpParam... params) {
    param = params[0];

    if (param.socket == null) {
      try {
        param.socket = new DatagramSocket();
      } catch (SocketException e) {
        e.printStackTrace();
        return false;
      }
    }

    byte[] msg;
    try {
      msg = param.body.getBytes("UTF-8");
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
      return false;
    }

    InetAddress inetAddress;
    try {
      inetAddress = InetAddress.getByName(param.address);
    } catch (UnknownHostException e) {
      e.printStackTrace();
      return false;
    }
    DatagramPacket packet =
        new DatagramPacket(msg, msg.length, inetAddress, param.port);

    try {
      param.socket.send(packet);
    } catch (IOException e) {
      e.printStackTrace();
      return false;
    }

    return true;
  }

  @Override
  protected void onPostExecute(Boolean result) {
    if (result) {
      Log.v(TAG, "successed to send message");
    } else {
      Log.e(TAG, "failed to send a message");
    }
  }
}

受信側(PC (openFrameworks, C++))

testApp.h

#pragma once

#include "ofMain.h"
#include "ofxUI.h"

#include <iostream>
#include <string>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>

class testApp : public ofBaseApp{
	public:
    void setup();
    void update();
    void draw();
    void exit();
    
    void keyPressed(int key);
    void keyReleased(int key);
    void mouseMoved(int x, int y);
    void mouseDragged(int x, int y, int button);
    void mousePressed(int x, int y, int button);
    void mouseReleased(int x, int y, int button);
    void windowResized(int w, int h);
    void dragEvent(ofDragInfo dragInfo);
    void gotMessage(ofMessage msg);
    
    ofxUICanvas *gui;
    void guiEvent(ofxUIEventArgs &e);
    bool drawPadding;
    
    int sock;  // socket discreptor
    fd_set fd, readfd; //file discreptor
    int maxfd;    // calculate max value of file discriptor. It is used by select.
    char buffer[8];
    
    struct sockaddr_in from_address;
    socklen_t sin_size;
};

testApp.cpp

#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){
    
    gui = new ofxUICanvas();
    gui->addLabelButton("EXIT", false);
    ofAddListener(gui->newGUIEvent, this, &testApp::guiEvent);

    struct sockaddr_in address;
    
    // create IPv4 UDP socket
    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket");
        OF_EXIT_APP(-1);
    }
    
    // sender IP and Port
    address.sin_family = AF_INET;
    address.sin_port = htons(60000);
    address.sin_addr.s_addr = INADDR_ANY;  // receive all packet whatever to_address
    
    // bind
    if (bind(sock, (struct sockaddr*)&address, sizeof(address)) < 0) {
        perror("bind");
        OF_EXIT_APP(-1);
    }
    
    // set sock non-blocking mode
    // if you change val to 0, you can set sock blocking mode
    // sock default is blocking mode
    int mode = 1;
    ioctl(sock, FIONBIO, &mode);
}

//--------------------------------------------------------------
void testApp::update(){
    memset(buffer, 0, sizeof(buffer));
    if (recv(sock, buffer, sizeof(buffer), 0) < 1){
        if (errno != EAGAIN) {
            perror("recv");
        }
    } else {
        cout << buffer << endl;
        if (string(buffer) == "end") {
            OF_EXIT_APP(1);
        }
    }
}

//--------------------------------------------------------------
void testApp::draw(){
}

//--------------------------------------------------------------
void testApp::exit() {
    cout << "exit" << endl;
    close(sock);
}

//--------------------------------------------------------------
void testApp::guiEvent(ofxUIEventArgs &e) {
    string name = e.widget->getName();
    int kind = e.widget->getKind();
    
    if (kind == OFX_UI_WIDGET_LABELBUTTON) {
        OF_EXIT_APP(1);
    }
}

//--------------------------------------------------------------
void testApp::keyPressed(int key){
    if (key == 'q') {
        OF_EXIT_APP(1);
    }

}

//--------------------------------------------------------------
void testApp::keyReleased(int key){

}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y){

}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void testApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void testApp::dragEvent(ofDragInfo dragInfo){ 

}

添付ファイル: filenetwork.png 2970件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2020-11-18 (水) 20:52:00