博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【移动开发】WIFI热点通信(二)
阅读量:5807 次
发布时间:2019-06-18

本文共 6570 字,大约阅读时间需要 21 分钟。

     相信大家在上一篇中已经了解了Android中WIFI热点通信的相关操作知识(),今天我们将在上一篇代码基础之上进行Socket编程,实现一个简单的多人聊天室功能,以达到热点网络上的通信目的。

    首先,我们先来看一张最终效果图:

<=======>

(说明:由于目前作服务器端的手机,只是实现了数据的接收和转发,自己发送的数据并未显示到自己的界面上,还需大家完善。。。)


一.框架搭建

在上一章的代码基础上,新增加了四个类:

    GameServer:服务器端实现。

    SocketClient:客户端实现类。

    ChatAdapter:聊天列表适配器。

    ChatMessage:聊天信息实体。

    GroupChatActivity:聊天室Acitivity。

1.1.相关类图

在热点连接成功后,开始聊天通信过程,服务器端与客户端的类实现如下图所示:

1.2.说明:

服务端:套接字GameServer,端口和套接字监听函数beginListen(),接收数据的函数serverAcceptClientMsg(),发送数据的函数sendMsgToAllCLients,以及网络通讯流BufferedReader。

客户端:套接字SocketClient,套接字连接函数startConnServer(),接收数据的函数acceptGameServerMsg(),发送数据的函数sendMsg()。

前面提到过创建热点成功后,会自动在当前手机后台创建GameServer,同时开启线程监听端口并等待连接,当其余玩家成功连接上热点后,每个手机客户端后台对应会创建一个独立的Socket,用于发送和接收消息。在客户端中通过client.getInputStream()接收数数据,ClientMsgListener.handlerHotMsg(getSMsg)将数据反映到UI界面上,最终实现了客户端接收服务器端数据刷新UI界面的功能。

二.通信模块


    2.1.服务器端

由于软件的通信载体是在手机上,所以在创建完成热点之后,在后台也同时创建了游戏的服务器,开启了监听PORT线程,等待其他客户端连接。这样设计的目的是为了在当有其他手机端连接上指定WIFI热点时就与后台服务器端进行了连接,即实现了TCP/IP通讯前期准备。主要业务设计如图所示:

核心代码:

  •  beginListenandAcceptMsg()

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
 
/** init server to listen **/
    
public 
void 
beginListenandAcceptMsg() {
        
new 
Thread(
new 
Runnable() {
            
@Override
            
public 
void 
run() {
                
try 
// init server
                    
mServerSocket = 
new 
ServerSocket();
                    
mServerSocket.setReuseAddress(
true
);
                    
InetSocketAddress address = 
new 
InetSocketAddress(mPort);
                    
mServerSocket.bind(address);
                    
mServerMsgListener.handlerHotMsg(Global.INT_SERVER_SUCCESS);
                    
Log.i(TAG, 
"server  =" 
+ mServerSocket);
                
catch 
(SocketException e) {
                    
e.printStackTrace();
                
catch 
(IOException e) {
                    
e.printStackTrace();
                
}
                
//server accept from socket msg
                
if
(mServerSocket != 
null
) {
                    
while
(onGoinglistner) {
                        
try 
{
                            
Socket socket = mServerSocket.accept();
                            
if
(socket != 
null
) {
                                
if
(!socketQueue.contains(socket)) {
                                    
socketQueue.add(socket);
                                    
count++; 
//记录连接人数
                                
}
                                
Log.i(TAG, 
"接收客户端消息" 
+ socket);
                                
serverAcceptClientMsg(socket);
                            
}
                        
catch 
(IOException e) {
                            
e.printStackTrace();
                        
}
                    
}
                
}
            
}
        
}).start();
    
}
  • serverAcceptClientMsg()

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
 
/**
     
* accept from socket msg
     
* @param socket
     
*/
    
private 
void 
serverAcceptClientMsg(
final 
Socket socket) {
        
new 
Thread(
new 
Runnable(){
            
@Override
            
public 
void 
run() {
                
while
(!socket.isClosed()) {
                    
try 
{
                    
//此处可以根据连接的客户端数量count做一些数据分发等操作。
                        
//接收客户端消息
                    
in = 
new 
BufferedReader(
new 
InputStreamReader(socket.getInputStream(), 
"UTF-8"
));
                        
String str = in.readLine();
                        
if
(str == 
null 
|| str.equals(
""
)) {
                            
break
;
                        
}
                        
Log.i(TAG, 
"client" 
+ socket + 
"str =" 
+ str);
                    
mServerMsgListener.handlerHotMsg(str);
                    
catch 
(Exception e) {
                        
e.printStackTrace();
                    
}
                
}
            
}
        
}).start();
    
}
  • sendMsg()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**send msg to the socket**/
    
public 
void 
sendMsg(Socket client, String chatMsg) {
        
Log.i(TAG, 
"into sendMsg(final Socket client,final ChatMessage msg) msg = " 
+ chatMsg);
        
PrintWriter out = 
null
;
        
if 
(client.isConnected()) {
            
if 
(!client.isOutputShutdown()) {
                
try 
{
                    
out = 
new 
PrintWriter(client.getOutputStream());
                    
out.println(chatMsg);
                    
out.flush();
                    
Log.i(TAG, 
"into sendMsg(final Socket client,final ChatMessage msg) msg = " 
+ chatMsg + 
" success!"
);
                
catch 
(IOException e) {
                    
e.printStackTrace();
                    
Log.d(TAG, 
"into sendMsg(final Socket client,final ChatMessage msg) fail!"
);
                
}
            
}
        
}
        
Log.i(TAG, 
"out sendMsg(final Socket client,final ChatMessage msg) msg = " 
+ chatMsg);
    
}

    2.2.客户端

        这里的客户端建立指的是当其他手机在该软件的WIFI管理界面上,点击可用WIFI列表中指定的WIFI进行连接操作,连接成功后,会在后台创建客户端,与服务器相连。主要业务设计如图所示:

核心代码:

  • connServerandAcceptMsg()

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
/**after hot pot created and connected successful , start connect GameServer**/
    
public 
void 
connServerandAcceptMsg() {
        
Log.i(TAG, 
"into connectServer()"
);
        
new 
Thread(
new 
Runnable() {
            
@Override
            
public 
void 
run() {
                
try 
{
                    
client = 
new 
Socket(site, port);
                    
Log.i(TAG, 
"Client is created! site:" 
+ site + 
" port:" 
+ port);
                     
                    
//callback
                    
mClientMsgListener.handlerHotMsg(Global.INT_CLIENT_SUCCESS);
                     
                    
//accept msg from GameServer
                    
acceptGameServerMsg();
                
catch 
(UnknownHostException e) {
                    
e.printStackTrace();
                    
mClientMsgListener.handlerErorMsg(Global.INT_CLIENT_FAIL);
                
catch 
(IOException e) {
                    
e.printStackTrace();
                    
mClientMsgListener.handlerErorMsg(Global.INT_CLIENT_FAIL);
                
}
            
}
        
}).start();
        
Log.i(TAG, 
"out connectServer()"
);
    
}
  • acceptGameServerMsg()

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
/**accept msg from GameServer**/
    
private 
void 
acceptGameServerMsg() {
        
new 
Thread(
new 
Runnable() {
            
@Override
            
public 
void 
run() {
                
while
(onGoinglistner){
                    
if
(client != 
null 
&& client.isConnected()) {
                        
if
(!client.isInputShutdown()) {
                            
try 
{
                                
in = 
new 
BufferedReader(
new 
InputStreamReader(client.getInputStream()));
                                
String getSMsg = in.readLine();
                                
Log.i(TAG, 
"into acceptMsg()  SMsg =" 
+ getSMsg);
                                
if
(getSMsg != 
null 
|| !getSMsg.equals(
""
)) {
                                    
//callback
                                
mClientMsgListener.handlerHotMsg(getSMsg);
                                
}
                            
catch 
(IOException e) {
                                
e.printStackTrace();
                            
}
                        
}
                    
}
                
}
            
}
        
}).start();
    
}
  • sendMsg()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**send msg to GameServer**/
    
public 
String sendMsg(
final 
String chatMsg) {
        
Log.i(TAG, 
"into sendMsgsendMsg(final ChatMessage msg)  msg =" 
+ chatMsg);
        
new 
Thread(
new 
Runnable() {
            
@Override
            
public 
void 
run() {
                
try 
{
                    
if 
(client != 
null 
&& client.isConnected()) {
                        
if 
(!client.isOutputShutdown()) {
                            
PrintWriter out = 
new 
PrintWriter(client.getOutputStream());
                            
out.println(chatMsg);
                            
// out.println(JsonUtil.obj2Str(msg));
                            
Log.i(TAG, 
"成功发送msg =" 
+ chatMsg);
                            
out.flush();
                        
}
                    
}
                
catch 
(IOException e) {
                    
e.printStackTrace();
                    
Log.d(TAG, 
"client snedMsg error!"
);
                
}
            
}
        
}).start();
        
return 
""
;
    
}

以上两大部分为Socket编程部分,为了能够将数据反映到UI 前台,这里我们将每次线程接收到的数据先以接口回调方法( mClientMsgListener.handlerHotMsg(getSMsg);)的形式传递,在其对应的方法中再利用Handler消息机制将数据发送到各自对应的Handler中,最后根据逻辑将其反映到UI上,以上就是代码的大体流程。

2.3.通信过程

下载过完整代码的朋友就会发现代码中许多重要的方法中我加入了Log,目的就是为了方便自己能够更加清晰的了解整个代码的流程,当然大家也可以在此基础上进行不断的修改和完善

  • 点击创建热点按钮:

  • 点击搜索热点按钮:









  • 点击列表“WIFI-TEST”进行连接


三.总结


1.此案例由于是从本人毕业设计中扒下来的,可能现在有些地方代码框架设计的不是很合理,如:GroupChatActivity就是为了方便实现聊天功能后添加的,大家在学习完之后可以在Activity跳转时的基础上,进一步按照自己的逻辑来实现一些东西。

 

    2.UI如何更新?

     服务器端只是实现数据转发,未对自己发送数据进行显示,了解了整个代码的同学可能已经发现不论是Server还是Client端,在接收到数据之后,我们通过各自的监听器(mServerMsgListener,mClientMsgListener)来回调对应的方法(handlerHotMsg,handlerErrorMsg),在方法中我们将数据添加msg.obj中,最终以消息传递的方式发送到各自对应的handler中(clientHandler,serverHandler),在那里我们就可以根据数据来更新界面。

 

3.题外话:

     要是有人对热点通信特别感兴趣,想在此的基础之上开发小游戏,前台游戏绘制界面就不用多说了,我主要想说的是后台数据部分,最好能给所有操作制定了一系列对应的数据规则,如:出牌操作:在传输的数据串前面加上规则字符---->“《#CARD》+数据段”,之后作为整体发送出去,这样的话,接收方在接收到数据后可以方便的更新UI,实现对应的游戏动画。(个人经验,仅供参考)

源码下载:

     本文转自zhf651555765 51CTO博客,原文链接:http://blog.51cto.com/smallwoniu/1538298,如需转载请自行联系原作者

你可能感兴趣的文章
nginx 域名跳转一例~~~(rewrite、proxy)
查看>>
linux用户家目录无损迁移到独立硬盘
查看>>
文件查找
查看>>
shell编程前言(一)
查看>>
5、centos7.*配置yum的EPEL源及其它源
查看>>
JSON前后台简单操作
查看>>
shell中一些常见的文件操作符
查看>>
CentOS 7 装vim遇到的问题和解决方法
查看>>
JavaScript基础教程1-20160612
查看>>
使用第三方类、库需要注意的正则类RegexKitLite的使用
查看>>
iOS \U7ea2 乱码 转换
查看>>
FCN图像分割
查看>>
ios xmpp demo
查看>>
设计模式之-工厂模式、构造函数模式
查看>>
python matplotlib 中文显示参数设置
查看>>
数据库事务隔离级别
查看>>
os模块大全详情
查看>>
【ros】Create a ROS package:package dependencies报错
查看>>
从内积的观点来看线性方程组
查看>>
kali linux 更新问题
查看>>