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. SpringMVC总结二:Controller的请求映射方式(RequestMapping)简单介绍

    在SpringMVC总结一:快速入门的基础上简单介绍一下请求映射的方式: 1,标准映射规则 1. @RequestMapping可以设置在类上,也可以设置在方法上 2. 请求的映射规则是:类上的Req ...

  2. 【原创】12. MYSQL++之Template Query

    1. 什么是Template Query 在我们实际的编程过程中,我们很容易碰到printf这类需要在运行时来决定到底打印出什么的函数,例如 printf(“hello %s”, sth); 在这个例 ...

  3. Github简单的上传和修改

    先自己手动创建一个仓库 echo "# delet" >> README.md git init git add . git commit -m "first ...

  4. Oracle设置主键自增长

    第一步:为表设置主键 第二步:新建序列 CREATE SEQUENCE SQ.SEQ_INCREASE  START WITH 12  MAXVALUE 999  MINVALUE 0 INCREME ...

  5. 27-拓扑排序-poj1094

    http://poj.org/problem?id=1094 Sorting It All Out Time Limit: 1000MS   Memory Limit: 10000K Total Su ...

  6. 面试题:MySQL性能调优——索引详解与索引的优化 没用

    ——索引优化,可以说是数据库相关优化.理解尤其是查询优化中最常用的优化手段之一.所以,只有深入索引的实现原理.存储方式.不同索引间区别,才能设计或使用最优的索引,最大幅度的提升查询效率! 一.BTre ...

  7. 面试题:SpringMVC的工作流程

    SpringMVC是当今最主流的Web MVC框架,没有之一,要做一名合格的JavaWeb工程师,学好它势在必行! 与Struts2原理不同,SpringMVC是通过最基础最传统的servlet来实现 ...

  8. 无返回值的函数如何捕获出错情况(检查errno常量)

    在执行这个函数前,先清除errno,函数返回时,检查errno常量. 每次程序调用失败的时候,系统会自动用用错误代码填充errno这个全局变量,这样你只需要读errno这个全局变量就可以获得失败原因了 ...

  9. pandas sort_values 排序后, index 也发生了改变,不改变的情况下需要 reset_index(drop = True)

    shenpi.sort_values(by=['apply_date'],ascending=True,inplace=True)shenpi.reset_index(drop = True)

  10. Part8-不用内存怎么行_我从内部看内存lesson1