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"; // 端口号 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实现聊天之消息推送,希望对大家有所帮助,如果大家有任何疑问请给我留言。
微信扫码,欢迎关注微信公众账号,更多精彩~
手机扫码加入qq群,欢迎你~