欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java Socket聊天室编程(一)之利用socket实现聊天之消息推送

程序员文章站 2022-04-09 10:43:13
这篇文章主要介绍了Java Socket聊天室编程(一)之利用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";
// 端口号
public final static int port = 8888;
}

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(500);
// 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) {
if (msg.what == 1) {
//发送回来消息后,更新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实现聊天之消息推送,希望对大家有所帮助,如果大家有任何疑问请给我留言。


 

     微信扫码,欢迎关注微信公众账号,更多精彩~

Java Socket聊天室编程(一)之利用socket实现聊天之消息推送

          手机扫码加入qq群,欢迎你~

Java Socket聊天室编程(一)之利用socket实现聊天之消息推送