相关阅读: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 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