功能:
只支持多个客户端同时在线聊天功能。
源码:
MultiThreadServer
MyServer.java
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class MyServer {
public static ArrayList<Socket> socketList = new ArrayList<Socket>();
final static int LISTEN_PORT = 6889;
public static void main(String[] args){
ServerSocket ss = null;
try {
ss = new ServerSocket(LISTEN_PORT);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while(true){
try {
System.out.println("listening...");
Socket s = ss.accept();
socketList.add(s);
//deal with each connection in a thread
new Thread(new ServerThread(s)).start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
ServerThread.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.SocketAddress;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class ServerThread implements Runnable{
//the connect socket dealt with by current thread
Socket s =null;
//the inputstream of the current thread's socket
BufferedReader br = null;
public ServerThread(Socket s){
this.s = s;
try {
br = new BufferedReader(new InputStreamReader(s.getInputStream(),"utf-8"));
System.out.println("excute the constructor of the thread...");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run(){
String send_msg = null;
String recv_msg = null;
System.out.println("begin while for...");
//read msg from client by using a while loop
while((recv_msg = readFromClient())!=null){
for(Socket s : MyServer.socketList){//send msg to every client
try {
OutputStream os = s.getOutputStream();
//msg from addr
//SocketAddress remote_addr = s.getRemoteSocketAddress();
send_msg = "(" + getCurrentTime() + ")" + recv_msg;//
System.out.println(send_msg);
os.write((send_msg+"\r\n").getBytes("utf-8"));//send msg to each client
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private String readFromClient(){
try {
String read_msg = null;
read_msg = br.readLine();
return read_msg;
} catch (IOException e) {
// TODO Auto-generated catch block
//
MyServer.socketList.remove(s);
e.printStackTrace();
}
return null;
}
private String getCurrentTime(){
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sd.format(calendar.getTime());
return time;
}
}
MultiThreadClient
MultiThreadClient.java
package com.example.multithreadclient;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MultiThreadClient extends Activity {
final static int RECV_MSG = 0x1234;
final static int SEND_MSG = 0x1235;
final static String server_ip = "172.27.35.1";
final static int server_port = 6889;
//
TextView show;
EditText input;
Button send;
Handler handler;
ClientThread clientThread;
//
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_multi_thread_client);
//
show = (TextView) findViewById(R.id.show);
input = (EditText) findViewById(R.id.input);
send = (Button) findViewById(R.id.send);
handler = new Handler(){
@Override
public void handleMessage(Message msg){
//show recv_msg in the textview
if(msg.what == RECV_MSG){
String recv_msg = msg.obj.toString();
// show.setText(recv_msg);
show.append("\n" + recv_msg);
}
}
};
clientThread = new ClientThread(handler);
new Thread(clientThread).start();
//pro:if the thread is not started ,but send button is clicked ?
//send the msg in the input edittext to the recvHandler
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Message msg = new Message();
msg.what = SEND_MSG;
msg.obj = input.getText().toString();//msg content
clientThread.recvHandler.sendMessage(msg);
input.setText("");//clear the input edit after send
}
});
//
}
}
ClientThread.java
package com.example.multithreadclient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
//all operation about socket are in the thread
public class ClientThread implements Runnable{
Socket s = null;
Handler handler = null;//send msg to UI
Handler recvHandler = null;//recv msg from UI
InputStream is = null;
BufferedReader br = null;
OutputStream os = null;
public ClientThread(Handler handler){
this.handler = handler;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
s = new Socket(MultiThreadClient.server_ip,MultiThreadClient.server_port);
//do not put the following statements in the handleMessgae or child thread run block
is = s.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
os = s.getOutputStream();
//
//child thread : read data from the server
new Thread(){
@Override
public void run(){
String recv_msg = null;
while((recv_msg = readFromServer())!= null){
Message msg = new Message();
msg.what = MultiThreadClient.RECV_MSG;
msg.obj = recv_msg;
handler.sendMessage(msg);//send the received msg to UI
}
}
}.start();
Looper.prepare();
recvHandler = new Handler(){
@Override
public void handleMessage(Message msg){
//send msg to the server
String send_msg = null;
if(msg.what == MultiThreadClient.SEND_MSG){
try {
//本地地址:消息内容
send_msg = s.getLocalAddress().toString() + ":" + msg.obj.toString()
+ "\r\n";
os.write(send_msg.getBytes("utf-8"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
Looper.loop();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private String readFromServer() {
// TODO Auto-generated method stub
try {
return br.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
activity_multi_thread_client.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<!-- show msg from server -->
<!-- TextView长文本,有滚动条 -->
<ScrollView
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
>
<TextView
android:id="@+id/show"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffff"
android:textSize="14dp"
android:textColor="#ff00ff"
android:layout_weight="1"
/>
</ScrollView>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<!-- accept user input info -->
<EditText
android:id="@+id/input"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="4"
/>
<Button
android:id="@+id/send"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/send"
/>
</LinearLayout>
</LinearLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.multithreadclient"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.INTERNET"/>
<!-- "adjustResize"该 Activity主窗口总是被调整屏幕的大小以便留出软键盘的空间 -->
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.multithreadclient.MultiThreadClient"
android:label="@string/app_name"
android:windowSoftInputMode="adjustResize"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
测试运行效果:
局域网拓扑图:
搭建局域网:
服务器端:
客户端:
运行结果:
Server:
Client 1:
Client2: