Android之Socket,Service通讯
来源:互联网 发布:windows fix it 下载 编辑:程序博客网 时间:2024/05/21 12:43
Android与服务器之间的通讯方式主要有两种。一种是Http通讯 , 一种是Socket通讯。两者最大的差异在于,Http连接使用的是“请求---响应方式”,即在请求是建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据。而Socket则是在双方建立连接后就直接进行数据传输,在连接时可实现信息的主动推送,而不需要每次由客户端向服务端发送请求。
什么是Socket?又称套接字,是一种抽象层。在程序内部提供了与外界通讯的端口,即端口信息。通过建立Socket连接,可为通讯双方的传输提供通道。Socket的主要特点有数据丢失率低,使用简单且易于移植。
本案例是基于TCP协议的Socket。服务端首先声明一个ServerSocket对象并且指定端口号。然后调用ServerSocket的accept()方法接收客户端的数据。accept()方法在没有数据进行接收的处于堵塞状态。(Socketsocket=serversocket.accept()),一旦接收到数据,通过inputstream读取接收的数据。
客户端创建一个Socket对象,指定服务器端的ip地址和端口号(Socketsocket=newSocket("172.168.10.108",8080);),通过inputstream读取数据,获取服务器发出的数据(OutputStreamoutputstream=socket.getOutputStream()),最后将要发送的数据写入到outputstream即可进行TCP协议的socket数据传输。
项目结构:
2. IMService.class
public class IMService extends Service {static Communication communication;public static String messageTag="com.gys.im.CYEJIMActivity";public static Notification notification;public static int messageId = 10000;private NotificationManager mNM;boolean isconnected;Timer timer=new Timer();@Overridepublic void onCreate() {// TODO Auto-generated method stub communication=Communication.newInstance(); communication.setReceiver(this); mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); notification=new Notification(R.drawable.ic_launcher, "", System.currentTimeMillis()); notification.number=1; timer.schedule(timerTask, 1000, 2000);} public Handler handler= new Handler() { public void handleMessage(Message msg) { String message=msg.obj.toString(); if(message.equals("start\n")) { start_check_in(); }else { Intent intent = new Intent(messageTag); intent.putExtra("message", message); IMService.this.sendBroadcast(intent); } } }; public TimerTask timerTask=new TimerTask() {@Overridepublic void run() {// TODO Auto-generated method stubisconnected=checkNetwork();if(!isconnected){showNotification("","");}} }; /** * 添加内容到发送消息队列 * @param str */ public static void addPacket(String str) { communication.addPacket(str); } public static void wakeUp() { communication.wakeUp(); } /** * 开始发送心跳 */ protected void start_check_in() { communication.start_check_in(); } public boolean checkNetwork() {boolean flag = false;ConnectivityManager cwjManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);if (cwjManager.getActiveNetworkInfo() != null){flag = cwjManager.getActiveNetworkInfo().isAvailable();}return flag;} private void showNotification(String statusInfo,String messageContent) { PendingIntent contentIntent = PendingIntent.getActivity(this,0,null,0); notification.when=System.currentTimeMillis(); notification.tickerText=statusInfo; notification.setLatestEventInfo(this,"test",messageContent, null); notification.contentIntent=contentIntent; notification.vibrate = new long[] {100, 250, 100, 500}; messageNotificationAdd(messageId, notification); } /*add a nonotification*/ public void messageNotificationAdd(int notificationNo,Notification notification){ try { mNM.notify(notificationNo,notification); }catch(Exception e) { e.printStackTrace(); } notification.number++;//number 增加后,可以与以前的notification区分开来 }@Overridepublic void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();mNM.cancel(messageId);}@Overridepublic void onLowMemory() {// TODO Auto-generated method stubsuper.onLowMemory();}@Overridepublic void onStart(Intent intent, int startId) {// TODO Auto-generated method stubsuper.onStart(intent, startId);}@Overridepublic boolean onUnbind(Intent intent) {// TODO Auto-generated method stubreturn super.onUnbind(intent);}@Overridepublic IBinder onBind(Intent arg0) {// TODO Auto-generated method stubreturn null;}}
3.Communication.class :
public class Communication {private NetTransportWorker transportWorker;private MessageWorker messageWorker;private static Communication instance;private Communication() {transportWorker = new NetTransportWorker();transportWorker.start();messageWorker = new MessageWorker(transportWorker);messageWorker.start();}public static Communication newInstance() {if (instance == null)instance = new Communication();return instance;}public NetTransportWorker getTransportWorker() {return transportWorker;}public MessageWorker getMessageWorker() {return messageWorker;}public void setReceiver(IMService service){transportWorker.setRecever(service);}//public void addReceiveInfoListener(ReceiveInfoListener listener) {//transportWorker.addReceiveInfoListener(listener);//}////public void removeReceiveInfoListener(ReceiveInfoListener listener) {//transportWorker.removeReceiveInfoListener(listener);//}public void reconnect() {transportWorker.notify();}private boolean sendDataToServer(String packet) {try {if (transportWorker.writeBuf(packet.getBytes("UTF8")))return true;} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return false;}/** 如果从不活动界面切换到聊天界面,此方法返回所有队列里面的信息数据包 **/public Queue<String> getReceivePackets() {return transportWorker.receiveQueue;}public void addPacket(String packet) {messageWorker.addPacket(packet);}public void wakeUp() {messageWorker.wakeUp();}public void start_check_in() {messageWorker.start_check_in();}public String newSessionID() {return String.valueOf(System.currentTimeMillis());}}
4.MessageWorker.class:
public class MessageWorker extends Thread {protected NetTransportWorker worker;protected Queue<String> sendQueue;protected Timer timer;protected TimerTask task;// 10S发送一个确认在线的报到protected final long delay = 30000;protected MessageWorker(final NetTransportWorker worker) {this.worker = worker;sendQueue = new ConcurrentLinkedQueue<String>();task = new TimerTask() {@Overridepublic void run() {// TODO Auto-generated method stubString packet = "hello\n";addPacket(packet);wakeUp();}};}public static String getLocalHostIp() { String ipaddress = "no_data"; try { Enumeration<NetworkInterface> en = NetworkInterface .getNetworkInterfaces(); // 遍历所用的网络接口 while (en.hasMoreElements()) { NetworkInterface nif = en.nextElement();// 得到每一个网络接口绑定的所有ip Enumeration<InetAddress> inet = nif.getInetAddresses(); // 遍历每一个接口绑定的所有ip while (inet.hasMoreElements()) { InetAddress ip = inet.nextElement(); if (!ip.isLoopbackAddress() && InetAddressUtils.isIPv4Address(ip .getHostAddress())) { return ipaddress =ip.getHostAddress(); } } } } catch (SocketException e) { System.out.print("获取IP 失败"+e.toString()); e.printStackTrace(); } return ipaddress;}protected void start_check_in() {if(timer==null){timer=new Timer();timer.schedule(task, delay, delay);}}public void addPacket(String packet) {sendQueue.add(packet);wakeUp();}public synchronized void wakeUp() {notify();}@Overridepublic synchronized void run() {// TODO Auto-generated method stubwhile (true) {try {while (sendQueue.size() > 0) {String packet = sendQueue.peek();if (worker.writeBuf(packet.getBytes("UTF8"))){sendQueue.poll();}else{sendQueue.clear();}}wait();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}
5.NetTransportWorker.class:
public class NetTransportWorker extends Thread {protected Socket socket = null;protected static final int CONNECT_TIMEOUT = 10000;protected static final int READ_TIMEOUT = 60000;protected static final int RECONNECT_TIME = 30000;protected ByteArrayOutputStream readByte;protected DataOutputStream readData;static {java.lang.System.setProperty("java.net.preferIPv6Addresses", "true");};protected final byte connect = 1;protected final byte running = 2;protected byte state = connect;protected boolean onWork;// 是否工作状态public static final String sysError = "与服务器连接断开了,马上重新连接!";protected IMService service;protected Queue<String> receiveQueue; String packet;DataOutputStream output;DataInputStream input;protected NetTransportWorker() {onWork = true;readByte = new ByteArrayOutputStream();readData = new DataOutputStream(readByte);receiveQueue = new ConcurrentLinkedQueue<String>();}protected void setRecever(IMService service){this.service=service;}@Overridepublic void run() {// TODO Auto-generated method stubwhile (onWork) {switch (state) {case connect:connect();break;case running:running();break;}}}private synchronized void running() {try { byte[] buffer=new byte[1024]; ByteArrayOutputStream baos=new ByteArrayOutputStream(); byte[] reallyByte; int number; while((number=input.read(buffer, 0, buffer.length))>0) { baos.write(buffer, 0, number); reallyByte=baos.toByteArray(); String info=new String(reallyByte);Message mess=new Message();mess.obj=info;service.handler.sendMessage(mess);baos.reset(); }} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();sendInfoMessageToUI(sysError);close();}}//protected void handleTimeout(Selector selector) {// try{// Iterator<SelectionKey> iter = selector.keys().iterator();// while(iter.hasNext()){// SelectionKey key = iter.next();// System.out.println("clear:"+key);// // if ( (key.interestOps() & SelectionKey.OP_READ) !=0 ) {// key.cancel();// key.attach(null);// key.channel().close();// }// }// }catch(Exception e2){// e2.printStackTrace();// }// } //public final String readBuf(InputStream input)//throws IOException {// byte[] buffer=new byte[1024];// ByteArrayOutputStream baos=new ByteArrayOutputStream();// int number;// while((number=input.read(buffer, 0, buffer.length))>0)// {// baos.write(buffer, 0, number); // }//byte[] reallyByte=baos.toByteArray();//String info=new String(reallyByte);//return info;//}protected final boolean writeBuf(byte[] data) throws IOException {if (socket != null && socket.isConnected()&&output!=null&&!socket.isOutputShutdown()&& state == running) {output.write(data);output.flush();return true;} else if (state != running) {return false;}return false;}private void sendInfoMessageToUI(String text) {//TuliaoBaseActivity.sendMessage(ProtocolConst.CMD_SYSTEM_ERROR, text);////self.setOnline(false);//Iterator<Integer> keys = all_user.keySet().iterator();//while (keys.hasNext()) {//UserInfo info = all_user.get(keys.next());//info.setOnline(false);//}//Message msg = new Message();//msg.what = ProtocolConst.CMD_HAS_USER_OFFLINE;//msg.obj = all_user;//TuliaoBaseActivity.sendMessage(msg);}/** * 唤起连接线程重新连接 */protected synchronized void reconnect() {close();//notify();}private synchronized void connect() {try {SocketAddress sa=new InetSocketAddress(ProtocolConst.ip,ProtocolConst.port);socket=new Socket();socket.setSoTimeout(READ_TIMEOUT);socket.setTcpNoDelay(true);//socket.setTrafficClass(0x04 | 0x10);socket.connect(sa, CONNECT_TIMEOUT);output=new DataOutputStream(socket.getOutputStream());input=new DataInputStream(socket.getInputStream());if (socket.isConnected()) {// 连接成功开始监听服务端消息// 发送一个验证数据包到服务器进行验证state = running;writeBuf("start\n".getBytes("UTF8")); //客户端接收到start表示心跳的开始} else {// 关闭通道过30S重新开始连接sendInfoMessageToUI("服务器连接失败" + (RECONNECT_TIME / 1000)+ "秒后再尝试连接");wait(RECONNECT_TIME);reconnect();}} catch (Exception e) {// TODO Auto-generated catch block// 有异常关闭通道过60S重新开始连接e.printStackTrace();sendInfoMessageToUI((RECONNECT_TIME / 1000) + "秒后再尝试连接");try {wait(RECONNECT_TIME);reconnect();} catch (InterruptedException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}}private void close() {state = connect;try {if (socket != null) {socket.close();socket = null;}if(input!=null){input.close();input=null;}if(output!=null){ output.close(); output=null;}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
6.ProtocolConst.class:
public class ProtocolConst { protected static final String ip = "192.168.1.167";protected static final int port = 4321;}
7.BootReceiver.class:
public class BootReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent arg1) {// TODO Auto-generated method stub context.startService(new Intent(context, IMService.class));}}
8.MainActivity.class:
public class MainActivity extends Activity implements OnClickListener{ /** Called when the activity is first created. */EditText username;EditText socketAddress;EditText showContent;Button connectButton;Button disconnectButton;Button quitButton;Button sendButton;EditText sendContent;String nameValue;String addressValue; public static final String reconnectTag="reconnect"; SocketAddress address; ReceiverHandler rh; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); username=(EditText)this.findViewById(R.id.username); socketAddress=(EditText)this.findViewById(R.id.serveraddress); showContent=(EditText)this.findViewById(R.id.showcontent); sendContent=(EditText)this.findViewById(R.id.sendcontent); connectButton=(Button)this.findViewById(R.id.connect); disconnectButton=(Button)this.findViewById(R.id.disconnect); quitButton=(Button)this.findViewById(R.id.quit); sendButton=(Button)this.findViewById(R.id.send); sendContent.setOnClickListener(this); connectButton.setOnClickListener(this); disconnectButton.setOnClickListener(this); quitButton.setOnClickListener(this); sendButton.setOnClickListener(this); findViewById(R.id.send_code).setOnClickListener(this); findViewById(R.id.send_close_code).setOnClickListener(this); this.startService(new Intent(this, IMService.class)); } public class ReceiverHandler extends BroadcastReceiver{ Context context=null; public ReceiverHandler(Context context) { this.context=context; } public void registerAction(String action){ IntentFilter filter=new IntentFilter(); filter.addAction(action); context.registerReceiver(this, filter); } @Override public void onReceive(Context context, Intent intent) { if(intent.getAction().equals(IMService.messageTag)) { String message=intent.getStringExtra("message"); Message mess=new Message(); mess.obj=message; handler.sendMessage(mess); } } } public Handler handler= new Handler() { public void handleMessage(Message msg) { String message=msg.obj.toString(); showContent.append(message); } };@Overrideprotected void onStart() {// TODO Auto-generated method stubsuper.onStart();rh=new ReceiverHandler(this);rh.registerAction(IMService.messageTag);}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();unregisterReceiver(rh);}public static final String FLAG_PLAYER_VIDEO="0";public static final String FLAG_CREATE_CODE="1";public static final String FLAG_CLOSE_CODE="2";public static String createPar(String productId) { String ret=""; JSONObject menu = new JSONObject(); try {menu.put("flag", FLAG_PLAYER_VIDEO);menu.put("msg", "播放商品视频");menu.put("productId", productId); ret=menu.toString(); } catch (JSONException e) {// TODO Auto-generated catch blocke.printStackTrace();} return ret; } public static String createCodePar(String productId){ String ret=""; JSONObject menu = new JSONObject(); try {menu.put("flag", FLAG_CREATE_CODE);menu.put("msg", "显示商品二维码");menu.put("productId", productId); ret=menu.toString(); } catch (JSONException e) {// TODO Auto-generated catch blocke.printStackTrace();} return ret; } public static String closeCodePar(){ String ret=""; JSONObject menu = new JSONObject(); try {menu.put("flag", FLAG_CLOSE_CODE);menu.put("msg", "关闭商品二维码");menu.put("productId", null); ret=menu.toString(); } catch (JSONException e) {// TODO Auto-generated catch blocke.printStackTrace();} return ret; } public static String getProductID(String str){ String ret=""; if(str!=null&&!str.equals("")){ try {JSONObject obj=new JSONObject(str);ret=obj.getString("productId");} catch (JSONException e) {// TODO Auto-generated catch blocke.printStackTrace();} } return ret; }@Overridepublic void onClick(View v) {// TODO Auto-generated method stubString text;switch(v.getId()){case R.id.send: text=sendContent.getText().toString();if(text!=null&&!text.equals("")){text=createPar(text)+"\n";Log.i("text", text);IMService.addPacket(text);IMService.wakeUp(); sendContent.setText("");}break;case R.id.send_code: text=sendContent.getText().toString();if(text!=null&&!text.equals("")){text=createCodePar(text)+"\n";Log.i("text", text);IMService.addPacket(text);IMService.wakeUp(); sendContent.setText("");}break;case R.id.send_close_code:text=closeCodePar()+"\n";Log.i("text", text);IMService.addPacket(text);IMService.wakeUp();break;}}}
10.main.xml:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <LinearLayout android:id="@+id/linearLayout1" android:layout_width="fill_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/textView3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/Name" /> <EditText android:id="@+id/username" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" > <requestFocus /> </EditText> </LinearLayout> <LinearLayout android:id="@+id/linearLayout2" android:layout_width="fill_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/Server" /> <EditText android:id="@+id/serveraddress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" /> </LinearLayout> <LinearLayout android:id="@+id/linearLayout4" android:layout_width="fill_parent" android:layout_height="340dp" android:layout_gravity="bottom" > <EditText android:id="@+id/showcontent" android:layout_width="268dp" android:layout_height="fill_parent" android:inputType="textMultiLine" /> <LinearLayout android:id="@+id/linearLayout5" android:layout_width="wrap_content" android:layout_height="fill_parent" android:gravity="center" android:orientation="vertical" > <Button android:id="@+id/connect" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/Connect" /> <Button android:id="@+id/disconnect" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/Disconnect" /> <Button android:id="@+id/quit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/Quit" /> </LinearLayout> </LinearLayout> <LinearLayout android:id="@+id/linearLayout6" android:layout_width="fill_parent" android:layout_height="wrap_content" > <EditText android:id="@+id/sendcontent" android:layout_width="245dp" android:layout_height="wrap_content" android:layout_weight="233.73" /> <Button android:id="@+id/send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="0.15" android:text="@string/Send" /> <Button android:id="@+id/send_code" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="弹出二维码" /> <Button android:id="@+id/send_close_code" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="关闭二维码" /> </LinearLayout> <LinearLayout android:id="@+id/linearLayout3" android:layout_width="wrap_content" android:layout_height="387dp" > </LinearLayout></LinearLayout>
11.AndroidManifest.xml
<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.gys.im" android:versionCode="1" android:installLocation="preferExternal" android:versionName="1.0" > <uses-sdk android:minSdkVersion="16" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <application android:icon="@drawable/ic_launcher" android:debuggable="true" android:label="@string/app_name" > <activity android:label="@string/app_name" android:name=".MainActivity" > <intent-filter > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name="com.gys.service.IMService"></service> <receiver android:name="com.gys.BroadCast.BootReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> <category android:name="android.intent.category.HOME" /> </intent-filter> </receiver> </application></manifest></span>
以上就是我关于Android的Socket通讯客户端的代码,下一篇中我会讲解服务端的代码,并与客户端对接。共勉.
- Android之Socket,Service通讯
- Socket编程之android service
- SOCKET之通讯超时
- socket通讯之TCP
- Android+socket+通讯
- Android 客户端socket通讯
- android socket 双向通讯
- android socket通讯
- Android Socket通讯
- android socket通讯过程?
- Android Socket通讯
- Android Socket通讯
- Android通讯-Socket
- Android开发笔记:Socket通讯之Tcp客户端
- Android基于客户端和服务器的Socket编程例子之Socket基础通讯--socket相关知识
- Android基于客户端和服务器的Socket编程例子之Socket基础通讯--socket模型使用
- TCP/IP 通讯之socket
- 进程通讯之本地Socket
- 第十一周项目1-验证算法(4)-哈夫曼编码的算法验证
- 嵌入式linux软件平台--QtLib、QwtLib实现图形显示(二)
- CTRL+F的作用
- ADO数据库
- mysql 5 长度解析
- Android之Socket,Service通讯
- 第十一周-项目一 验证算法(3)中序线索化二叉树的算法验证
- 美国大选与数据可视化
- 第十一周项目1-验证算法(2)-二叉树构造算法的验证
- 单调队列 学习笔记
- 视图的运行时交互模型(The Runtime Interaction Model for Views)
- 1492: [NOI2007]货币兑换Cash
- 第九周项目4-广义表算法库及应用(1)
- 嵌入式应用编程BUG-STM32串口应用