1、Android socket编程 以非阻塞IAndroid socket编程 以非阻塞I/O服务器及Service为例来源:中国手机开发网2010年01月25日字体:小 大点击推荐给好友关键字:之前采用聊天敲门的方式来介绍Socket通信,有两个不足的地方,1.服务器会造成IO的阻塞即服务器一旦执行server.accept();将一直处于阻塞状态,直到有客户端请求连接。2.服务器端没有建立用户列表,无法将某一客户端发送的消息广播给所有正在连接的客户端。就好象是一个人自说自话,自己发送给客户端,自己接收服务器返回的消息。基于以上两点,我改进了我的程序。服务器端的改进:1.通过采用socketc
2、hannel的非阻塞方式进行通信2.建立Userlist客户端的哈希表,存储 已连接客户端的 ip地址和 服务器为其分发的socketchannel客户端的改进:1.采用Service 与服务器端进行连接,发送数据,实时监听服务器返回的数据。流程图:需要改进的地方服务器端:1.当一个客户端断开连接以后,另一个客户端在收到消息之前也断开连接,而此时服务器正在向客户端发送消息,因此,服务器的Thread.sleep时间不能太长,但也不能太短,因为考虑到服务器的负荷问题。2.服务器容错处理机制需要改进。客户端:1.将Notificationbar改为其他更为直观方式刷新显示。2.容错处理机制的处理。
3、下面是效果图:服务器端:dos客户端:Android客户端:效果图的意思是,Android的客户端通过绑定Service与服务器端进行了连接,并发送消息。服务器向所有正在连接的客户端广播消息。之后,Dos终端也进行连接,并发送消息,服务器接到消息后向所有正在连接的客户端广播消息(其中包括在线的android手机)第1页 第2页 第3页 第4页 第5页 第6页 之前采用聊天敲门的方式来介绍Socket通信,有两个不足的地方,1.服务器会造成IO的阻塞即服务器一旦执行server.accept();将一直处于阻塞状态,直到有客户端请求连接。2.服务器端没有建立用户列表,无法将某一客户端发送的消息广
4、播给所有正在连接的客户端。就好象是一个人自说自话,自己发送给客户端,自己接收服务器返回的消息。基于以上两点,我改进了我的程序。服务器端的改进:1.通过采用socketchannel的非阻塞方式进行通信2.建立Userlist客户端的哈希表,存储 已连接客户端的 ip地址和 服务器为其分发的socketchannel客户端的改进:1.采用Service 与服务器端进行连接,发送数据,实时监听服务器返回的数据。流程图:需要改进的地方服务器端:1.当一个客户端断开连接以后,另一个客户端在收到消息之前也断开连接,而此时服务器正在向客户端发送消息,因此,服务器的Thread.sleep时间不能太长,但也
5、不能太短,因为考虑到服务器的负荷问题。2.服务器容错处理机制需要改进。客户端:1.将Notificationbar改为其他更为直观方式刷新显示。2.容错处理机制的处理。下面是效果图:服务器端:dos客户端:Android客户端:效果图的意思是,Android的客户端通过绑定Service与服务器端进行了连接,并发送消息。服务器向所有正在连接的客户端广播消息。之后,Dos终端也进行连接,并发送消息,服务器接到消息后向所有正在连接的客户端广播消息(其中包括在线的android手机)第1页 第2页 第3页 第4页 第5页 第6页 接上页源代码如下:Server端:package com.androi
6、d.Yao;import java.io.*;import java.nio.*;import java.nio.channels.*;import .*;import java.util.*;import java.nio.charset.*;import java.lang.*;public class YaoChatServerpublic Selector sel = null;public ServerSocketChannel server = null;public SocketChannel socket = null;public int thisport = 4900;pr
7、ivate String result = null;private Hashtableuserlists ;private SocketChannel readingsocket = null;public YaoChatServer()System.out.println(Inside startserver );public YaoChatServer(int port)System.out.println(Inside startserver );thisport = port;public void initializeOperations() throws IOException,
8、UnknownHostExceptionSystem.out.println(Inside initialization );sel = Selector.open();server = ServerSocketChannel.open();server.configureBlocking(false);InetAddress ia = InetAddress.getLocalHost();InetSocketAddress isa = new InetSocketAddress(ia,thisport);server.socket().bind(isa);userlists = new Ha
9、shtable();public void startServer() throws IOExceptioninitializeOperations();server.register(sel, SelectionKey.OP_ACCEPT);while (sel.select() 0 )Set readyKeys = sel.selectedKeys();Iterator it = readyKeys.iterator();while(it.hasNext()SelectionKey key = (SelectionKey)it.next();it.remove();if (key.isAc
10、ceptable()ServerSocketChannel ssc = (ServerSocketChannel) key.channel();socket = (SocketChannel) ssc.accept();socket.configureBlocking(false);String socketname = socket.socket().getRemoteSocketAddress().toString();socket.register(sel, SelectionKey.OP_WRITE);userlists.put(socketname,socket);System.ou
11、t.println(socketname + is connected!);if (key.isWritable() readingsocket =(SocketChannel)key.channel();String ret=readMessage(readingsocket);if (ret.equalsIgnoreCase( is going to say goodbye!)key.cancel();readingsocket.close();userlists.remove(readingsocket.socket().getRemoteSocketAddress().toString
12、();System.out.println(send server msg:+ret.replace(, readingsocket.socket().getRemoteSocketAddress().toString();sendMessage(ret.replace(, readingsocket.socket().getRemoteSocketAddress().toString();else if (ret.length() 0 ) System.out.println(send server msg:+ret);sendMessage(ret);public void sendMes
13、sage(String msg) throws IOExceptionByteBuffer buffer = ByteBuffer.allocate(1024);buffer = ByteBuffer.wrap(msg.getBytes();/ ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes(UTF-8);Collection channels = userlists.values();SocketChannel sc;for(Object o:channels)sc = (SocketChannel)o;sc.write(buffer);bu
14、ffer.flip();try Thread.sleep(500); catch (InterruptedException e) / TODO Auto-generated catch blocke.printStackTrace();public String readMessage(SocketChannel sc)int nBytes = 0;ByteBuffer buf = ByteBuffer.allocate(1024);try nBytes = sc.read(buf);buf.flip();Charset charset = Charset.forName(UTF-8);Ch
15、arsetDecoder decoder = charset.newDecoder();CharBuffer charBuffer = decoder.decode(buf);result = charBuffer.toString(); catch (IOException e) result = is going to say goodbye!;return result;public static void main(String args)YaoChatServer nb = new YaoChatServer();trynb.startServer();catch (IOExcept
16、ion e)e.printStackTrace();System.exit(-1);Android客户端的Service类:package com.android.Yao;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import .InetSocketAddress;import java.nio.ByteBuffer;import java.nio.CharBuffer;import java.nio.channels.SocketChannel;impor
17、t java.nio.charset.CharacterCodingException;import java.nio.charset.Charset;import java.nio.charset.CharsetDecoder;import java.util.Collection;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;import android.app.Service;import android.content.Con
18、text;import android.content.Intent;import android.os.Binder;import android.os.IBinder;public class ReceiveMessage extends Serviceprivate SocketChannel client = null;private InetSocketAddress isa = null;private String message=;public void onCreate() super.onCreate();ConnectToServer();StartServerListe
19、ner();public void onDestroy() super.onDestroy();DisConnectToServer();public void onStart(Intent intent, int startId) super.onStart(intent, startId);/* IBinder方法 , LocalBinder 类,mBinder接口这三项用于* Activity进行Service的绑定,点击发送消息按钮之后触发绑定* 并通过Intent将Activity中的EditText的值* 传送到Service中向服务器发送* */public IBinder on
20、Bind(Intent intent) message = intent.getStringExtra(chatmessage);if(message.length()0)SendMessageToServer(message);return mBinder;public class LocalBinder extends Binder ReceiveMessage getService() return ReceiveMessage.this;private final IBinder mBinder = new LocalBinder();/用于链接服务器端public void Conn
21、ectToServer()try client = SocketChannel.open();isa = new InetSocketAddress(192.168.0.107,4900);client.connect(isa);client.configureBlocking(false); catch (IOException e) / TODO Auto-generated catch blocke.printStackTrace();/断开与服务器端的链接public void DisConnectToServer()try client.close(); catch (IOExcep
22、tion e) / TODO Auto-generated catch blocke.printStackTrace();/启动服务器端的监听线程,从Server端接收消息public void StartServerListener()ServerListener a=new ServerListener();a.start();/向Server端发送消息public void SendMessageToServer(String msg)tryByteBuffer bytebuf = ByteBuffer.allocate(1024);bytebuf = ByteBuffer.wrap(m
23、sg.getBytes(UTF-8);client.write(bytebuf);bytebuf.flip();catch (IOException e) / TODO Auto-generated catch blocke.printStackTrace();private void shownotification(String tab)NotificationManager barmanager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);Notification msg=new Notifica
24、tion(android.R.drawable.stat_notify_chat,A Message Coming!,System.currentTimeMillis();PendingIntent contentIntent=PendingIntent.getActivity(this, 0, new Intent(this,YaoChatRoomAndroid.class), PendingIntent.FLAG_ONE_SHOT);msg.setLatestEventInfo(this,Message , Message:+tab, contentIntent);barmanager.n
25、otify(0, msg);private class ServerListener extends Threadpublic void run () try /无线循环,监听服务器,如果有不为空的信息送达,则更新Activity的UIwhile(true)ByteBuffer buf = ByteBuffer.allocate(1024);client.read(buf);buf.flip();Charset charset = Charset.forName(UTF-8);CharsetDecoder decoder = charset.newDecoder();CharBuffer charBuffer;charBuffer = decoder.decode(buf);String result = charBuffer.toString();if (result.length()0)shownotification(result);catch (CharacterCodingException e) / TODO Auto-generated catch blocke.printStackTrace();catch (IOException e) / TODO Auto-generated catch blocke.printStackTrace();
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1