Andriod(一)Andriod手机(客户端)和电脑(服务器)之间的简单通信

[size=medium]主要是实现手机和电脑之间互发信息,并显示在各自的界面。
一、Android手机(客户端)
分为2个界面,一个连接界面(MyClientActivity),用来输入要连接的服务器的IP地址和端口号,确认成功后进入下一个页面,客户端界面(LoginActivity)
连接界面:[/size][img]http://dl.iteye.com/upload/attachment/0064/6011/e865419d-84e9-3c25-a740-4872dc4f6c6e.jpg[/img]
public class MyClientActivity extends Activity {
// 文本框和按钮对象
EditText edit_1;
EditText edit_2;
Button button;
// String 数组,用来存储服务器连接的ip地址和端口号
String[] str = new String[2];
public void onCreate(Bundle savedInstanceState) {
// 显示当前界面
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获得文本框和按钮对象
edit_1 = (EditText) this.findViewById(R.id.edit_text1);
edit_2 = (EditText) this.findViewById(R.id.edit_text2);
button = (Button) this.findViewById(R.id.button);
// 给按钮添加监听器。点击发送按钮后,将文本框内容发送到第二个页面
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// 获得文本框内容
String ip = edit_1.getText().toString();
String port = edit_2.getText().toString();
// 添加ip和端口号到数组
str[0] = ip;
str[1] = port;
// 实现页面跳转
Intent intent = new Intent(MyClientActivity.this,
LoginActivity.class);
// 将ip和端口号传递到第二个页面
intent.putExtra("str", str);
// 进行页面跳转
MyClientActivity.this.startActivity(intent);

}
});

}
}

