原创内容,转载请注明原文网址:http://homeqin.cn/a/wenzhangboke/jishutiandi/Android/2019/0929/665.html
一、服务器
常州网站开发建设思路:
首先建立服务器,用一个死轮回等候几何个客户端的持续。一旦有客户端持续,就把客户端增加到鸠合中间,并且启动一个新的线程来连结长持续,监控客户端发来的信息。一旦汲取到有客户端发来的信息,就举行包装后遍历鸠合,把包装好的信息发送给每一个客户端。
代码以下:
/**
* Tcp通信服务器
* @author Devin Chen
*
*/
public class CSServer {
private static final int PORT = 8888;
private List<Socket> mClientList = new ArrayList<Socket>();
private ServerSocket server = null;
private ExecutorService mExecutors = null; // 线程池对象
public static void main(String[] args) {
new CSServer();
}
/**
* 组织方式:使命是启动服务器,等待客户端持续
*/
public CSServer() {
try {
server = new ServerSocket(PORT);
mExecutors = Executors.newCachedThreadPool(); // 建立线程池
System.out.println("服务器已启动,等待客户端持续...");
Socket client = null;
/*
* 用死轮回等待多个客户端的持续,持续一个就启动一个线程举行经管
*/
while (true) {
client = server.accept();
// 把客户端放入鸠合中
mClientList.add(client);
mExecutors.execute(new Service(client)); // 启动一个线程,用以等待从客户端发来的消息
}
} catch (Exception e) {
e.printStackTrace();
}
}
class Service implements Runnable {
private Socket socket;
private BufferedReader in = null;
private String message = "";
public Service(Socket socket) {
this.socket = socket;
try {
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));// 获取输入流对象
// 客户端只要一连到服务器,便发送持续胜利的信息
message = "游戏开发运营服务器地点:" + this.socket.getInetAddress();
this.sendMessage(message);
message = "目前持续总数:" + mClientList.size();
this.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
while (true) {
if ((message = in.readLine()) != null) {
// 当客户端发送的信息为:exit时,封闭持续
if (message.equals("exit")) {
closeSocket();
break;
} else {
// 汲取客户端发过来的信息message,而后转发给客户端。
message = socket.getInetAddress() + ":" + message;
this.sendMessage(message);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 封闭客户端
*
* @throws IOException
*/
public void closeSocket() throws IOException {
mClientList.remove(socket);
in.close();
message = "主机:" + socket.getInetAddress() + "封闭持续\r目前在线:"
+ mClientList.size();
socket.close();
this.sendMessage(message);
}
/**
* 将常州手游开发汲取的消息转发给每一个客户端
*
* @param msg
*/
public void sendMessage(String msg) {
System.out.println(msg);// 先在控制台输出
int count = mClientList.size();
// 遍历客户端鸠合
for (int i = 0; i < count; i++) {
Socket mSocket = mClientList.get(i);
PrintWriter out = null;
try {
out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(mSocket.getOutputStream())),
true);// 建立输出流对象
out.println(msg);// 转发
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
二、Android客户端
思路:
设置权限。
首先开发线程,在线程中持续服务器,并获取输入流和输出流,并用一个死轮回汲取来自服务器的消息,输入流收到消息举行处分,用handler关照给UI线程更新文本框。
编纂框填好消息,干脆点击发送。用获取的输出流发送消息。
代码:
/**
* Android Tcp即时通信客户端
*/
public class MainActivity extends Activity implements Runnable{
private TextView tv_msg = null;
private EditText ed_msg = null;
private Button btn_send = null;
private static final String HOST = "192.168.0.100";//服务器地点
private static final int PORT = 8888;//持续端口号
private Socket socket = null;
private BufferedReader in = null;
private PrintWriter out = null;
//汲取线程发送过来信息,并用TextView追加表现
public Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
tv_msg.append((CharSequence) msg.obj);
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_msg = (TextView) findViewById(R.id.txt_1);
ed_msg = (EditText) findViewById(R.id.et_talk);
btn_send = (Button) findViewById(R.id.btn_send);
btn_send.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
String msg = ed_msg.getText().toString();
if (socket.isConnected()) {//要是服务器持续
if (!socket.isOutputShutdown()) {//要是输出流没有断开
out.println(msg);//点击按钮发送消息
ed_msg.setText("");//清空编纂框
}
}
}
});
//启动常州游戏开发培训线程,持续服务器,并用死轮回等待,汲取服务器发送过来的数据
new Thread(this).start();
}
/**
* 持续服务器
*/
private void connection() {
try {
socket = new Socket(HOST, PORT);//持续服务器
in = new BufferedReader(new InputStreamReader(socket
.getInputStream()));//汲取消息的流对象
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);//发送消息的流对象
} catch (IOException ex) {
ex.printStackTrace();
ShowDialog("持续服务器失利:" + ex.getMessage());
}
}
/**
* 要是持续出现异常,弹出AlertDialog!
*/
public void ShowDialog(String msg) {
new AlertDialog.Builder(this).setTitle("关照").setMessage(msg)
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
}).show();
}
/**
* 读取服务器发来的信息,并通过Handler发给UI线程
*/
public void run() {
connection();// 持续到服务器
try {
while (true) {//死轮回保卫,监控服务器发来的消息
if (!socket.isClosed()) {//要是服务器没相封闭
if (socket.isConnected()) {//持续平常
if (!socket.isInputShutdown()) {//要是输入流没有断开
String getLine;
if ((getLine = in.readLine()) != null) {//读取汲取的信息
getLine += "\r";
Message message=new Message();
message.obj=getLine;
mHandler.sendMessage(message);//关照UI更新
} else {
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行效果:
要是要扩大优化成一个有模有样的即时通信对象。思量发发送的消息用json举行格式化,包括用户昵称和图片地点等等,服务器收到后分析,在增加上光阴等举行从新包装。客户端收到消息,一样举行分析,装载到粉饰好的listview中间。
上篇:上一篇:安卓线程handler用法
下篇:下一篇:Android 一套完备的 Socket 办理计划