android socket聊天室功能实现
发布时间 - 2026-01-11 00:26:40 点击率:次前提概要

笔者很久之前其实就已经学习过了socket,当然也是用socket做过了聊天室,但是觉得此知识点比较一般,并无特别难的技术点,于是也并未深究。
然而近期一个项目中对socket的使用却让笔者感觉socket强大无比,可以实现诸多功能。
个人Socket体验
项目主要有关智能家居,需要实现多台手机同时对灯进行操作(开或者关),主要需要实现以下几点:
1、进入界面时获取所有灯的状态。
2、一台手机改变了灯的状态,其他的手机上可以有所显示。
3、硬件上改变了灯的状态(手动开关灯),所有手机上要有所显示。
此功能如果使用HTTP读取的方式实现就不太合适了。一方面客户端与服务器读取文件的同步性难以保证,即使保证了,也需要浪费大量性能;另一方面,类似笔者的这种项目功能服务器和客户端交互比较频繁,对“即时性”要求也比较高,用HTTP不仅性能消耗太大,而且难以保证“即时性”。
但是使用Socket就很容易实现了,主要逻辑如下:
1、每次进入界面与服务器建立Socket连接,并得到此时灯的状态
2、每次需要对灯进行操作的时候建立一个线程把灯的状态传递给服务器,服务器接收到之后,把该状态传递给每一个此时与服务器建立连接的客户端。
此次体验也是让笔者想起了学长之前做的一道笔试题,题目大概如下:
将淘宝网页和手机版同时打开账户,手机停留在购物车界面,此时网页上将某一物品加入购物车,如何设计才能让手机自动刷新购物车。
如果使用socket,相信是一个不错的思路。
好了,接下来进入正题,展示socket聊天室demo。
效果(源码在文章结尾)
主要思路
Android
1、进入界面客户端与服务器建立socket,同时此时开启一个线程一直接收服务器发送来的消息。
2、每次点击button获取EditText中的字符串,调用子线程把字符串发送给服务器。
服务器
1、创建一个ArrayList存储Socket。
2、循环接收请求访问该端口的客户端,接收到之后,把该socket存储到ArrayList中,并且为每一个socket开启一个线程用于通信。
3、每个socket的线程的逻辑如下:循环接收客户端发来的消息,接收到之后,利用之前的ArrayList,发送到每一个客户端。如果某个客户端返回空值或者无法发送过去,那么表示该客户端已经断开,就从ArrayList中移除。
代码
(借鉴《Android疯狂讲义》)
Android
不要忘记在AndroidManifest里面加上访问网络的权限
MainActivity:
package com.example.double2.sockettesttwo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private EditText etMain;
private Button btnMain;
private TextView tvMain;
private ClientThread mClientThread;
//在主线程中定义Handler传入子线程用于更新TextView
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etMain = (EditText) findViewById(R.id.et_main);
btnMain = (Button) findViewById(R.id.btn_main);
tvMain = (TextView) findViewById(R.id.tv_main);
mHandler=new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 0) {
tvMain.append("\n" + msg.obj.toString());
}
}
};
//点击button时,获取EditText中string并且调用子线程的Handler发送到服务器
btnMain.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
Message msg = new Message();
msg.what = 1;
msg.obj = etMain.getText().toString();
mClientThread.revHandler.sendMessage(msg);
etMain.setText("");
} catch (Exception e) {
e.printStackTrace();
}
}
});
mClientThread = new ClientThread(mHandler);
new Thread(mClientThread).start();
}
}
ClientThread
package com.example.double2.sockettesttwo;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
/**
* 项目名称:SocketTestTwo
* 创建人:Double2号
* 创建时间:2016.11.20 9:16
* 修改备注:
*/
public class ClientThread implements Runnable {
private Socket mSocket;
private BufferedReader mBufferedReader = null;
private OutputStream mOutputStream = null;
private Handler mHandler;
public Handler revHandler;
public ClientThread(Handler handler) {
mHandler = handler;
}
@Override
public void run() {
try {
mSocket = new Socket("10.3.20.159", 30003);
Log.d("xjj","connect success");
mBufferedReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
mOutputStream = mSocket.getOutputStream();
new Thread(){
@Override
public void run() {
super.run();
try {
String content = null;
while ((content = mBufferedReader.readLine()) != null) {
Log.d("xjj",content);
Message msg = new Message();
msg.what = 0;
msg.obj = content;
mHandler.sendMessage(msg);
}
}catch (IOException e){
e.printStackTrace();
}
}
}.start();
//由于子线程中没有默认初始化Looper,要在子线程中创建Handler,需要自己写
Looper.prepare();
revHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
try {
mOutputStream.write((msg.obj.toString() + "\r\n").getBytes("utf-8"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
Looper.loop();
} catch (IOException e) {
e.printStackTrace();
Log.d("xjj","");
}
}
}
activity_main
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/activity_vertical_margin" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <EditText android:id="@+id/et_main" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"/> <Button android:id="@+id/btn_main" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/send"/> </LinearLayout> <TextView android:id="@+id/tv_main" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
服务器:
MySever
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class MySever {
public static ArrayList<Socket> socketList = new ArrayList<Socket>();
public static String content="";
public static void main(String[] args) throws IOException {
//建立ServerSocket
ServerSocket ss = new ServerSocket(30003);
//不断接收此端口的socket,并存储到socketList中
//并且为每一个socket开启一个线程,用于接收信息
while (true) {
Socket s = ss.accept();
System.out.println("connect success!");
socketList.add(s);
new Thread(new ServerThread(s)).start();
}
}
}
SeverThread
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.SocketException;
import java.util.Iterator;
public class ServerThread implements Runnable {
private Socket mSocket = null;
private BufferedReader mBufferedReader = null;
// 构造函数中接收socket并且初始化BufferedReader
public ServerThread(Socket socket)
throws UnsupportedEncodingException, IOException {
mSocket = socket;
mBufferedReader = new BufferedReader(
new InputStreamReader(mSocket.getInputStream(), "utf-8"));
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
String content = null;
//循环接收来自此客户端的消息
//如果接收不到了,表面已经断开,就将此客户端从socketList中移除
while ((content = mBufferedReader.readLine()) != null) {
System.out.println(content);
//向连接中的每个客户端发送数据
//如果异常,说明断开,就将该条目从socketList中移除
for (Iterator<Socket> it = MySever.socketList.iterator();
it.hasNext();) {
Socket s = it.next();
try {
OutputStream os = s.getOutputStream();
os.write((content + "\n").getBytes("utf-8"));
} catch (SocketException e) {
e.printStackTrace();
it.remove();
}
}
}
} catch (IOException e) {
e.printStackTrace();
MySever.socketList.remove(mSocket);
}
}
}
源码地址:android socket聊天室
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# android
# socket
# 聊天室
# Android Socket实现多个客户端聊天布局
# android使用Socket通信实现多人聊天应用
# Android Socket通信实现简单聊天室
# Android使用Websocket实现聊天室
# 基于Socket.IO实现Android聊天功能代码示例
# android Socket实现简单聊天小程序
# android Socket实现简单聊天功能以及文件传输
# Android 基于Socket的聊天室实例
# Android基于socket实现的简单C/S聊天通信功能
# Android Socket实现多个客户端即时通信聊天
# 客户端
# 购物车
# 移除
# 过了
# 发送到
# 把该
# 是一个
# 改变了
# 好了
# 不太
# 其他的
# 很久
# 较高
# 一台
# 要在
# 很容易
# 太大
# 能让
# 几点
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
javascript中闭包概念与用法深入理解
Laravel如何处理文件上传_Laravel Storage门面实现文件存储与管理
Laravel如何实现多级无限分类_Laravel递归模型关联与树状数据输出【方法】
JavaScript如何实现错误处理_try...catch如何捕获异常?
动图在线制作网站有哪些,滑动动图图集怎么做?
如何用景安虚拟主机手机版绑定域名建站?
Laravel如何使用缓存系统提升性能_Laravel缓存驱动和应用优化方案
PythonWeb开发入门教程_Flask快速构建Web应用
Laravel如何使用.env文件管理环境变量?(最佳实践)
如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?
Laravel Docker环境搭建教程_Laravel Sail使用指南
Android滚轮选择时间控件使用详解
原生JS获取元素集合的子元素宽度实例
Laravel如何配置和使用缓存?(Redis代码示例)
iOS中将个别页面强制横屏其他页面竖屏
Laravel中Service Container是做什么的_Laravel服务容器与依赖注入核心概念解析
微信小程序制作网站有哪些,微信小程序需要做网站吗?
Laravel定时任务怎么设置_Laravel Crontab调度器配置
JavaScript如何实现音频处理_Web Audio API如何工作?
专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?
Laravel如何处理CORS跨域问题_Laravel项目CORS配置与解决方案
美食网站链接制作教程视频,哪个教做美食的网站比较专业点?
ChatGPT回答中断怎么办 引导AI继续输出完整内容的方法
邀请函制作网站有哪些,有没有做年会邀请函的网站啊?在线制作,模板很多的那种?
Laravel怎么配置.env环境变量_Laravel生产环境敏感数据保护与读取【方法】
大连 网站制作,大连天途有线官网?
Edge浏览器怎么启用睡眠标签页_节省电脑内存占用优化技巧
家族网站制作贴纸教程视频,用豆子做粘帖画怎么制作?
Laravel如何实现用户角色和权限系统_Laravel角色权限管理机制
如何在Windows环境下新建FTP站点并设置权限?
Laravel如何配置Horizon来管理队列?(安装和使用)
Laravel如何处理异常和错误?(Handler示例)
Laravel如何实现API版本控制_Laravel API版本化路由设计策略
怎样使用JSON进行数据交换_它有什么限制
Laravel N+1查询问题如何解决_Eloquent预加载(Eager Loading)优化数据库查询
Google浏览器为什么这么卡 Google浏览器提速优化设置步骤【方法】
高防服务器:AI智能防御DDoS攻击与数据安全保障
Laravel如何与Pusher实现实时通信?(WebSocket示例)
香港服务器租用每月最低只需15元?
如何解决hover在ie6中的兼容性问题
头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?
网站制作壁纸教程视频,电脑壁纸网站?
如何在建站宝盒中设置产品搜索功能?
Laravel如何使用API Resources格式化JSON响应_Laravel数据资源封装与格式化输出
高端智能建站公司优选:品牌定制与SEO优化一站式服务
JS中页面与页面之间超链接跳转中文乱码问题的解决办法
大型企业网站制作流程,做网站需要注册公司吗?
Python自然语言搜索引擎项目教程_倒排索引查询优化案例
手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?
Laravel如何发送邮件_Laravel Mailables构建与发送邮件的简明教程

