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下解压后缀名为".tar.xz"的文件
作者:荒原之梦 原文链接:http://zhaokaifeng.com/?p=576 1 解压".xz" xz -d your_file_name.tar.xz 注:运行上述命令后 ...
- 阿里云oss挂载到linux本地文件系统
对象存储 OSS 阿里云对象存储服务 (OSS) 是一种高度可伸缩且安全可靠的云对象存储服务,让您可以存储.备份和归档大量数据.阿里云 OSS 是一种简单易用的服务,让您每秒能处理数百万请求,它还支持 ...
- app后端设计(3)--短信,邮件,推送服务(2014.12.05更新)
在app的后端设计中,免不了消息的推送,短信,邮件等服务,下面就个人的开发经验谈谈这方面. (1)最重要的是,各种推送一定要放在队列系统中处理,不然会严重影响api的响应时间. (2)短信方面 以前我 ...
- java面向对象中四种权限(private,protected,public,友好型)详解
转自http://blog.csdn.net/a1237871112/article/details/50926975 及http://blog.csdn.net/blackmanren/articl ...
- Mac下将文件复制到移动硬盘
在Mac下将移动硬盘格式化成exfat,这样Mac和Windows都可以对移动硬盘进行识别
- [Poi2012]A Horrible Poem BZOJ2795
分析: 这是今天下午的考试题,推了2个小时,考试中A掉了 首先,循环串通过字符串hash可以O(1)判断:get_hash(l,r-len)==get_hash(l+len,r);显然可证. 我们其次 ...
- [NOIP2002]字串变换 T2 双向BFS
题目描述 已知有两个字串 A,B 及一组字串变换的规则(至多6个规则): A1−>B1 A2−>B2 规则的含义为:在 A$中的子串 A1可以变换为可以变换为B1.A2可以变换为可 ...
- Postman-----设置环境变量
1.环境变量的作用域: 使用环境变量(可用于切换开发环境/生产环境.设置动态参数),有4个作用域(优先级由高到低):Global, Environment, Local, Data.同名变量会使用优先 ...
- 函数strlen()和sizeof的区别
函数strlen()和sizeof的区别: #include<stdio.h> #include<stdlib.h> #include<string.h> #def ...
- 死链接检查工具:Xenu 使用教程
一.软件作用 Xenu 全称Xenu’s Link Sleuth,是一款英文软件,界面单一,功能简单,使用方法很容易掌握.虽然看起来简单,但Xenu却拥有强大的功能.Xenu可以对网站的内链进行详细的 ...