您的位置:首页 > 移动开发 > Android开发

android项目中,测试Socket连接时遇到的问题

2016-04-22 14:54 633 查看
在学习完一个项目之余,随意找了本书阅读,看到了对AsyncTask及另外几种实现线程的方式,由于讲的比较新颖,于是就放下书本,开始码代码了。没想到,这一写,还真的就碰到了以前不曾注意的问题。
1.AsyncTask在一个项目中只能同时运行一个。
2.byte[]的实例化伴随着其中的byte的实例化。

由于是在闲暇时间完成的,所以仅仅只是一个简单的测试程序,仅此而已。

在这次测试中是利用Socket进行两台android设备之间的通信,完成了两个项目——一个是模拟服务器,一个是模拟客户端。
第一个项目(服务器)的代码:
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

import android.app.Activity;
import android.app.AlertDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

private TextView text; // 接收到的消息
private EditText edit; // 发送消息的编辑框
private Button send; // 发送按钮
private ServerSocket server; // 服务器
private Socket client; // 连接的客户端
BufferedInputStream bis; // 输入流
PrintStream ps; // 输出流

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.text = (TextView) findViewById(R.id.text);
this.edit = (EditText) findViewById(R.id.edit);
this.send = (Button) findViewById(R.id.send);

// 接收数据的线程启动
AsyncTask<Void, byte[], Void> read = new ReadDataThread();
read.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

// 为发送按钮设置点击事件
this.send.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String str = edit.getText().toString();
new SendDataThread().execute(str);
}
});
}

/**
* 发送数据线程
*
* @author yufeng
*
*/
private class SendDataThread extends AsyncTask<String, String, Void> {

@Override
protected Void doInBackground(String... params) {
if (client != null) {
ps.print(params[0]);
} else {
publishProgress("无客户端连接,请等待。。。");
}
return null;
}

@Override
protected void onProgressUpdate(String... values) {
new AlertDialog.Builder(MainActivity.this).setTitle("提示")
.setMessage(values[0]).setNeutralButton("取消", null)
.create().show();
}
}

/**
* 接收数据数据线程
*
* @author yufeng
*
*/
private class ReadDataThread extends AsyncTask<Void, byte[], Void> {

@Override
protected Void doInBackground(Void... params) {

try { // 初始化相关参数
server = new ServerSocket(8888);
client = server.accept();
System.out.println("客户端连接成功");
bis = new BufferedInputStream(client.getInputStream());
ps = new PrintStream(client.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}

int len;
byte[] b;
while (client != null) {
try {
len = bis.available();
if (len > 0) {
b = new byte[len];
bis.read(b);
publishProgress(b);
b = null;
}
} catch (IOException e) {
e.printStackTrace();
}
SystemClock.sleep(1000);
}
return null;
}

@Override
protected void onProgressUpdate(byte[]... values) {
byte[] by = values[0];
String msg = new String(by);
text.setText("消息:" + msg);
}
}

@Override
protected void onStop() {
super.onStop();
try {
if (bis != null) {
bis.close();
}
if (ps != null) {
ps.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

该项目就一个类——MainActivity,由于布局比肩简单粗糙,因此省略。
该类中主要就是SendDataThread和ReadDataThread这两个内部类,这两个类都继承自AsyncTask类,项目运行后ReadDataThread就执行,一直等待客户端的连接,之后循环进行数据的读取与UI更新。

第二个项目(客户端)的代码:
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;

import android.app.Activity;
import android.app.AlertDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

private TextView text; // 接受到的消息
private EditText edit, ip; // 发送的消息编辑框,IP地址编辑框
private Button send, setIp; // 发送消息按钮,设置IP按钮
private Socket client; // 客户端
BufferedInputStream bis; // 输入流
PrintStream ps; // 输出流
private String strIp = null; // IP地址设置

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.text = (TextView) findViewById(R.id.text);
this.edit = (EditText) findViewById(R.id.edit);
this.send = (Button) findViewById(R.id.send);
this.ip = (EditText) findViewById(R.id.ip);
this.setIp = (Button) findViewById(R.id.setIp);

// 为发送按钮设置点击事件
this.send.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String str = edit.getText().toString();
new SendDataThread().execute(str);
}
});

// 为IP设置按钮设置点击事件
this.setIp.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
strIp = ip.getText().toString().trim();
// 为了避免测试时在IP设置之前操作该按钮,在xml文件中将发送按钮设置为了不可见
send.setVisibility(View.VISIBLE);
// 执行消息发送线程
AsyncTask<Void, byte[], Void> read = new ReadDataThread();
read.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
});
}

/**
* 发送数据
*
* @author yufeng
*
*/
private class SendDataThread extends AsyncTask<String, String, Void> {

@Override
protected Void doInBackground(String... params) {
if (client != null && strIp != null) {
ps.print(params[0]);
} else {
publishProgress("尚未成功连接服务器");
}
return null;
}

@Override
protected void onProgressUpdate(String... values) {
new AlertDialog.Builder(MainActivity.this).setTitle("提示")
.setMessage(values[0]).setNeutralButton("取消", null)
.create().show();
}
}

/**
* 接收数据
*
* @author yufeng
*
*/
private class ReadDataThread extends AsyncTask<Void, byte[], Void> {

@Override
protected Void doInBackground(Void... params) {
try { // 初始化相关参数
if (client == null) {
client = new Socket(strIp, 8888);
}
bis = new BufferedInputStream(client.getInputStream());
ps = new PrintStream(client.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}

int len;
byte[] b;
while (client != null) {
try {
len = bis.available();
if (len > 0) {
b = new byte[len];
bis.read(b);
publishProgress(b);
b = null;
}
} catch (IOException e) {
e.printStackTrace();
}
SystemClock.sleep(1000);
}
return null;
}

@Override
protected void onProgressUpdate(byte[]... values) {
byte[] by = values[0];
String msg = new String(by);
text.setText("消息:" + msg);
}
}

@Override
protected void onStop() {
super.onStop();
try {
if (bis != null) {
bis.close();
}
if (ps != null) {
ps.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

该项目与服务器大同小异。在客户端的界面中多了一个IP设置,除此之外,两个项目大致相同。
在IP设置正确的前提下,能实现客户端与服务器端的聊天(姑且称之为聊天吧),测试目的也基本完成。

在上面列举的面临的两个问题,第一个问题是利用线程池解决,即执行时将execute()方法替换为executeOnExecutor()方法。
第二个问题发生在数据获取、保存时,原本思路是申请一个足够大的byte[],这就导致输出数据时会附带一串无意义的乱码,解决方式如代码。
测试时间仓促,仅为实现联通,难免有所遗漏,请留言告知。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: