Java Socket聊天室编程(一)之利用socket实现聊天之消息推送
这篇文章主要介绍了Java Socket聊天室编程(一)之利用socket实现聊天之消息推送的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
网上已经有很多利用socket实现聊天的例子了,但是我看过很多,多多少有一些问题存在。
这里我将实现一个比较完整的聊天例子,并解释其中的逻辑。
由于socket这一块比较大,所以我将分出几篇来写一个比较完整的socket例子。
这里我们先来实现一个最简单的,服务器与客户端通讯,实现消息推送的功能。
目的:服务器与客户端建立连接,客户端可以向服务器发送消息,服务器可以向客户端推送消息。
1,使用java建立socket聊天服务器
1,SocketUrls 确定ip地址和端口号
- public class SocketUrls{
- // ip地址
- public final static String IP = "192.168.1.110";
- // 端口号
- ;
- }
2,Main 程序的入口
- public class Main {
- public static void main(String[] args) throws Exception {
- new ChatServer().initServer();
- }
- }
3,Bean 实体类
用户信息 UserInfoBean
- public class Main {
- public static void main(String[] args) throws Exception {
- new ChatServer().initServer();
- }
- }
聊天信息 MessageBean
- public class MessageBean extends UserInfoBean {
- private long messageId;// 消息id
- private long groupId;// 群id
- private boolean isGoup;// 是否是群消息
- private int chatType;// 消息类型;1,文本;2,图片;3,小视频;4,文件;5,地理位置;6,语音;7,视频通话
- private String content;// 文本消息内容
- private String errorMsg;// 错误信息
- private int errorCode;// 错误代码
- //省略get/set方法
- }
4,ChatServer 聊天服务,最主要的程序
- public class ChatServer {
- // socket服务
- private static ServerSocket server;
- public Gson gson = new Gson();
- /**
- * 初始化socket服务
- */
- public void initServer() {
- try {
- // 创建一个ServerSocket在端口8080监听客户请求
- server = new ServerSocket(SocketUrls.PORT);
- createMessage();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- /**
- * 创建消息管理,一直接收消息
- */
- private void createMessage() {
- try {
- System.out.println("等待用户接入 : ");
- // 使用accept()阻塞等待客户请求
- Socket socket = server.accept();
- System.out.println("用户接入 : " + socket.getPort());
- // 开启一个子线程来等待另外的socket加入
- new Thread(new Runnable() {
- public void run() {
- createMessage();
- }
- }).start();
- // 向客户端发送信息
- OutputStream output = socket.getOutputStream();
- // 从客户端获取信息
- BufferedReader bff = new BufferedReader(new InputStreamReader(socket.getInputStream()));
- // Scanner scanner = new Scanner(socket.getInputStream());
- new Thread(new Runnable() {
- public void run() {
- try {
- String buffer;
- while (true) {
- // 从控制台输入
- BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
- buffer = strin.readLine();
- // 因为readLine以换行符为结束点所以,结尾加入换行
- buffer += "
- ";
- output.write(buffer.getBytes("utf-8"));
- // 发送数据
- output.flush();
- }
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }).start();
- // 读取发来服务器信息
- String line = null;
- // 循环一直接收当前socket发来的消息
- while (true) {
- Thread.sleep();
- // System.out.println("内容 : " + bff.readLine());
- // 获取客户端的信息
- while ((line = bff.readLine()) != null) {
- MessageBean messageBean = gson.fromJson(line, MessageBean.class);
- System.out.println("用户 : " + messageBean.getUserName());
- System.out.println("内容 : " + messageBean.getContent());
- }
- }
- // server.close();
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- System.out.println("错误 : " + e.getMessage());
- }
- }
- }
2,Android 端作为移动端连接服务器
1,appliaction 实例化一个全局的聊天服务
- public class ChatAppliaction extends Application {
- public static ChatServer chatServer;
- public static UserInfoBean userInfoBean;
- @Override
- public void onCreate() {
- super.onCreate();
- }
- }
2,ip地址和端口号和服务器保持一致
3,聊天实力类同服务器端一样
4,xml布局。登陆,聊天
1,登录
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
- <EditText
- android:id="@+id/chat_name_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:hint="用户名"
- android:text="admin"/>
- <EditText
- android:id="@+id/chat_pwd_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:hint="密码"
- android:text="123123123a"
- android:inputType="numberPassword" />
- <Button
- android:id="@+id/chat_login_btn"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:hint="登录" />
- </LinearLayout>
2,聊天
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- tools:context=".activity.MainActivity">
- <ScrollView
- android:id="@+id/scrollView"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="0.9">
- <LinearLayout
- android:id="@+id/chat_ly"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
- </LinearLayout>
- </ScrollView>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
- <EditText
- android:id="@+id/chat_et"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="0.8" />
- <Button
- android:id="@+id/send_btn"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="0.2"
- android:text="发送" />
- </LinearLayout>
- </LinearLayout>
5,LoginActivity 登陆
- public class LoginActivity extends AppCompatActivity {
- private EditText chat_name_text, chat_pwd_text;
- private Button chat_login_btn;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_login);
- chat_name_text = (EditText) findViewById(R.id.chat_name_text);
- chat_pwd_text = (EditText) findViewById(R.id.chat_pwd_text);
- chat_login_btn = (Button) findViewById(R.id.chat_login_btn);
- chat_login_btn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (getLogin(chat_name_text.getText().toString().trim(), chat_pwd_text.getText().toString().trim())) {
- getChatServer();
- Intent intent = new Intent(LoginActivity.this, MainActivity.class);
- startActivity(intent);
- finish();
- }
- }
- });
- }
- private boolean getLogin(String name, String pwd) {
- if (TextUtils.isEmpty(name) || TextUtils.isEmpty(pwd)) return false;
- if (name.equals("admin") && pwd.equals("123123123a")) return true;
- return false;
- }
- private void getChatServer() {
- ChatAppliaction.chatServer = new ChatServer();
- }
- }
6,MainActivity 聊天
- public class MainActivity extends AppCompatActivity {
- private LinearLayout chat_ly;
- private TextView left_text, right_view;
- private EditText chat_et;
- private Button send_btn;
- private ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- chat_ly = (LinearLayout) findViewById(R.id.chat_ly);
- chat_et = (EditText) findViewById(R.id.chat_et);
- send_btn = (Button) findViewById(R.id.send_btn);
- send_btn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- ChatAppliaction.chatServer.sendMessage(chat_et.getText().toString().trim());
- chat_ly.addView(initRightView(chat_et.getText().toString().trim()));
- }
- });
- //添加消息接收队列
- ChatAppliaction.chatServer.setChatHandler(new Handler() {
- @Override
- public void handleMessage(Message msg) {
- ) {
- //发送回来消息后,更新ui
- chat_ly.addView(initLeftView(msg.obj.toString()));
- }
- }
- });
- }
- /**靠右的消息
- * @param messageContent
- * @return
- */
- private View initRightView(String messageContent) {
- right_view = new TextView(this);
- right_view.setLayoutParams(layoutParams);
- right_view.setGravity(View.FOCUS_RIGHT);
- right_view.setText(messageContent);
- return right_view;
- }
- /**靠左的消息
- * @param messageContent
- * @return
- */
- private View initLeftView(String messageContent) {
- left_text = new TextView(this);
- left_text.setLayoutParams(layoutParams);
- left_text.setGravity(View.FOCUS_LEFT);
- left_text.setText(messageContent);
- return left_text;
- }
- }
7,ChatServer 聊天逻辑,最主要的
- public class ChatServer {
- private Socket socket;
- private Handler handler;
- private MessageBean messageBean;
- private Gson gson = new Gson();
- // 由Socket对象得到输出流,并构造PrintWriter对象
- PrintWriter printWriter;
- InputStream input;
- OutputStream output;
- DataOutputStream dataOutputStream;
- public ChatServer() {
- initMessage();
- initChatServer();
- }
- /**
- * 消息队列,用于传递消息
- *
- * @param handler
- */
- public void setChatHandler(Handler handler) {
- this.handler = handler;
- }
- private void initChatServer() {
- //开个线程接收消息
- receiveMessage();
- }
- /**
- * 初始化用户信息
- */
- private void initMessage() {
- messageBean = new MessageBean();
- messageBean.setUserId(1);
- messageBean.setMessageId(1);
- messageBean.setChatType(1);
- messageBean.setUserName("admin");
- ChatAppliaction.userInfoBean = messageBean;
- }
- /**
- * 发送消息
- *
- * @param contentMsg
- */
- public void sendMessage(String contentMsg) {
- try {
- if (socket == null) {
- Message message = handler.obtainMessage();
- message.what = 1;
- message.obj = "服务器已经关闭";
- handler.sendMessage(message);
- return;
- }
- byte[] str = contentMsg.getBytes("utf-8");//将内容转utf-8
- String aaa = new String(str);
- messageBean.setContent(aaa);
- String messageJson = gson.toJson(messageBean);
- /**
- * 因为服务器那边的readLine()为阻塞读取
- * 如果它读取不到换行符或者输出流结束就会一直阻塞在那里
- * 所以在json消息最后加上换行符,用于告诉服务器,消息已经发送完毕了
- * */
- messageJson += "
- ";
- output.write(messageJson.getBytes("utf-8"));// 换行打印
- output.flush(); // 刷新输出流,使Server马上收到该字符串
- } catch (Exception e) {
- e.printStackTrace();
- Log.e("test", "错误:" + e.toString());
- }
- }
- /**
- * 接收消息,在子线程中
- */
- private void receiveMessage() {
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- // 向本机的8080端口发出客户请求
- socket = new Socket(SocketUrls.IP, SocketUrls.PORT);
- // 由Socket对象得到输入流,并构造相应的BufferedReader对象
- printWriter = new PrintWriter(socket.getOutputStream());
- input = socket.getInputStream();
- output = socket.getOutputStream();
- dataOutputStream = new DataOutputStream(socket.getOutputStream());
- // 从客户端获取信息
- BufferedReader bff = new BufferedReader(new InputStreamReader(input));
- // 读取发来服务器信息
- String line;
- while (true) {
- Thread.sleep(500);
- // 获取客户端的信息
- while ((line = bff.readLine()) != null) {
- Log.i("socket", "内容 : " + line);
- Message message = handler.obtainMessage();
- message.obj = line;
- message.what = 1;
- handler.sendMessage(message);
- }
- if (socket == null)
- break;
- }
- output.close();//关闭Socket输出流
- input.close();//关闭Socket输入流
- socket.close();//关闭Socket
- } catch (Exception e) {
- e.printStackTrace();
- Log.e("test", "错误:" + e.toString());
- }
- }
- }).start();
- }
- }
写到这里,已经完成了所有的代码。
这个demo可以实现手机端向服务器发送消息,服务器向手机端发送消息。
这个demo可以算是推送功能,不过真正的推送没有这么简单。作为一个socket的入门了解,可以从中看到socket编程的思想。
以上所述是小编给大家介绍的Java Socket聊天室编程(一)之利用socket实现聊天之消息推送,希望对大家有所帮助,如果大家有任何疑问请给我留言。
微信扫码,欢迎关注微信公众账号,更多精彩~
手机扫码加入QQ群,欢迎你~
Java Socket聊天室编程(一)之利用socket实现聊天之消息推送的更多相关文章
- Java Socket聊天室编程(二)之利用socket实现单聊聊天室
这篇文章主要介绍了Java Socket聊天室编程(二)之利用socket实现单聊聊天室的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 在上篇文章Java Socket聊天室编程(一)之 ...
- 结合实际需求,在webapi内利用WebSocket建立单向的消息推送平台,让A页面和服务端建立WebSocket连接,让其他页面可以及时给A页面推送消息
1.需求示意图 2.需求描述 原本是为了给做unity3d客户端开发的同事提供不定时的消息推送,比如商城购买道具后服务端将道具信息推送给客户端. 本篇文章简化理解,用“相关部门开展活动,向全市人民征集 ...
- Thinkphp利用微信多客服消息推送取货二维码消息
首先看微信官方的说法: 当用户主动发消息给公众号的时候(包括发送信息.点击自定义菜单.订阅事件.扫描二维码事件.支付成功事件.用户维权), 微信将会把消息数据推送给开发者,开发者在一段时间内(目前修改 ...
- cakephp 利用Pushapi扩展 进行app 消息推送
public function push_designer_app($params) { $this->layout = false; $this->autoRender = false; ...
- java版Web Socket,实现消息推送
# web socket是什么? WebSocket协议是基于TCP的一种新的网络协议. 它实现了浏览器与服务器全双工(full-duplex)通信,允许服务器主动发送信息给客户端. ## 用途 实时 ...
- 利用Kafka的Assign模式实现超大群组(10万+)消息推送
引言 IM即时通信场景下,最重要的一个能力就是推送:在线的直接通过长连接网关服务转发,离线的通过APNS或者极光等系统进行推送. 本文主要是针对在线用户推送场景来进行总结和探讨:如何利用Kafka ...
- WebSocket实现Java后台消息推送
1.什么是WebSocket WebSocket协议是基于TCP的一种新的网络协议.它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端. 2.实现原理 在实现 ...
- SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=》提升)
SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=>提升,5个Demo贯彻全篇,感兴趣的玩才是真的学) 官方demo:http://www.asp.net/si ...
- SSE(Server-sent events)技术在web端消息推送和实时聊天中的使用
最近在公司闲着没事研究了几天,终于搞定了SSE从理论到实际应用,中间还是有一些坑的. 1.SSE简介 SSE(Server-sent events)翻译过来为:服务器发送事件.是基于http协议,和W ...
随机推荐
- Linux时间子系统之八:动态时钟框架(CONFIG_NO_HZ、tickless)
在前面章节的讨论中,我们一直基于一个假设:Linux中的时钟事件都是由一个周期时钟提供,不管系统中的clock_event_device是工作于周期触发模式,还是工作于单触发模式,也不管定时器系统是工 ...
- 附录D——自动微分(Autodiff)
本文介绍了五种微分方式,最后两种才是自动微分. 前两种方法求出了原函数对应的导函数,后三种方法只是求出了某一点的导数. 假设原函数是$f(x,y) = x^2y + y +2$,需要求其偏导数$\fr ...
- 最近最久未使用页面淘汰算法———LRU算法(java实现)
请珍惜小编劳动成果,该文章为小编原创,转载请注明出处. LRU算法,即Last Recently Used ---选择最后一次访问时间距离当前时间最长的一页并淘汰之--即淘汰最长时间没有使用的页 按照 ...
- Android 自定义ViewGroup手把手教你实现ArcMenu
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/37567907 逛eoe发现这样的UI效果,感觉很不错,后来知道github上有这 ...
- ImageMagick简介、GraphicsMagick、命令行使用示例
http://elf8848.iteye.com/blog/382528 ImageMagick资料 ------------------------------------------------- ...
- yum 出问题了
今天用yum 安装ntp 的过程中用了 Ctrl+ z, 然后yum 再也不能使用了: error: rpmdb: BDB0113 Thread/process 6589/14060193936774 ...
- Python 员工信息管理系统
学Python将近一个月了,第一次写了两百多行代码,一个很简单的脚本. 员工信息管理系统: 需求: 1.管理员账户能够增加,删除,修改,查询员工信息,并且设置管理员账户. 2.普通账户可以查看所有员工 ...
- Python 模块详解及import本质
同在当前目录下的模块和包导入 模块定义 本质就是.py结尾的python文件. 用来从逻辑上组织python代码(变量,函数,类,逻辑) 文件名: test.py; 对应的模块名 : test 模块 ...
- 在Windows Server 2008 R2下搭建jsp环境(二)-mysql的下载安装
个人推荐java开发过程中的数据库首选MYSQL,MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司.MySQL是一种关联数据库管理系统,关联数据库将数据保 ...
- bzoj 1210 [HNOI2004] 邮递员 插头dp
插头dp板子题?? 搞了我一晚上,还tm全是抄的标程.. 还有高精,哈希混入,还是我比较弱,orz各种dalao 有不明白的可以去看原论文.. #include<cstdio> #incl ...