UDPソケットを介してデータを適切に送信できますが、データを受信しても、受信コマンドで待機し続けます。これは何が原因なのかわかりません。以下の私のコードを見てください。
Androidデバイスからサーバー側でデータを正しく受信できますが、サーバー側からAndroidデバイスにデータを送信すると受信しません。サーバーから他のクライアントにデータを送信するとき(たとえば、PCアプリケーション)、データを正しく受信して表示します。
class Task implements Runnable {
@Override
public void run() {
try {
String messageStr = "feed";
int server_port = 8888;
InetAddress local = InetAddress.getByName("10.0.2.2");
int msg_length = messageStr.length();
byte[] message = messageStr.getBytes();
DatagramSocket s = new DatagramSocket();
//
DatagramPacket p = new DatagramPacket(message, msg_length, local, server_port);
s.send(p);//properly able to send data. i receive data to server
for (int i = 0; i <= 20; i++) {
final int value = i;
message = new byte[30000];
p = new DatagramPacket(message,message.length );
s.receive(p); //keeps on waiting here but i am sending data back from server, but it never receives
final byte[] data = p.getData();;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
@Override
public void run() {
progressBar.setProgress(value);
imageView.setImageBitmap(BitmapFactory.decodeByteArray(data,0,data.length));
}
});
}
}
catch(Exception ex)
{
}
}
}
Eclipseのドキュメント:
このソケットからパケットを受信し、引数パックに保存します。パックのすべてのフィールドは、受信したデータに従って設定する必要があります。受信したデータがパケットバッファサイズより長い場合、切り捨てられます。このメソッドは、パケットが受信されるか、タイムアウトが期限切れになるまでブロックします。
「s.receive(p);
」コマンドは、データを受信するか、setSoTimeout(timeout)で設定されたタイムアウトが終了するまでスレッドをブロックします。
コミュニケーションをとるために2つのクラスを作成しました。最初のUDPサーバー:
import Java.net.DatagramPacket;
import Java.net.DatagramSocket;
import Android.annotation.SuppressLint;
import Android.content.Intent;
import Android.os.AsyncTask;
import Android.os.Build;
public class UDP_Server
{
private AsyncTask<Void, Void, Void> async;
private boolean Server_aktiv = true;
@SuppressLint("NewApi")
public void runUdpServer()
{
async = new AsyncTask<Void, Void, Void>()
{
@Override
protected Void doInBackground(Void... params)
{
byte[] lMsg = new byte[4096];
DatagramPacket dp = new DatagramPacket(lMsg, lMsg.length);
DatagramSocket ds = null;
try
{
ds = new DatagramSocket(Main.SERVER_PORT);
while(Server_aktiv)
{
ds.receive(dp);
Intent i = new Intent();
i.setAction(Main.MESSAGE_RECEIVED);
i.putExtra(Main.MESSAGE_STRING, new String(lMsg, 0, dp.getLength()));
Main.MainContext.getApplicationContext().sendBroadcast(i);
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (ds != null)
{
ds.close();
}
}
return null;
}
};
if (Build.VERSION.SDK_INT >= 11) async.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else async.execute();
}
public void stop_UDP_Server()
{
Server_aktiv = false;
}
}
受信したデータをBroadcastReceiverに送信すると、データを使って何でもできます。
そして今、私のクライアントはデータを送信します。このコードではブロードキャストを送信していますが、直接IPなどに送信するためのコードを変更しても問題ないと思います。
import Java.net.DatagramPacket;
import Java.net.DatagramSocket;
import Android.annotation.SuppressLint;
import Android.os.AsyncTask;
import Android.os.Build;
public class UDP_Client
{
private AsyncTask<Void, Void, Void> async_cient;
public String Message;
@SuppressLint("NewApi")
public void NachrichtSenden()
{
async_cient = new AsyncTask<Void, Void, Void>()
{
@Override
protected Void doInBackground(Void... params)
{
DatagramSocket ds = null;
try
{
ds = new DatagramSocket();
DatagramPacket dp;
dp = new DatagramPacket(Message.getBytes(), Message.length(), Main.BroadcastAddress, Main.SERVER_PORT);
ds.setBroadcast(true);
ds.send(dp);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (ds != null)
{
ds.close();
}
}
return null;
}
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
}
};
if (Build.VERSION.SDK_INT >= 11) async_cient.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else async_cient.execute();
}
次に、メインクラスからクラスをインスタンス化する方法を示します。
//start UDP server
Server = new UDP_Server();
Server.runUdpServer();
//UDP Client erstellen
Client = new UDP_Client();
そして、ここでクライアントとメッセージを送信する方法。
//Set message
Client.Message = "Your message";
//Send message
Client.NachrichtSenden();
UDP_Serverを停止するには、Server.Server_aktivをfalseに設定するだけです。
上記のメッセージを設定するには、「setMessage(String message)」メソッドなどを書くこともできます。
ここでは、この投稿で、デバイス間または同じモバイルの2つのアプリケーション間でソケットを確立するための詳細なコードを見つけます。
以下のコードをテストするには、2つのアプリケーションを作成する必要があります。
両方のアプリケーションのマニフェストファイルで、以下の権限を追加します
<uses-permission Android:name="Android.permission.INTERNET" />
最初のアプリコード:UDPクライアントソケット
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<TableRow
Android:id="@+id/tr_send_message"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:gravity="center"
Android:layout_alignParentLeft="true"
Android:layout_alignParentStart="true"
Android:layout_alignParentTop="true"
Android:layout_marginTop="11dp">
<EditText
Android:id="@+id/edt_send_message"
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_weight="1"
Android:layout_marginRight="10dp"
Android:layout_marginLeft="10dp"
Android:hint="Enter message"
Android:inputType="text" />
<Button
Android:id="@+id/btn_send"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_marginRight="10dp"
Android:text="Send" />
</TableRow>
<ScrollView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_alignParentLeft="true"
Android:layout_alignParentStart="true"
Android:layout_below="@+id/tr_send_message"
Android:layout_marginTop="25dp"
Android:id="@+id/scrollView2">
<TextView
Android:id="@+id/tv_reply_from_server"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical" />
</ScrollView>
</RelativeLayout>
DPClientSocketActivity.Java
import Android.os.Bundle;
import Android.os.Handler;
import Android.support.v7.app.AppCompatActivity;
import Android.view.View;
import Android.widget.Button;
import Android.widget.EditText;
import Android.widget.TextView;
import Java.io.IOException;
import Java.net.DatagramPacket;
import Java.net.DatagramSocket;
import Java.net.InetAddress;
/**
* Created by Girish Bhalerao on 5/4/2017.
*/
public class UDPClientSocketActivity extends AppCompatActivity implements View.OnClickListener {
private TextView mTextViewReplyFromServer;
private EditText mEditTextSendMessage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button buttonSend = (Button) findViewById(R.id.btn_send);
mEditTextSendMessage = (EditText) findViewById(R.id.edt_send_message);
mTextViewReplyFromServer = (TextView) findViewById(R.id.tv_reply_from_server);
buttonSend.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_send:
sendMessage(mEditTextSendMessage.getText().toString());
break;
}
}
private void sendMessage(final String message) {
final Handler handler = new Handler();
Thread thread = new Thread(new Runnable() {
String stringData;
@Override
public void run() {
DatagramSocket ds = null;
try {
ds = new DatagramSocket();
// IP Address below is the IP address of that Device where server socket is opened.
InetAddress serverAddr = InetAddress.getByName("xxx.xxx.xxx.xxx");
DatagramPacket dp;
dp = new DatagramPacket(message.getBytes(), message.length(), serverAddr, 9001);
ds.send(dp);
byte[] lMsg = new byte[1000];
dp = new DatagramPacket(lMsg, lMsg.length);
ds.receive(dp);
stringData = new String(lMsg, 0, dp.getLength());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ds != null) {
ds.close();
}
}
handler.post(new Runnable() {
@Override
public void run() {
String s = mTextViewReplyFromServer.getText().toString();
if (stringData.trim().length() != 0)
mTextViewReplyFromServer.setText(s + "\nFrom Server : " + stringData);
}
});
}
});
thread.start();
}
}
2番目のアプリコード-UDPサーバーソケット
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<Button
Android:id="@+id/btn_stop_receiving"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="STOP Receiving data"
Android:layout_alignParentTop="true"
Android:enabled="false"
Android:layout_centerHorizontal="true"
Android:layout_marginTop="89dp" />
<ScrollView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_below="@+id/btn_stop_receiving"
Android:layout_marginTop="35dp"
Android:layout_alignParentLeft="true"
Android:layout_alignParentStart="true">
<TextView
Android:id="@+id/tv_data_from_client"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical" />
</ScrollView>
<Button
Android:id="@+id/btn_start_receiving"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="START Receiving data"
Android:layout_alignParentTop="true"
Android:layout_centerHorizontal="true"
Android:layout_marginTop="14dp" />
</RelativeLayout>
DPServerSocketActivity.Java
import Android.os.Bundle;
import Android.os.Handler;
import Android.support.v7.app.AppCompatActivity;
import Android.view.View;
import Android.widget.Button;
import Android.widget.TextView;
import Java.io.IOException;
import Java.net.DatagramPacket;
import Java.net.DatagramSocket;
/**
* Created by Girish Bhalerao on 5/4/2017.
*/
public class UDPServerSocketActivity extends AppCompatActivity implements View.OnClickListener {
final Handler handler = new Handler();
private Button buttonStartReceiving;
private Button buttonStopReceiving;
private TextView textViewDataFromClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonStartReceiving = (Button) findViewById(R.id.btn_start_receiving);
buttonStopReceiving = (Button) findViewById(R.id.btn_stop_receiving);
textViewDataFromClient = (TextView) findViewById(R.id.tv_data_from_client);
buttonStartReceiving.setOnClickListener(this);
buttonStopReceiving.setOnClickListener(this);
}
private void startServerSocket() {
Thread thread = new Thread(new Runnable() {
private String stringData = null;
@Override
public void run() {
byte[] msg = new byte[1000];
DatagramPacket dp = new DatagramPacket(msg, msg.length);
DatagramSocket ds = null;
try {
ds = new DatagramSocket(9001);
//ds.setSoTimeout(50000);
ds.receive(dp);
stringData = new String(msg, 0, dp.getLength());
updateUI(stringData);
String msgToSender = "Bye Bye ";
dp = new DatagramPacket(msgToSender.getBytes(), msgToSender.length(), dp.getAddress(), dp.getPort());
ds.send(dp);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ds != null) {
ds.close();
}
}
}
});
thread.start();
}
private void updateUI(final String stringData) {
handler.post(new Runnable() {
@Override
public void run() {
String s = textViewDataFromClient.getText().toString();
if (stringData.trim().length() != 0)
textViewDataFromClient.setText(s + "\n" + "From Client : " + stringData);
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_start_receiving:
startServerSocket();
buttonStartReceiving.setEnabled(false);
buttonStopReceiving.setEnabled(true);
break;
case R.id.btn_stop_receiving:
//Add logic to stop server socket yourself
buttonStartReceiving.setEnabled(true);
buttonStopReceiving.setEnabled(false);
break;
}
}
}