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多线程通信实现群聊天的功能的更多相关文章

  1. Android基于XMPP Smack openfire 开发的聊天室

    Android基于XMPP Smack openfire 开发的聊天室(一)[会议服务.聊天室列表.加入] http://blog.csdn.net/lnb333666/article/details ...

  2. 链路的有效性检测 及 基于TCP的通信为什么需要RETRY

    一.链路的有效性检测 当网络发生单通.连接被防火墙Hang住.长时间GC或者通信线程发生非预期异常时,会导致链路不可用且不易被及时发现. 特别是异常发生在凌晨业务低谷期间,当早晨业务高峰期到来时,由于 ...

  3. Android基于TCP的局域网聊天通信

    概述 在同一局域网内,两台设备通过TCP进行通信聊天. 详细 代码下载:http://www.demodashi.com/demo/10567.html 一.准备工作 开发环境 jdk1.8 Ecli ...

  4. 网络编程应用:基于TCP协议【实现一个聊天程序】

    要求: 基于TCP协议实现一个聊天程序,客户端发送一条数据,服务器端发送一条数据 客户端代码: package Homework1; import java.io.IOException; impor ...

  5. Learning-Python【28】:基于TCP协议通信的套接字

    什么是 Socket Socket 是应用层与 TCP/IP 协议通信的中间软件抽象层,它是一组接口.在设计模式中,Socket 其实就是一个门面模式,它把复杂的 TCP/IP 协议族隐藏在 Sock ...

  6. Linux 系统编程 学习:008-基于socket的网络编程3:基于 TCP 的通信

    背景 上一讲我们介绍了 基于UDP 的通信 这一讲我们来看 TCP 通信. 知识 TCP(Transmission Control Protoco 传输控制协议). TCP是一种面向广域网的通信协议, ...

  7. 基于WebSocket和SpringBoot的群聊天室

    引入 普通请求-响应方式:例如Servlet中HttpServletRequest和HttpServletResponse相互配合先接受请求.解析数据,再发出响应,处理完成后连接便断开了,没有数据的实 ...

  8. 如何巧妙地在基于 TCP Socket 的应用中实现用户注册功能?

    通常,在基于TCP的应用中(比如我开源的GGTalk即时通信系统),当TCP连接建立之后,第一个请求就是登录请求,只有登录成功以后,服务器才会允许客户端进行其它性质的业务请求.但是,注册用户这个功能比 ...

  9. Linux以下基于TCP多线程聊天室(server)

    接上篇博文,本文是server端的实现,主要实现的功能,就是现实client的连接.转发client发送的消息.以及client掉线提示等功能,同一时候能够在这这上面扩展和TCP以及线程相关的功能木块 ...

随机推荐

  1. dyld_decache&MesaSQLite

    [dyld_decache] Starting from iPhone OS 3.1, the individual libraries files supplied by the system ar ...

  2. shell cut 用法

    cut -f   提取第几列 -d  按指定的分隔符割列 cut -f 1 xxx.txt   提取第1列 cut -f 1,3 xxx.txt   提取第1,3列 cut -d ":&qu ...

  3. HTML中禁用表中控件的两种方法与区别

    在网页的制作过程中,我们会经常使用到表单.但是有时候我们会希望表单上的控件是不可修改的,比如在修改密码的网页中,显示用户名的文本框就应该是不可修改状态的. 在html中有两种禁用的方法,他们分别是: ...

  4. Ubuntu 查看软件版本

    Boost dpkg -S /usr/include/boost/version.hpp OpenCV pkg-config --modversion opencv

  5. Linux下DNS配置

    一.本机DNS配置 参考:http://blog.sina.com.cn/s/blog_68d6e9550100k3b7.html 二.DNS服务器搭建 http://toutiao.com/i631 ...

  6. 19、SOAP安装,运用与比对结果解释

    转载:http://www.dengfeilong.com/post/Soap2.html https://blog.csdn.net/zhu_si_tao/article/details/71108 ...

  7. HDU 5293 Tree chain problem

    树状数组 + dp 设$f_i$表示以$i$为根的子树中的能选取的最大和,$sum_x$表示$\sum_{f_y}$  ($y$是$x$的一个儿子),这样子我们把所有给出的链按照两点的$lca$分组, ...

  8. redis的一些简介

    Redis是Remote Dictionary Server的缩写,他本质上一个Key/Value数据库,与Memcached类似的NoSQL型数据库. 1.       redis的数据类型: st ...

  9. .net 基元类型,引用类型和值类型

    基元类型(primitive type): 编译器直接支持的数据类型称为基元类型(primitive type). string 与 String: 由于C#中的string (一个关键字)直接映射到 ...

  10. hbuilder h5 原生socket

    在网上搜索了很多资料都不行,要么就是不能发送数据,要么就不能接收数据,使用如下的方法可以接收数据,一个一个字节接收: 有部分限制是需要明确知道要接收多少个字节,否则容易出现接收异常.. var tes ...