可能现在很多应用中都会用到两个人活着多人互动的界面,当然,对于这个界面,我们别无选择的都会用到客户端以及服务端的交互。
这里主要的思路就是通过客户端接受用户的输入,然后,我们把输入的值通过一个请求发送给服务端,然后再通过一个方式得到服务端返回的数据,当然,这里想要不停的接受客户端的访问,所以在服务端我们必须要把条件设为true。
这里我们做一个简单的客户端界面,当然,这里我们也可以做成像QQ聊天界面那样的界面,然后可以做成一个多人聊天室。(网络聊天室)。
/***
*
* @author William 这里我们要演示的是多线程聊天功能
*
* */
public class AndroidThreadClientActivity extends Activity {
/** Called when the activity is first created. */
// define a key这里我们就是给客户端一个端口,然后让他们进行交互
public static final int PORT = 8080;
//这里的ip地址是在无网的状态下也可以进行连接的ip,那么大家就该知道是什么了吧(虚列机的ip)
public static final String HOST = "10.0.2.2";
private EditText sentText;
private EditText getText;
Socket s;
// create a visible t
// 创建消息对象
Handler handler;
String get_text;
// 设置菜单的listView留言人的数组
// 输出流对象
OutputStream output;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 构建视图控件
getText = (EditText) findViewById(R.id.get);
sentText = (EditText) findViewById(R.id.send);
// 立即与服务端连接
try {
s = new Socket(HOST, PORT);
System.out.println("he is " + s.getInetAddress() + "的用户--->1");
output = s.getOutputStream();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// sendBtn.setOnClickListener((android.view.View.OnClickListener) this);
// 使用类方法创建Handler
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
/* super.handleMessage(msg); */
// 判断是否是子线程传过来的信息
if (msg.what == 3) {
// 将服务器端的消息追加的edittext控件进行显示
System.out.println("这里我是去读线程消息传过来的值------>6");
get_text = msg.obj.toString();
getText.append(get_text);
// 启动子线程,每个线程处理对应的socket
MyThread my = new MyThread(s, handler);
new Thread(my).start();
System.out.println("我已经启动了线程clientthread----------->5");
} else {
System.out.println("不好意思,线程获取错误");
}
}
};
}
public void onAction(View v) {
// 将输入文本框的文本信息写出流
try {
System.out.println("我写的内容是" + sentText.getText().toString());
output.write((sentText.getText().toString() + "\n")
.getBytes("utf-8"));
// output.write(sentText.getText().toString() .getBytes());
System.out.println(sentText.getText().toString());
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
sentText.setText("");
}
}
这里我们把消息实现消息的线程建立成了一个外部类,当然,这里我们也可以建立成一个内部类:
import android.os.Handler;
import android.os.Message;
//这里我开始也以为会有一些问题,那就是我们见过的都是继承Thread,而这里呢?我们这里是直接继承了runable:
public class MyThread implements Runnable{
private Socket s;
private Handler handler;
BufferedReader br = null;
String str;
/**
* to create the funcation
* */
public MyThread(Socket s, Handler h) {
this.s = s;
this.handler = h;
try {
//这里我开始是想要进行测试的,结果发现有问题,所以,还是用下面这种的吧。
一种:
// // deine a inputstream
// InputStream ip = s.getInputStream();
// // define a byte
// byte[] mByte = new byte[1024];
// // input the byte int the
// ip.read(mByte);
//二种:
br = new BufferedReader(new InputStreamReader(
s.getInputStream(), "utf-8"));
System.out.println("str is ------>----->2"+br);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
String content = "haha";
System.out.println("我在run里面了------------>3");
// TODO Auto-generated method stub
// to read the content
//这里我是用的true,当然我只是为了测试,你们就大可不必这样了
while (true) {
System.out.println("我在run里面了------------>4");
//Message message = handler.obtainMessage();
Message message=new Message();
message.what = 3;
message.obj = content;
handler.sendMessage(message);
}
}
}
以上就是一个实现一个简单聊天的客户端过程。
当然,这里呢,我也将服务端的代码贴了出来:
package cn;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class ThreadServer {
// 定义保存所有socket里面的的list
public static List<Socket> socketList = new ArrayList<Socket>();
/**
*
* @author Wiuizm
* */
public static void main(String[] args) {
// 创建serversocket对象,使用端口8080
try {
System.out.println("我在服务端的main方法里面");
ServerSocket ss = new ServerSocket(8080);
// 不断的轮询,然后接受客户端的访问
while (true) {
// 创建socket对象
Socket s = ss.accept();
System.out.println("he is "+s.getInetAddress()+"的用户");
socketList.add(s);
System.out.println(socketList);
// 客户端连接后,我们启动第一条线程,然后开始为客户端服务
new Thread(new serverThreas(s)).start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//这里也可以建立一个内部类或者外部类,当然,我这里是建立了一个外部类,方便看吧,老师也曾经说过,我们把能分开的就分开吧,这样在每一个类里面就不会看到太多的代码量。
//这里是一个外部线程类:
public class serverThreas implements Runnable{
// 定义当前处理线程的socket
Socket s = null;
// 该线程处理的socket所对应的输入流
BufferedReader br = null;
/***
* 构造党法
*
* */
public serverThreas(Socket s) {
System.out.println("我在socketthread里面");
this.s = s;
// 初始化socket对应的输入流
try {
br = new BufferedReader(new InputStreamReader(
s.getInputStream(), "utf-8"));
System.out.println(br);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
// TODO Auto-generated method stub
String content = null;
while ((content = readMessageFormClient()) != null) {
// 遍历socketlist中的每个socket,将读取到的内容行每个socket发送一次
for (Socket s : ThreadServer.socketList) {
// 创建输出流对象
OutputStream output;
try {
output = s.getOutputStream();
output.write((content + "\n").getBytes("utf-8"));
output.flush();
output.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private String readMessageFormClient() {
try {
System.out.println("this content is ----->"+br.readLine());
return br.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
// 如果发生异常
ThreadServer.socketList.remove(s);
e.printStackTrace();
}
return null;
}
}
好了,现在客户端和服务端我们都算有一点思路了,不知道大家看了有清晰一点没?如果有什么不对劲的地方,希望大家还是狠狠的提出来,谢谢。