Android 基于TCP多线程通信实现群聊天的功能
1.TCP多线程原理图

2.实现方法
(1)服务器端



(2)客户端

3.java后台代码
主界面
package com.lucky.test50socket2; import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView; public class MainActivity extends AppCompatActivity {
EditText editText;
TextView textView2;
Button button1;
ClientThread clientThread; //handler实现页面与Socket的交互,handler获取ClientThread中发送的message
@SuppressLint("HandlerLeak")
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what==0x01){
textView2.setText(msg.obj.toString());
}
}
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText=findViewById(R.id.editText);
textView2=findViewById(R.id.textView2);
button1=findViewById(R.id.button);
clientThread=new ClientThread(handler); //实例化ClientThread
new Thread(clientThread).start(); //开启客户端的线程
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Message message=new Message(); //实例化一个message
message.what=0x02; //设置message的代号
message.obj=editText.getText().toString();//设置message的内容
ClientThread.handlerrev.handleMessage(message); //调用ClientThread的成员对象的方法,向服务器发送消息
}
}); }
}
服务器
package com.lucky.myserver; import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List; public class Myserver {
public static List<Socket> list; //定义一个存放socket的集合
public static void main(String[] args) throws IOException {
ServerSocket serverSocket=new ServerSocket(30004); //实例化一个服务器套接字
//while设置为死循环,等待客户端的socket请求的到来
while (true){
Socket socket=serverSocket.accept(); //获取套接字
list=new ArrayList<>();
list.add(socket);
ServerThead serverThead=new ServerThead(socket); //调用自建的ServerThead
new Thread(serverThead).start(); //启动线程
}
}
}
服务器线程
package com.lucky.myserver; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket; public class ServerThead implements Runnable {
private Socket socket;
InputStream inputStream; //输入流
OutputStream outputStream;//输出流
BufferedReader bufferedReader;
//构造方法
public ServerThead(Socket socket) throws IOException {
this.socket=socket;
inputStream=socket.getInputStream(); //获取输入流
bufferedReader=new BufferedReader(new InputStreamReader(inputStream,"utf-8")); } @Override
public void run() {
String str;
while ((str=readData())!=null){
for (Socket socket1 : Myserver.list) {
try {
outputStream=socket1.getOutputStream();
PrintStream printStream=new PrintStream(outputStream);
printStream.println(socket.getInetAddress()+":"+str);
} catch (IOException e) {
e.printStackTrace();
}
}
}
} private String readData(){
try {
return bufferedReader.readLine();
} catch (IOException e) {
Myserver.list.remove(socket); //删除套接字,避免占用内存
return null;
}
}
}
客户端
package com.lucky.test50socket2; import android.annotation.SuppressLint;
import android.os.Looper;
import android.os.Message; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.logging.Handler; public class ClientThread implements Runnable {
android.os.Handler handler1; //天坑:注意要导入android.os.Handler,handler要两种类型
InputStream inputStream;
OutputStream outputStream;
BufferedReader bufferedReader;
static android.os.Handler handlerrev; //构造方法
public ClientThread(android.os.Handler handler){
this.handler1=handler;
} @SuppressLint("HandlerLeak")
@Override
public void run() {
try {
Socket socket=new Socket("192.168.228.2",30004); //连接服务器
inputStream=socket.getInputStream();//实例化输入流
bufferedReader=new BufferedReader(new InputStreamReader(inputStream,"GBK"));
new Thread(){
@Override
public void run() {
String string;
try {
while ((string=bufferedReader.readLine())!=null){
Message message=new Message(); //实例化一个消息,通过handler发送到前台
message.what=0x01; //数据的代号
message.obj=string; //发送的数据
//信息回传给主线程(主界面)显示
handler1.sendMessage(message);
}
}catch (IOException e){
e.printStackTrace();
}
}
}.start();
/*
* 说明:如果要在非主线程中创建Handler对象,首先需要使用Looper类的prepare()方法来初始化一个Looper对象,
* 然后创建Handler对象,再使用Looper类的loop()方法启动Looper,从消息队列中获取和处理消息。
*/
Looper.prepare(); //准备handler
outputStream=socket.getOutputStream();//实例化输出流
handlerrev=new android.os.Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what==0x02){ //根据msg是否是需要发送的消息,若是,执行以下操作
String str=msg.obj.toString();
PrintStream printStream=new PrintStream(outputStream);
printStream.println(str); //将消息数据发送到服务器
}
}
};
Looper.loop(); //这句代码可以理解为循环执行run方法(最外层的run)
} catch (IOException e) {
e.printStackTrace();
}
}
}
Android 基于TCP多线程通信实现群聊天的功能的更多相关文章
- Android基于XMPP Smack openfire 开发的聊天室
Android基于XMPP Smack openfire 开发的聊天室(一)[会议服务.聊天室列表.加入] http://blog.csdn.net/lnb333666/article/details ...
- 链路的有效性检测 及 基于TCP的通信为什么需要RETRY
一.链路的有效性检测 当网络发生单通.连接被防火墙Hang住.长时间GC或者通信线程发生非预期异常时,会导致链路不可用且不易被及时发现. 特别是异常发生在凌晨业务低谷期间,当早晨业务高峰期到来时,由于 ...
- Android基于TCP的局域网聊天通信
概述 在同一局域网内,两台设备通过TCP进行通信聊天. 详细 代码下载:http://www.demodashi.com/demo/10567.html 一.准备工作 开发环境 jdk1.8 Ecli ...
- 网络编程应用:基于TCP协议【实现一个聊天程序】
要求: 基于TCP协议实现一个聊天程序,客户端发送一条数据,服务器端发送一条数据 客户端代码: package Homework1; import java.io.IOException; impor ...
- Learning-Python【28】:基于TCP协议通信的套接字
什么是 Socket Socket 是应用层与 TCP/IP 协议通信的中间软件抽象层,它是一组接口.在设计模式中,Socket 其实就是一个门面模式,它把复杂的 TCP/IP 协议族隐藏在 Sock ...
- Linux 系统编程 学习:008-基于socket的网络编程3:基于 TCP 的通信
背景 上一讲我们介绍了 基于UDP 的通信 这一讲我们来看 TCP 通信. 知识 TCP(Transmission Control Protoco 传输控制协议). TCP是一种面向广域网的通信协议, ...
- 基于WebSocket和SpringBoot的群聊天室
引入 普通请求-响应方式:例如Servlet中HttpServletRequest和HttpServletResponse相互配合先接受请求.解析数据,再发出响应,处理完成后连接便断开了,没有数据的实 ...
- 如何巧妙地在基于 TCP Socket 的应用中实现用户注册功能?
通常,在基于TCP的应用中(比如我开源的GGTalk即时通信系统),当TCP连接建立之后,第一个请求就是登录请求,只有登录成功以后,服务器才会允许客户端进行其它性质的业务请求.但是,注册用户这个功能比 ...
- Linux以下基于TCP多线程聊天室(server)
接上篇博文,本文是server端的实现,主要实现的功能,就是现实client的连接.转发client发送的消息.以及client掉线提示等功能,同一时候能够在这这上面扩展和TCP以及线程相关的功能木块 ...
随机推荐
- Leetcode:Longest Substring Without Repeating Characters分析和实现
题目大意是传入一条字符串,计算出这样的这样一条子字符串,要求子字符串是原字符串的连续的某一段,且子字符串内不包含两个或两个以上的重复字符.求符合上面条件的字符串中最长的那一条的长度. 首先注意到任意一 ...
- EF中的批量操作
阅读目录 插入 更新 删除 在使用EF的过程中,我们经常会遇到需要批量操作数据的场景,批量操作有的时候不仅能提高性能,比如使用SqlBulkCopy进入批量插入的时候,而且比较方便操作,提高效率.那么 ...
- 69. Sqrt(x) 求根号再取整
[抄题]: Implement int sqrt(int x). Compute and return the square root of x, where x is guaranteed to b ...
- 485. Max Consecutive Ones最长的连续1的个数
[抄题]: Given a binary array, find the maximum number of consecutive 1s in this array. Example 1: Inpu ...
- C语言实践 输出100以内的素数
int main() { int isprime = 1; for (int i = 2; i < 101; i++) { isprime = 1;//要确保每次循环都要把这个值设置为1,不然上 ...
- chrome浏览器-Toolbar工具条不显示
来源于<sencha touch 权威指南> ------------------------------------ 工具条按钮在chrome下不显示,不知是不支持还是代码有问题.app ...
- 怎样去阅读一份php源代码
一份好的源代码例如 dz的论坛,wind论坛,帝国cms,dedecms等,都具有自己的一套设计思路和设计模式,所以在看某个产品之前就要做好心理准备,可以把自己的经验和这些产品做对比,但千万别一直用自 ...
- Python基础 之列表、字典、元组、集合
基础数据类型汇总 一.列表(list) 例如:删除索引为奇数的元素 lis=[11,22,33,44,55] #第一种: for i in range(len(lis)): if i%2==1: de ...
- hdu 1556 Color the ball (线段树做法)
Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球a ...
- bootstrap实现菜单定位
<!DOCTYPE html><html lang="zh-cn"><head><meta charset="utf-8&quo ...