这篇文章主要介绍了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实现聊天之消息推送的更多相关文章

  1. Java Socket聊天室编程(二)之利用socket实现单聊聊天室

    这篇文章主要介绍了Java Socket聊天室编程(二)之利用socket实现单聊聊天室的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 在上篇文章Java Socket聊天室编程(一)之 ...

  2. 结合实际需求,在webapi内利用WebSocket建立单向的消息推送平台,让A页面和服务端建立WebSocket连接,让其他页面可以及时给A页面推送消息

    1.需求示意图 2.需求描述 原本是为了给做unity3d客户端开发的同事提供不定时的消息推送,比如商城购买道具后服务端将道具信息推送给客户端. 本篇文章简化理解,用“相关部门开展活动,向全市人民征集 ...

  3. Thinkphp利用微信多客服消息推送取货二维码消息

    首先看微信官方的说法: 当用户主动发消息给公众号的时候(包括发送信息.点击自定义菜单.订阅事件.扫描二维码事件.支付成功事件.用户维权), 微信将会把消息数据推送给开发者,开发者在一段时间内(目前修改 ...

  4. cakephp 利用Pushapi扩展 进行app 消息推送

    public function push_designer_app($params) { $this->layout = false; $this->autoRender = false; ...

  5. java版Web Socket,实现消息推送

    # web socket是什么? WebSocket协议是基于TCP的一种新的网络协议. 它实现了浏览器与服务器全双工(full-duplex)通信,允许服务器主动发送信息给客户端. ## 用途 实时 ...

  6. WebSocket实现Java后台消息推送

    1.什么是WebSocket WebSocket协议是基于TCP的一种新的网络协议.它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端. 2.实现原理 在实现 ...

  7. SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=》提升)

     SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=>提升,5个Demo贯彻全篇,感兴趣的玩才是真的学) 官方demo:http://www.asp.net/si ...

  8. SSE(Server-sent events)技术在web端消息推送和实时聊天中的使用

    最近在公司闲着没事研究了几天,终于搞定了SSE从理论到实际应用,中间还是有一些坑的. 1.SSE简介 SSE(Server-sent events)翻译过来为:服务器发送事件.是基于http协议,和W ...

  9. 消息推送学习一、原生Socket的使用

    消息推送也是客户端和服务器连接然后进行交互的一种形式,但是不同于HTTP的连接,这种连接需要长时间的进行,当有消息时可以及时推送到客户端.除此之外还有多个用户,可能需要针对其身份进行不同的推送等等要求 ...

随机推荐

  1. 慕课网__CSS_网页图标制作

    参考地址:http://www.flowerboys.cn/font/article/fontsArticle/how-to-turn-your-icons-into-a-web-font.html

  2. 烂泥:Linux系统与windows系统文件同步

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 上篇文章中,我们介绍了有关Linux系统之间的文件同步,这篇文章我们来介绍下,有关Linux系统与windows系统,以及windows系统与windo ...

  3. jstl 保留两位小数

    简介:jstl保留两位小数实现方法在JSP开头导入以下标签:<%@tagliburi="http://java.sun.com/jsp/jstl/fmt"pre jstl 保 ...

  4. grunt之filerev、usemin

    窃以为这两个插件是比较有用的,filerev是给js.css进行编码重命名,usemin修改html中被重命名的js.css文件的引用.另外说明下之前将concat.cssmin.uglify放在一篇 ...

  5. J2EE走向成功路-02-Struts2 配置(Maven)

    在上一篇中,介绍了使用jar包搭建Struts2框架,这一篇中来介绍一下在Maven环境下搭建Struts2框架,主要为配置Maven. 1.下载Maven,官网:http://maven.apach ...

  6. BZOJ_1834_[ZJOI2010]network 网络扩容_费用流

    BZOJ_1834_[ZJOI2010]network 网络扩容_费用流 题意: 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用. 求:  1.在不扩容的 ...

  7. Dynamics365 WebAPI ADFS token 获取

    public class CrmAuth { ///<summary> /// Token /// </summary> public string access_token ...

  8. 《一头扎进SpringMvc视频教程》

    第二章 SpringMvc控制器 第三章 Rest风格的资源URL 第四章 SpringMvc上传文件

  9. 利用python计算多边形面积

    最近业务上有一个需求,给出多边形面积. Google了一下,发现国内论坛给的算法都是你抄我我抄你,也不验证一下是否正确, 从 博客园到csdncsdn 然后传播到国内各个角落...真是无力吐槽了. 直 ...

  10. hiho1270 建造基地([Offer收割]编程练习赛1)

    题目意思很简单, 一道类似于背包的问题,问恰好超过背包容量的最小取值.并且需要计算n次,每计算一次都要将所有的物品的价值w[i] /= t,最后输出背包n次的总使用容量. 如果无法实现输出”No An ...