Java Socket聊天室编程(一)之利用socket实现聊天之消息推送
相关阅读:JavaSocket聊天室编程(二)之利用socket实现单聊聊天室
网上已经有很多利用socket实现聊天的例子了,但是我看过很多,多多少有一些问题存在。
这里我将实现一个比较完整的聊天例子,并解释其中的逻辑。
由于socket这一块比较大,所以我将分出几篇来写一个比较完整的socket例子。
这里我们先来实现一个最简单的,服务器与客户端通讯,实现消息推送的功能。
目的:服务器与客户端建立连接,客户端可以向服务器发送消息,服务器可以向客户端推送消息。
1,使用java建立socket聊天服务器
1,SocketUrls确定ip地址和端口号
publicclassSocketUrls{
//ip地址
publicfinalstaticStringIP="192.168.1.110";
//端口号
publicfinalstaticintPORT=8888;
}
2,Main程序的入口
publicclassMain{
publicstaticvoidmain(String[]args)throwsException{
newChatServer().initServer();
}
}
3,Bean实体类
用户信息UserInfoBean
publicclassMain{
publicstaticvoidmain(String[]args)throwsException{
newChatServer().initServer();
}
}
聊天信息MessageBean
publicclassMessageBeanextendsUserInfoBean{
privatelongmessageId;//消息id
privatelonggroupId;//群id
privatebooleanisGoup;//是否是群消息
privateintchatType;//消息类型;1,文本;2,图片;3,小视频;4,文件;5,地理位置;6,语音;7,视频通话
privateStringcontent;//文本消息内容
privateStringerrorMsg;//错误信息
privateinterrorCode;//错误代码
//省略get/set方法
}
4,ChatServer聊天服务,最主要的程序
publicclassChatServer{
//socket服务
privatestaticServerSocketserver;
publicGsongson=newGson();
/**
*初始化socket服务
*/
publicvoidinitServer(){
try{
//创建一个ServerSocket在端口8080监听客户请求
server=newServerSocket(SocketUrls.PORT);
createMessage();
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
/**
*创建消息管理,一直接收消息
*/
privatevoidcreateMessage(){
try{
System.out.println("等待用户接入:");
//使用accept()阻塞等待客户请求
Socketsocket=server.accept();
System.out.println("用户接入:"+socket.getPort());
//开启一个子线程来等待另外的socket加入
newThread(newRunnable(){
publicvoidrun(){
createMessage();
}
}).start();
//向客户端发送信息
OutputStreamoutput=socket.getOutputStream();
//从客户端获取信息
BufferedReaderbff=newBufferedReader(newInputStreamReader(socket.getInputStream()));
//Scannerscanner=newScanner(socket.getInputStream());
newThread(newRunnable(){
publicvoidrun(){
try{
Stringbuffer;
while(true){
//从控制台输入
BufferedReaderstrin=newBufferedReader(newInputStreamReader(System.in));
buffer=strin.readLine();
//因为readLine以换行符为结束点所以,结尾加入换行
buffer+="\n";
output.write(buffer.getBytes("utf-8"));
//发送数据
output.flush();
}
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
}).start();
//读取发来服务器信息
Stringline=null;
//循环一直接收当前socket发来的消息
while(true){
Thread.sleep(500);
//System.out.println("内容:"+bff.readLine());
//获取客户端的信息
while((line=bff.readLine())!=null){
MessageBeanmessageBean=gson.fromJson(line,MessageBean.class);
System.out.println("用户:"+messageBean.getUserName());
System.out.println("内容:"+messageBean.getContent());
}
}
//server.close();
}catch(Exceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
System.out.println("错误:"+e.getMessage());
}
}
}
2,Android端作为移动端连接服务器
1,appliaction实例化一个全局的聊天服务
publicclassChatAppliactionextendsApplication{
publicstaticChatServerchatServer;
publicstaticUserInfoBeanuserInfoBean;
@Override
publicvoidonCreate(){
super.onCreate();
}
}
2,ip地址和端口号和服务器保持一致
3,聊天实力类同服务器端一样
4,xml布局。登陆,聊天
1,登录
<?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns: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,聊天
<?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns: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登陆
publicclassLoginActivityextendsAppCompatActivity{
privateEditTextchat_name_text,chat_pwd_text;
privateButtonchat_login_btn;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
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(newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
if(getLogin(chat_name_text.getText().toString().trim(),chat_pwd_text.getText().toString().trim())){
getChatServer();
Intentintent=newIntent(LoginActivity.this,MainActivity.class);
startActivity(intent);
finish();
}
}
});
}
privatebooleangetLogin(Stringname,Stringpwd){
if(TextUtils.isEmpty(name)||TextUtils.isEmpty(pwd))returnfalse;
if(name.equals("admin")&&pwd.equals("123123123a"))returntrue;
returnfalse;
}
privatevoidgetChatServer(){
ChatAppliaction.chatServer=newChatServer();
}
}
6,MainActivity聊天
publicclassMainActivityextendsAppCompatActivity{
privateLinearLayoutchat_ly;
privateTextViewleft_text,right_view;
privateEditTextchat_et;
privateButtonsend_btn;
privateViewGroup.LayoutParamslayoutParams=newViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
@Override
protectedvoidonCreate(BundlesavedInstanceState){
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(newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
ChatAppliaction.chatServer.sendMessage(chat_et.getText().toString().trim());
chat_ly.addView(initRightView(chat_et.getText().toString().trim()));
}
});
//添加消息接收队列
ChatAppliaction.chatServer.setChatHandler(newHandler(){
@Override
publicvoidhandleMessage(Messagemsg){
if(msg.what==1){
//发送回来消息后,更新ui
chat_ly.addView(initLeftView(msg.obj.toString()));
}
}
});
}
/**靠右的消息
*@parammessageContent
*@return
*/
privateViewinitRightView(StringmessageContent){
right_view=newTextView(this);
right_view.setLayoutParams(layoutParams);
right_view.setGravity(View.FOCUS_RIGHT);
right_view.setText(messageContent);
returnright_view;
}
/**靠左的消息
*@parammessageContent
*@return
*/
privateViewinitLeftView(StringmessageContent){
left_text=newTextView(this);
left_text.setLayoutParams(layoutParams);
left_text.setGravity(View.FOCUS_LEFT);
left_text.setText(messageContent);
returnleft_text;
}
}
7,ChatServer聊天逻辑,最主要的
publicclassChatServer{
privateSocketsocket;
privateHandlerhandler;
privateMessageBeanmessageBean;
privateGsongson=newGson();
//由Socket对象得到输出流,并构造PrintWriter对象
PrintWriterprintWriter;
InputStreaminput;
OutputStreamoutput;
DataOutputStreamdataOutputStream;
publicChatServer(){
initMessage();
initChatServer();
}
/**
*消息队列,用于传递消息
*
*@paramhandler
*/
publicvoidsetChatHandler(Handlerhandler){
this.handler=handler;
}
privatevoidinitChatServer(){
//开个线程接收消息
receiveMessage();
}
/**
*初始化用户信息
*/
privatevoidinitMessage(){
messageBean=newMessageBean();
messageBean.setUserId(1);
messageBean.setMessageId(1);
messageBean.setChatType(1);
messageBean.setUserName("admin");
ChatAppliaction.userInfoBean=messageBean;
}
/**
*发送消息
*
*@paramcontentMsg
*/
publicvoidsendMessage(StringcontentMsg){
try{
if(socket==null){
Messagemessage=handler.obtainMessage();
message.what=1;
message.obj="服务器已经关闭";
handler.sendMessage(message);
return;
}
byte[]str=contentMsg.getBytes("utf-8");//将内容转utf-8
Stringaaa=newString(str);
messageBean.setContent(aaa);
StringmessageJson=gson.toJson(messageBean);
/**
*因为服务器那边的readLine()为阻塞读取
*如果它读取不到换行符或者输出流结束就会一直阻塞在那里
*所以在json消息最后加上换行符,用于告诉服务器,消息已经发送完毕了
**/
messageJson+="\n";
output.write(messageJson.getBytes("utf-8"));//换行打印
output.flush();//刷新输出流,使Server马上收到该字符串
}catch(Exceptione){
e.printStackTrace();
Log.e("test","错误:"+e.toString());
}
}
/**
*接收消息,在子线程中
*/
privatevoidreceiveMessage(){
newThread(newRunnable(){
@Override
publicvoidrun(){
try{
//向本机的8080端口发出客户请求
socket=newSocket(SocketUrls.IP,SocketUrls.PORT);
//由Socket对象得到输入流,并构造相应的BufferedReader对象
printWriter=newPrintWriter(socket.getOutputStream());
input=socket.getInputStream();
output=socket.getOutputStream();
dataOutputStream=newDataOutputStream(socket.getOutputStream());
//从客户端获取信息
BufferedReaderbff=newBufferedReader(newInputStreamReader(input));
//读取发来服务器信息
Stringline;
while(true){
Thread.sleep(500);
//获取客户端的信息
while((line=bff.readLine())!=null){
Log.i("socket","内容:"+line);
Messagemessage=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(Exceptione){
e.printStackTrace();
Log.e("test","错误:"+e.toString());
}
}
}).start();
}
}
写到这里,已经完成了所有的代码。
这个demo可以实现手机端向服务器发送消息,服务器向手机端发送消息。
这个demo可以算是推送功能,不过真正的推送没有这么简单。作为一个socket的入门了解,可以从中看到socket编程的思想。
以上所述是小编给大家介绍的JavaSocket聊天室编程(一)之利用socket实现聊天之消息推送,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!