- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Java Socket聊天室编程(一)之利用socket实现聊天之消息推送由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
相关阅读:Java Socket聊天室编程(二)之利用socket实现单聊聊天室 。
网上已经有很多利用socket实现聊天的例子了,但是我看过很多,多多少有一些问题存在.
这里我将实现一个比较完整的聊天例子,并解释其中的逻辑.
由于socket这一块比较大,所以我将分出几篇来写一个比较完整的socket例子.
这里我们先来实现一个最简单的,服务器与客户端通讯,实现消息推送的功能.
目的:服务器与客户端建立连接,客户端可以向服务器发送消息,服务器可以向客户端推送消息.
1,使用java建立socket聊天服务器 。
1,SocketUrls 确定ip地址和端口号 。
1
2
3
4
5
6
|
public
class
SocketUrls{
// ip地址
public
final
static
String IP =
"192.168.1.110"
;
// 端口号
public
final
static
int
PORT =
8888
;
}
|
2,Main 程序的入口 。
1
2
3
4
5
|
public
class
Main {
public
static
void
main(String[] args)
throws
Exception {
new
ChatServer().initServer();
}
}
|
3,Bean 实体类 。
用户信息 UserInfoBean 。
1
2
3
4
5
6
|
public
class
Main {
public
static
void
main(String[] args)
throws
Exception {
new
ChatServer().initServer();
}
}
|
聊天信息 MessageBean 。
1
2
3
4
5
6
7
8
9
10
|
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 聊天服务,最主要的程序 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
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 +=
"\n"
;
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 实例化一个全局的聊天服务 。
1
2
3
4
5
6
7
8
|
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,登录 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<?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,聊天 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
<?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 登陆 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
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 聊天 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
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 聊天逻辑,最主要的 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
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 +=
"\n"
;
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实现聊天之消息推送,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我网站的支持! 。
原文链接:http://blog.csdn.net/yehui928186846/article/details/52572157 。
最后此篇关于Java Socket聊天室编程(一)之利用socket实现聊天之消息推送的文章就讲到这里了,如果你想了解更多关于Java Socket聊天室编程(一)之利用socket实现聊天之消息推送的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
在后台开启了“URL Rewrite”,看起来一切正常,可是点击某一栏目的时候却怎么都进不去,显示的依然是论坛的首页。看了一下论坛目录下,原来这下面并没有自己的.htaccess文件,所以默认使用的
本文实例为大家分享了.net发送邮件的实现代码,供大家参考,具体内容如下 关键代码: 需要引用命名空间: using System.Net.Mail; using System.Net;
今天的一个小测试是老师让用.NET用控件来制作一个拉菜单要求如下: 将鼠标移到父菜单上弹出3个子菜单,而且每个子菜单都有超链接。 以下是我自己做的代码: 复制代
我有以下内容 static const unsigned int chromosome = 6; double bestFitness[chromosomes]; for(int i = 0; i
关于附图,我需要一个计算算法来将 A 轴向下移动 n 英寸,将 B 轴从左向右移动 m 英寸,以便组件圆 D 遵循抛物线的曲线;圆 D 并不总是 10 英寸,可以更小。我不是数学专业的,所以这对我来说
我正在尝试利用我的格式字符串错误,它存在于这个程序中: #include #include #include #include #include void foo(char* tmp, ch
用Matplotlib和Seaborn这类Python库可以画出很好看的图,但是这些图只是静态的,难以动态且美观地呈现数值变化。要是在你下次的演示、视频、社交媒体Po文里能用短视频呈现数据变化,是不
1、进程介绍 进程:正在执行的程序,由程序、数据和进程控制块组成,是正在执行的程序,程序的一次执行过程,是资源调度的基本单位。 程序:没有执行的代码,是一个静态的。 2、线程
1、前言 在开发过程中,有时会遇到需要控制任务并发执行数量的需求。 例如一个爬虫程序,可以通过限制其并发任务数量来降低请求频率,从而避免由于请求过于频繁被封禁问题的发生。 接下来
Opera 管理着一个漏洞赏金计划,研究人员可以在该计划中报告 Opera 软件中的漏洞并获得奖励。 这篇文章就是我发现的一个漏洞——网页可能会从用户那里检索本地文件的屏幕截图。 考虑到 O
C++ 文件查找 在C++中我们要如何查找文件呢?我们需要一个结构体和几个大家可能不太熟悉的函数。这些函数和结构体在的头文件中,结构体为struct _finddata_t ,函数为_findfi
1、前言 本文利用 fsockopen() 函数,编写一个功能简单的端口扫描器。 2、关键技术 本实例的端口号是固定的,通过对数组的遍历,利用 fsockopen() 函数连接,如果连接成功,
最近在将一些项目的rest api迁移到.net core中,最开始是用的Nginx做反向代理,将已经完成切换的部分切入系统,如下图所示: 由于迁移过程中也在进行代码重构,需要经常比较频繁的测
前言 最近学习了python,感觉挺多地方能用到它的。打包 测试 上传 爬电影....而且代码量是真少。人生苦短,我用python。而今天写的这个是因为下载电影时总会发现除了视频还会有这两个文件,
1、Monkey测试简介 Monkey测试是Android平台自动化测试的一种手段,通过Monkey程序模拟用户触摸屏幕、滑动Trackball、按键等操作来对设备上的程序进行压力测试,检测程序
一直想写一套生成静态页面的文章系统 但面对生成静态后的一些复杂数据库交互问题。又望而却步! 于是就想 有没有 在不耽误数据交互的情况下,而又能降低服务器负
Qt 利用大量第 3 方库进行图像编码、压缩、加密、音频和视频编解码器支持等。 从历史上看,当我想使用它们时,我总是必须将它们作为附加依赖项包含在内。我一直想知道是否有一种方法可以简单地重用 Qt 已
我想知道是否可以使用属性将功能“混合”到类/方法/属性中。 就像是: [TrackChanges] public Foo { get; set; } 如果可能的话,有谁会如何实现? 最佳答
有些站点位于共享主机(Windows 2003 Server)上,因此我无法访问服务器配置。 我到处都读到关于杠杆浏览器缓存的信息,特别是静态文件(jpg,css,js等)的信息,但是...在我的情况
我想在我的项目中使用 Julia 的主要原因之一是它的速度,尤其是在计算积分方面。 我想在某个区间 [a,b] 上积分一维函数 f(x)。一般来说,Julia 的 quadgk 函数将是一个快速而准确
我是一名优秀的程序员,十分优秀!