Android的Socket通信


1 重庆邮 电大学移动 互联工作室 重庆邮 电大学移动 互联工作室 重庆邮 电大学移动 互联工作室 重庆邮 电大学移动 互联工作室 智能校 园项目开发 组指南 智能校 园项目开发 组指南 智能校 园项目开发 组指南 智能校 园项目开发 组指南 第四期 Socket Socket Socket Socket 通信 目 录 一、Socket通信简介............................................................................2 1.1 什么是 Socket..................................................................................2 1.2 Socket 的分类..................................................................................2 二、Socket的基本通信模型...............................................................2 2.1 TCP 通信模型.................................................................................3 2.2 UDP 通信模型.................................................................................3 三、Socket基本实现原理...................................................................3 3.1 基于 TCP 协议的 Socket.................................................................3 3.2 基于 UDP 协议的数据传输..............................................................3 四、Socket的基本实现方式...............................................................4 4.1 TCP 方式........................................................................................ 4 4.2 UDP 方式........................................................................................ 5 五、Socket通信实例............................................................................6 六、Socket通信过程中的常见问题及解决方案.............................8 2 引 言 随着 CES2012在拉斯维加斯的落幕,我们可以清楚的看到,移动互联网决定着全 球移动市场的发展趋势,它将像 PC机改变我们以前的生活一样,改变我们未来的生 活。移动互联的实现需要确保数据的可靠和有效传输。因此,数据通信是开发设计过 程中必不可少的一个重要环节。 在上一期指南中,我们介绍了如何利用控件来布局应用的 UI界面,好的界面设 计是吸引用户的第一步,当然,这还远远不够,高效的数据传输,流畅的界面跳转, 才是高品质用户体验的最终归属。下面,我们来介绍 Android与服务器的网络通信。 通信通常包含两个部分,一是应用程序的内部通信,一是客户端和服务器之间的网络 通信,本期指南我们主要介绍 Android客户端与服务器之间的网络通信。 一、Socket Socket Socket Socket 通信简介 Android与服务器的通信方式主要有两种,一是 Http通信,一是 Socket通信。 两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接 通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据。而 Socket 通信则是在双方建立起连接后就可以直接进行数据的传输,在连接时可实现信息的主 动推送,而不需要每次由客户端想服务器发送请求。 那么,什么是 socket?Socket又称套接字,在程序内部提供了与外界通信的端 口,即端口通信。通过建立 socket连接,可为通信双方的数据传输传提供通道。socket 的主要特点有数据丢失率低,使用简单且易于移植。 下面,我们来进一步了解认识 Socket。 1.1 1.1 1.1 1.1 什么是 SocketSocketSocketSocket Socket是一种抽象层,应用程序通过它来发送和接收数据,使用 Socket可以将 应用程序添加到网络中,与处于同一网络中的其他应用程序进行通信。简单来说, Socket提供了程序内部与外界通信的端口并为通信双方的提供了数据传输通道。 1.21.21.21.2 Socket Socket Socket Socket 的分类 根据不同的的底层协议,Socket的实现是多样化的。本指南中只介绍 TCP/IP协 议族的内容,在这个协议族当中主要的 Socket类型为流套接字(stream socket)和 数据报套接字(datagram socket)。流套接字将 TCP作为其端对端协议,提供了一个 可信赖的字节流服务。数据报套接字使用 UDP协议,提供数据打包发送服务。 下面,我们来认识一下这两种 Socket类型的基本实现模型。 二、Socket Socket Socket Socket 的基本通信模型 3 2.1 TCP 通信模型 2.2 UDP 通信模型 下面,我们根据上述模型简述 Socket的基本实现原理。 三、Socket Socket Socket Socket 基本实现原理 3.1基于 TCP协议的 Socket 服务器端首先声明一个 ServerSocket对象并且指定端口号,然后调用 4 Serversocket的accept()方法接收客户端的数据。accept()方法在没有数据进 行接收的处于堵塞状态。(Socket socket = serversocket.accept()),一旦接收到 数据,通过 inputstream读取接收的数据。 客户端创建一个 Socket对象,指定服务器端的 ip地址和端口号(Socket socket = new Socket("172.168.10.108",8080);),通过 inputstream读取数据,获取服务 器发出的数据(OutputStream outputstream =socket.getOutputStream()),最后将 要发送的数据写入到 outputstream即可进行 TCP协议的 socket数据传输。 3.2基于 UDP协议的数据传输 服务器端首先创建一个 DatagramSocket对象,并且指点监听的端口。接下来创建 一个空的DatagramSocket 对象用于接收数据(byte data[] = new byte[1024;]DatagramSocket packet = new DatagramSocket(data,data.length)), 使用DatagramSocket 的receive 方法接收客户端发送的数据,receive()与 serversocket的accepet()类似,在没有数据进行接收的处于堵塞状态。 客户端也创建个 DatagramSocket对象,并且指点监听的端口。接下来创建一个 InetAddress对象,这个对象类似与一个网络的发送地址(InetAddress serveraddress = InetAddress.getByName("172.168.1.120")).定义要发送的一个 字符串,创建一个 DatagramPacket对象,并制定要讲这个数据报包发送到网络的那 个地址以及端口号,最后使用 DatagramSocket的对象的 send()发送数据。*(String str = "hello";byte data[] = str.getByte();DatagramPacket packet = new DatagramPacket(data,data.length,serveraddress,4567);socket.send(packet);) 理解起来似乎比较困难,我们通过下面的例子来看看 Socket的实现方式。 四、Socket Socket Socket Socket 的基本实现方式 4.1 TCP 方式 TCP协议客户端实现: //创建一个 Socket对象,指定服务器端的 IP地址和端口号 Socket socket = new Socket("192.168.1.104",4567); //使用 InputStream读取硬盘上的文件 InputStream inputStream = new FileInputStream("f://file/words.txt"); //从Socket当中得到 OutputStream OutputStream outputStream = socket.getOutputStream(); byte buffer [] = new byte[4*1024]; int temp = 0 ; //将InputStream当中的数据取出,并写入到 OutputStream当中 while((temp = inputStream.read(buffer)) != -1) 5 { outputStream.write(buffer, 0, temp); } outputStream.flush(); } TCP协议服务器端实现: //声明一个 ServerSocket对象 ServerSocket serverSocket = null; try { //创建一个 ServerSocket对象,并让这个 Socket在4567端口监听 serverSocket = new ServerSocket(4567); //调用 ServerSocket的accept()方法,接受客户端所发送的请求, //如果客户端没有发送数据,那么该线程就停滞不继续 Socket socket = serverSocket.accept(); //从Socket当中得到 InputStream对象 InputStream inputStream = socket.getInputStream(); byte buffer [] = new byte[1024*4]; int temp = 0; //从InputStream当中读取客户端所发送的数据 while((temp = inputStream.read(buffer)) != -1){ System.out.println(new String(buffer,0,temp)); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } serverSocket.close(); } 4.2 UDP 方式 UDP的客户端代码实现如下: public static void main(String[] args) { try { //首先创建一个 DatagramSocket对象 DatagramSocket socket = new DatagramSocket(4567); //创建一个 InetAddree 6 InetAddress serverAddress = InetAddress.getByName("192.168.1.104"); String str = "hello"; //这是要传输的数据 byte data [] = str.getBytes(); //把传输内容分解成字节 //创建一个 DatagramPacket对象,并指定要讲这个数据包发送到网 络当中的哪个地址,以及端口号 DatagramPacket packet = new DatagramPacket(data,data.length,serverAddress,4567); //调用 socket对象的 send方法,发送数据 socket.send(packet); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } UDP的服务端代码实现如下: //创建一个 DatagramSocket对象,并指定监听的端口号 DatagramSocket socket = new DatagramSocket(4567); byte data [] = new byte[1024]; //创建一个空的 DatagramPacket对象 Datagram Packet packet = new DatagramPacket(data,data.length); //使用 receive方法接收客户端所发送的数据, //如果客户端没有发送数据,该进程就停滞在这里 socket.receive(packet); String result = new String(packet.getData(),packet.getOffset(), packet.getLength()); System.out.println("result--->" + result); 五、Socket Socket Socket Socket 通信实例 通过上面的例子,我们可以简单的了解到Socket通信的基本实现方式和处理过程, 接下来,我们就TCP协议的通信方式,再结合一个简单的实例,来加深对Socket通信 的了解。 该实例为一个简单的登陆操作,当服务器处于监听状态时,客户端向服务器发送 登陆请求,当所请求的登陆信息和服务器验证信息吻合,返回信息“1”,在客户端中 通过Toast现实,当登陆信息错误,返回登陆错误信息,用“2”表示。代码如下: 客户端: importimportimportimportjava.io.DataInputStream; 7 importimportimportimportjava.io.DataOutputStream; importimportimportimportjava.io.IOException; importimportimportimportjava.net.Socket; importimportimportimportjava.net.UnknownHostException; importimportimportimportandroid.app.Activity; importimportimportimportandroid.os.Bundle; importimportimportimportandroid.view.View; importimportimportimportandroid.widget.Button; importimportimportimportandroid.widget.Toast; publicpublicpublicpublicclassclassclassclassSocketActivityextendsextendsextendsextendsActivity{ /**Calledwhentheactivityisfirstcreated.*/ @Override publicpublicpublicpublicvoidvoidvoidvoidonCreate(BundlesavedInstanceState){ supersupersupersuper.onCreate(savedInstanceState); setContentView(R.layout.main); Buttonbutton=(Button)findViewById(R.id.button); button.setOnClickListener(newnewnewnewView.OnClickListener(){ @Override publicpublicpublicpublicvoidvoidvoidvoidonClick(Viewarg0){ //TODOTODOTODOTODOAuto-generatedmethodstub connectToserver(); } }); } publicpublicpublicpublicvoidvoidvoidvoidconnectToserver(){ //TODOTODOTODOTODOAuto-generatedmethodstub trytrytrytry{ //建立一个socket通信端口 Socketsocket=newnewnewnewSocket("192.168.0.100",8080); System.out.println("-------------------------------"); DataOutputStreamout=newnewnewnewDataOutputStream(socket.getOutputStream()); DataInputStreamdin=newnewnewnewDataInputStream(socket.getInputStream()); //通过输出流发出数据 out.writeUTF("<#login#>"+"yy"); System.out.println("-------------------------------"); 8 whilewhilewhilewhile(truetruetruetrue){ Stringmsg=""; //从输入流读入数据 msg=din.readUTF(); System.out.println(msg); ifififif(!msg.equals("")){ Toast.makeText(SocketActivity.thisthisthisthis,msg,1).show(); out.close(); din.close(); socket.close(); breakbreakbreakbreak; } } }catchcatchcatchcatch(UnknownHostExceptione) { e.printStackTrace(); }catchcatchcatchcatch(IOExceptione) { //TODOTODOTODOTODOAuto-generatedcatchblock e.printStackTrace(); } } } 服务器: importimportimportimportjava.io.DataInputStream; importimportimportimportjava.io.DataOutputStream; importimportimportimportjava.io.IOException; importimportimportimportjava.net.ServerSocket; importimportimportimportjava.net.Socket; publicpublicpublicpublicclassclassclassclassService{ publicpublicpublicpublicstaticstaticstaticstaticvoidvoidvoidvoidmain(Stringargs[]){ trytrytrytry{ ServerSocketss=newnewnewnewServerSocket(8080); System.out.println("llistening..."); whilewhilewhilewhile(truetruetruetrue){ Socketsocket=ss.accept(); System.out.println("clientconnected..."); DataInputStreamin=newnewnewnewDataInputStream(socket.getInputStream()); DataOutputStreamout=newnewnewnewDataOutputStream(socket.getOutputStream()); Stringoo=in.readUTF(); 9 System.out.println(oo); ifififif(oo.startsWith("<#login#>"))//解析数据,对数据进行判断 { Stringcontent=oo.substring(9); ifififif(content.equals("yy")) { out.writeUTF("1"); } elseelseelseelse { out.writeUTF("2"); } in.close(); socket.close(); } } }catchcatchcatchcatch(IOExceptione){ //TODOTODOTODOTODOAuto-generatedcatchblock e.printStackTrace(); } } } 以上就是Socket通信中最常见的字符串通信,另外还有图片和文件传输,基本思 路也都是先转化为字符串数组再进行传输,请读者自行学习。 六、Socket Socket Socket Socket 通信过程中的常见问题及解决方案 在Socket通信的实际应用中,我们还会碰到各种问题。下面,我们将结合开发过 程中经常遇到的一些 Socket通信问题和大家进行分享,希望能对大家的学习有所帮 助。 问题 问题分析 问题解决 1.客户端接收数据超时, 导致客户端无响应,一段 时间后,弹出进程错误 造成该问题主要有两个 方面,一个是服务器繁 忙,没有及时返回数据; 二是服务器有返回数据, 但由于网络繁忙,客户端 没能及时接收到数据。开 始,程序在等待数据接 收,从用户的视觉,则是 ‘卡机’状态,当长时间 没有响应后,在系统保护 机制下,系统会自动发送 一个 singal3 信号杀掉该 处理建议: � 自设超时时间,避免延 时过长,造成‘卡机’ 的假象。同时逃避系统 的查杀。 � 使用异常处理方法, Catch 到超时错误,并 通知用户访问超时。 10 进程,此时会弹出一个询 问是否关闭程序的进程 错误对话框。 2.服务器接收数据超时, 会导致服务器崩溃 造成该问题主要是由于 网络繁忙,和网络信号不 好,导致服务器一直处在 数据接收的状态,超出服 务器的超时时间后,服务 器会崩溃。 考虑到该问题的出现对 用户是隐形的,即出现该 问题时,用户不会察觉到 是服务器出现崩溃,而只 会看到网络繁忙的提醒。 处理建议: � 服务器采用多线程机 制, 把数据接收代码写到 子线程里,避免因该问 题造成主线程出错,导 致服务器崩溃 3.IP 复用问题,也容易 造成服务器崩溃 造成该问题的主要原因 是由于 socket 是采用套 接字方式进行数据传输 的机制,如果有多个 ip 相同的客户端同时访问 服务器,容易导致数据传 输紊乱和服务器崩溃。 客户端出现相同 ip 的原 因是当几个客户端接入 同一个局域网,并同时访 问‘外网’的服务器,此 时,这些客户端表现出相 同的 IP。 处理建议: � 服务器采用多线程机制 � 尽量避免特殊的网络环 境 Socket通信过程中还应注意以下几点: � 客户端设计过程中,网络访问权限申请: � 服务器的端口最好选择比较靠后,避免与系统中其他功能冲突 � 客户端代码中的端口要与服务器的监听端口一致 � 完成数据传输最好关闭流 � 服务器最好使用多线程操作
还剩9页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享pdf获得金币 ] 1 人已下载

下载pdf

pdf贡献者

wnjnln123

贡献于2013-03-18

下载需要 8 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf