前面服务器和客户端只是进行了简单的通信操作:服务器接收到客户端连接之后
服务器向客户端输出一个字符串,而客户端也只是读取服务器的字符串之后就退出了
而实际 应用中的客户端则可能需要和服务器保持长时间的通信,即服务器
需要不断的读取客户端的数据,并向客户端写入数据;客户端也需要不断的
读取服务器,并向数据库中写入数据。
使用传统BufferedReader的 readLine 方法读取数据时,当该方法成功返回之前,该线程
是阻塞的,程序无法继续进行。所以,服务器应该为每一个Socket开启一个线程,每条线程
负责与一个客户端进行通信。
服务器端:
class ServerThread implements Runnable {
Socket s;
BufferedReader br;
public ServerThread(Socket s) throws IOException {
super();
this.s = s;
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
}
@Override
public void run() {
String content = null;
try {
while ((content = readFromClient()) != null) {
for (Socket s : MultiThreadServer.sockets) {
OutputStream os;
os = s.getOutputStream();
os.write((content + "\n").getBytes("utf-8"));
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private String readFromClient() {
try {
return br.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
public class MultiThreadServer {
public static ArrayList<Socket> sockets = new ArrayList<Socket>();
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(45623);
while (true) {
Socket s = ss.accept();
sockets.add(s);
new Thread(new ServerThread(s)).start();
}
}
}
每当客户端Socket连接到该ServerSocket之后,
程序将对应Socket加入到集合中保存,并为该Socket开启一条线程,负责处理该Socket的
所有通信事务。
客户端:
MultiClient:
public class MultiThreadClient extends Activity {
EditText input;
TextView show;
Button send;
Handler handler;
ClientThread clientThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client_thread);
input = (EditText) findViewById(R.id.input);
show = (TextView) findViewById(R.id.show);
send = (Button) findViewById(R.id.send);
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 如果消息来自于子线程
if (msg.what == 0x123) {
// 将读取的内容追加显示在文本中
show.append("\n" + msg.obj.toString());
}
}
};
clientThread = new ClientThread(handler);
// 客户端启动ClientThread线程创建网络连接、读取来自服务器的数据
new Thread(clientThread).start();
send.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 当用户按下发送按钮后,将用户输入的数据封装成Message,然后发送给子线程的handler
Message msg = new Message();
msg.what = 0x345;
msg.obj = input.getText().toString();
clientThread.revHandler.sendMessage(msg);
input.setText("");
}
});
}
}
ClientThread:
public class ClientThread implements Runnable {
private Socket s;
// 定义向UI线程发送消息的Handler对象。
private Handler handler;
// 定义接收UI线程的消息的Handler对象.
public Handler revHandler;
// 该线程所处理的Socket所对用的流对象
BufferedReader br;
OutputStream os;
public ClientThread(Handler handler) {
super();
this.handler = handler;
}
@Override
public void run() {
try {
s = new Socket("192.168.3.12", 45623);
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
os = s.getOutputStream();
// 启动一条子线程
new Thread() {
public void run() {
String content = null;
// 不断读取Socket输入流中的内容
try {
while ((content = br.readLine()) != null) {
// 每当读到来自服务器的数据之后,发送消息通知程序界面显示该数据
Message msg = new Message();
msg.what = 0x123;
msg.obj = content;
handler.sendMessage(msg);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
};
}.start();
// 为当前线程初始化Looper
Looper.prepare();
// 创建revhandler对象
revHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 接收UI线程中用户输入的数据
if (msg.what == 0x345) {
// 将用户在文本框内输入的内容写入网络
try {
os.write((msg.obj.toString() + "\r\n").getBytes("utf-8"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
Looper.loop();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Android---51---加入多线程进行Socket通信
原文:http://blog.csdn.net/u013476556/article/details/46291661