[size=medium]
客户端显示界面:[/size][img]http://dl.iteye.com/upload/attachment/0064/6013/bbf85084-e533-3acb-8769-d409f77dc2de.jpg[/img]
public class LoginActivity extends Activity {
// 客户端套接
Socket client;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
// 发送按钮
Button button;
// 显示信息的区域
final EditText textArea;
// 写出信息的文本框
final EditText textField;

try {
// 先获取ip和端口号建立客户端套接,即获取第一个页面传递过来数组的信息
String[] str = this.getIntent().getStringArrayExtra("str");
// 将port转换为int型
int port = Integer.parseInt(str[1]);
// 建立连接
client = new Socket(str[0], port);
System.out.println("连接成功!");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 显示界面
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
// 获取文本框和按钮对象
button = (Button) this.findViewById(R.id.button);
textArea = (EditText) this.findViewById(R.id.text_area);
textField = (EditText) this.findViewById(R.id.text_field);
// 给按钮添加监听器
button.setOnClickListener(new OnClickListener() {
// 重写方法:点击按钮时,发送信息
public void onClick(View arg0) {
// 获取信息
String str = textField.getText().toString();
try {
// 获取输出流
OutputStream ous = client.getOutputStream();
// 写出信息
ous.write(str.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
// 清空文本框
textField.setText("");
}
});
// 启动线程,读取数据
ClientThread ct = new ClientThread(client, textArea);
ct.start();
}
}

[size=medium]然后有一个客户端读取信息的线程。[/size]
public class ClientThread extends Thread {

// 重载构造函数,传递套接和文本区域过来
EditText textArea;
private InputStream ins;

public ClientThread(Socket client, EditText textArea) {
try {
// 获得输入流
ins = client.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
this.textArea = textArea;
}

public void run() {
while (true) {
// 不断的调用读的方法
read();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public void read() {

try {// 读取数据
while (ins.available() > 0) {// 当有数据可读时,读取数据到字节数组b
// 创建一个字符串缓冲区
StringBuffer stb = new StringBuffer();
char c;
while (ins.available() > 0) {
// 读取个服务器发来的一个字节
int i = ins.read();
// 将输入的一个字节转化为char类型
c = (char) i;
// 将得到的字符加入字符串缓冲区
stb.append(c);
}
// 将读入的字节转为字符串
final String str = stb.toString();
textArea.post(new Runnable() {
public void run() {
textArea.append("收到来自服务器信息:" + str
+ "\t\n");
}
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

[size=medium]因为要在线程中改变主界面,EditText中的text值,而Andriod的线程又是不安全的(更新UI只能是主线程的工作,子线程更新UI是线程不安全的,因为子线程可能会有多个,多个同时操作一个控件可能会有麻烦发生,所以android就限定了只有主线程可以操作UI。)故而采用了一个办法来解决这个问题.[/size]
textArea.post(new Runnable() {
public void run() {
textArea.append("收到来自服务器信息:" + str
+ "\t\n");
}
});


[size=medium]main.xml(设置登录前界面(连接界面MyClientActivity)上的组件和其位置)[/size]
  <?xml version="1.0" encoding="utf-8" ?> 
- <AbsoluteLayout android:id="@+id/widget0" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:id="@+id/text_view1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="IP号" android:layout_x="10px" android:layout_y="47px" />
<EditText android:id="@+id/edit_text1" android:layout_width="150dip" android:layout_height="wrap_content" android:textSize="18sp" android:layout_x="89px" android:layout_y="35px" />
<TextView android:id="@+id/text_view2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="端口号" android:layout_x="12px" android:layout_y="129px" />
<EditText android:id="@+id/edit_text2" android:layout_width="150dip" android:layout_height="wrap_content" android:textSize="18sp" android:layout_x="90px" android:layout_y="120px" />
<Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="enter" android:layout_x="260px" android:layout_y="78px" />
</AbsoluteLayout>

[size=medium]login.xml(设置成功登录后界面(客户端界面LoginActivity)上的组件和其位置)[/size]
<?xml version="1.0" encoding="utf-8" ?> 
- <AbsoluteLayout android:id="@+id/widget35" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android">
<EditText android:id="@+id/text_area" android:layout_width="300dip" android:layout_height="wrap_content" android:background="#c0c0c0ff" android:textSize="18sp" android:layout_x="13px" android:layout_y="112px" />
<EditText android:id="@+id/text_field" android:layout_width="200dip" android:layout_height="wrap_content" android:textSize="18sp" android:layout_x="18px" android:layout_y="35px" />
<Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="send msg" android:layout_x="242px" android:layout_y="34px" />
</AbsoluteLayout>

[size=medium]二、电脑(服务器端)
显示界面:[/size][img]http://dl.iteye.com/upload/attachment/0064/6018/fd1d04c6-e9e1-337b-a017-45a98d4983a4.jpg[/img]
[size=medium]服务器端界面:[/size]
public class ServerUI extends javax.swing.JFrame {
TextArea ta;
java.net.Socket s;
int count;
javax.swing.JTextField jtf;

public static void main(String args[]) {
ServerUI ms = new ServerUI();
// 显示服务器界面
ms.initServerUI();
// 创建一个服务器,为客户端的连接 随机分配一个端口号:0~65535之间均可
ms.setServer(9995);
System.out.println("服务器创建成功");
}

/**
* 创建服务器的方法
*
* @param port 端口号
*/
public void setServer(int port) {
try {
// 创建一个服务器对象,如果端口号超出范围或者已经被占用,则抛出异常
java.net.ServerSocket so = new java.net.ServerSocket(port);
// 让服务器进入循环等待状态
while (true) {// 等待客户机连接,连接后生成一个Socket对象,如果没有客户机连接进来则程序在此阻塞
s = so.accept();
System.out.println("连接成功:"+s.getLocalSocketAddress());
// 创建ServerThread线程对象,并启动线程
ServerThread st = new ServerThread(s, ta);
Thread th = new Thread(st);
th.start();

}
} catch (IOException e1) {
e1.printStackTrace();
}
}
/**
* 服务器界面
*/
public void initServerUI() {
// 创建窗体对象
ServerUI serverUI = new ServerUI();
// 设置各种属性
serverUI.setTitle("服务器显示界面");
serverUI.setBackground(Color.white);
serverUI.setSize(420, 500);
serverUI.setLayout(null);
serverUI.setDefaultCloseOperation(3);
// 添加一个显示纯文本的多行区域(40行,40列),用来显示客户端发送过来的信息
ta = new TextArea("", 10, 10, TextArea.SCROLLBARS_BOTH);
ta.setBackground(Color.gray);
ta.setBounds(2, 2, 400, 400);
// 设置为只读,不可以编辑
ta.setEditable(false);
serverUI.add(ta);
// 添加一个单行文本区域,用来输入要发送的信息
jtf = new javax.swing.JTextField(15);
jtf.setBounds(2, 405, 300, 40);
serverUI.add(jtf);
// 添加一个发送按钮
javax.swing.JButton jb = new javax.swing.JButton("发送!");
jb.setBounds(305, 405, 100, 40);
serverUI.add(jb);
// 给发送按钮添加监听器,当点击它时,发送信息
jb.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
//写入信息:信息发送出去,输入框清空
// 得到输出流
try {
OutputStream ous = s.getOutputStream();
// 获得输入框信息,写出信息
ous.write(jtf.getText().getBytes());
count++;
ous.flush();
// 清空输入框
jtf.setText("");
System.out.println("服务器信息写出成功");
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
serverUI.setVisible(true);
}


}


[size=medium]服务器线程,每接入一个客户端,启动一个线程:[/size]
public class ServerThread implements Runnable {

private Socket s;
private TextArea ta;

// 重写构造函数,传值
public ServerThread(Socket s, TextArea ta) {
this.s = s;
this.ta = ta;
}

public void run() {
// 调用读的方法
read();
}

public void read() {
while (true) {
try {// 不断读取数据
// 创建输入流
InputStream ins = s.getInputStream();
while (ins.available() > 0) {// 当有数据可读时,读取数据到字节数组b
// 创建一个字符串缓冲区
StringBuffer stb = new StringBuffer();
char c;
while (ins.available() > 0) {
// 读取个客户机发来的一个字节
int i = ins.read();
// 将输入的一个字节转化为char类型
c = (char) i;
// 将得到的字符加入字符串缓冲区
stb.append(c);
}
// 将读入的字节转为字符串
String str = stb.toString();
// 将读取到的数据显示到JTextArea中
ta.append("收到来自客户端的信息:" + str + "\t\n");
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}

}

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值