文档章节

Android 中的Socket通讯机制

tomcater
 tomcater
发布于 2014/04/20 17:55
字数 1219
阅读 1104
收藏 80

Android中的网络通讯无非Http和Socket,Socket有两种形式——TCP和UDP。

TCP与UDP区别

TCP---传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。
UDP---用户数据报协议,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。

下面通过一个简单的例子介绍一下两种形式的客户端

Socket socket = new Socket("192.168.3.119",7628);//创建Socket实例,并绑定连接远端IP地址和端口

OutputStream ops = socket.getOutputStream();//定义一个输出流,来自于Socket输出流
  
byte[] bytes = b.getBytes();
       
ops.write(bytes);//向输出流中写入数据

ops.flush();//刷行输出流

//至此,在连接成功的情况下,服务端应该就能收到发送过去的流了。


//接下来是接收服务器发送过来的数据
InputStream ips = socket.getInputStream();//定义输入流,来自于socket的输入流

byte[] bytes2 = new byte[20];

ips.read(bytes2);//读取输入流数据
  
String str = new String(bytes2);//转换成字符串

btn.setText(str);//显示出来(我是现实在button上,当然,这个方法不正规,不过可以让我少放点空间,看上去界面干净点,只要能看到效果就行)

socket.close();

接下来是UDP的

 DatagramSocket dgs = new DatagramSocket();//建立一个Socket,这个Socket将作为一个发送器,将Socket包发送出去
    
InetAddress inet = InetAddress.getByName("192.168.3.119");//创建一个InetAddress,ip地址为要发动到的远端的服务器IP
    
DatagramPacket dgp = new DatagramPacket("test2".getBytes(), "test2".getBytes().length,inet,7628);//创建一个UDP数据包,数据包包含远端的IP地址及端口
    
dgs.send(dgp);//发送    
   
dgs.close();
    
    
DatagramSocket dgs2 = new DatagramSocket(9997);//创建另一个UDPSocket,
    
DatagramPacket dgp2 = new DatagramPacket(new byte[20],20); //创建一个空报文包
dgs2.receive(dgp2);//接收数据并填充到报文包中
    
String str = new String(dgp2.getData());//获取报文包里的数据并转换成字符串
    
btn.setText(str);//显示获得的数据
    
dgs2.close();//关闭Socket

需要特别注意的地方,在不做端口映射的情况下,UDP可能无法接受到服务器端发送过来的数据,原因是使用eclipse开发的时候,调试程序是用的模拟环境,模拟环境下,接收数据是要做端口映射的,因为模拟环境下,没有自己真实的IP地址和端口,模拟器是使用5554来运行的,发送数据到PC没问题,但是 PC发送到模拟器的时候,需要把本机的端口映射到模拟器上,真机环境不需要,具体操作方式如下

1、运行模拟器
2、打开DOS命令行窗口
    执行:telnet localhost 5554
   5554是模拟器的端口,执行之后会进入android console
3、 在console下执行:
   redir add udp :8000:9000
   其中,第一个端口号是PC的端口,第二个端口号是模拟器端口。
   执行此命令之后,会把PC 8000端口接收到的数据转到模拟器的9000端口,模拟器就能从9000端口接收UDP数据包了

另外,要实现Socket,必须在 AndroidManifest.xml 中加入权限如下

1 <uses-permission android:name="android.permission.INTERNET" />

服务器端:

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class SocketActivity extends Activity {
    /** Called when the activity is first created. */
 private Button startButton = null;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        startButton = (Button)findViewById(R.id.startListener);
        startButton.setOnClickListener(new StartSocketListener());
    }
    
    class StartSocketListener implements OnClickListener{
  @Override
  public void onClick(View v) {
   new ServerThread().start();
  }
     
    }
    
    class ServerThread extends Thread{
     /*public void run(){
      //声明一个ServerSocket对象
      ServerSocket serverSocket = null;
      try {
       //创建一个ServerSocket对象,并让这个Socket在7628端口监听
    serverSocket = new ServerSocket(7628);
    //调用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();
   }
   finally{
    try {
     serverSocket.close();
    } catch (IOException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
  
     }*/
     public void run(){
      try {
       //创建一个DatagramSocket对象,并指定监听的端口号
    DatagramSocket socket = new DatagramSocket(7628);
    byte data [] = new byte[1024];
    //创建一个空的DatagramPacket对象
    DatagramPacket 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);
   } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
     }
    }
}

© 著作权归作者所有

共有 人打赏支持
tomcater
粉丝 4
博文 43
码字总数 55169
作品 0
海淀
程序员
加载中

评论(5)

tomcater
tomcater

引用来自“zhaosod”的评论

http协议和socket属于不同两层上的概念把
谢谢指正
zhaosod
zhaosod

引用来自“純白陰影”的评论

引用来自“zhaosod”的评论

http协议和socket属于不同两层上的概念把

HTTP基于TCP
对,是的
純白陰影
純白陰影

引用来自“zhaosod”的评论

http协议和socket属于不同两层上的概念把

HTTP基于TCP
zhaosod
zhaosod
http协议和socket属于不同两层上的概念把
萝卜007工作室
萝卜007工作室
简单明了
android网络通信之socket教程实例汇总

一、socket基础 1、Socket通讯机制(详细),如何将socket通信的客户端与服务器 http://www.eoeandroid.com/thread-61727-1-1.html 2、Http和Socket区别 http://www.eoeandroid.com/thread-9...

程序袁_绪龙
2014/12/11
0
0
Android TCP/IP Socket Test

TCP/IP协议:Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协议、Internet国际互联网络的基础,由网...

postdep
2014/11/01
0
1
Android源码学习之八—系统启动过程

Android源码数量庞大,虽然对它的学习从未停止,但是整理成这样的文字,实在是费时费力的一件事情,不过好在前文已经对其基本机制加以分析,相信以此为基础,其他的内容学习起来就没那么困难...

晨曦之光
2012/03/13
0
0
Android客户端与服务器交互方式-小结

最近的Android项目开发过程中一个问题困扰自己很长时间,Android客户端与服务器交互有几种方式,最常见的就是webservices和json。要在Android手机客户端与pc服务器交互,需要满足下面几种条件...

x-knight_勋爵
2016/04/18
0
0
android socket各种通信

我已经试验成功: ps:模拟器做服务器,PC机做客户端。如果通过wifi连接的话直接访问IP就行,不用重定向。 PC访问模拟器用localhost即127.0.0.1, 模拟器 访问 模拟器用10.0.2.2 本人已成功运...

buleberry
2014/04/01
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Python深体验,常见的数据处理方式(必须要懂的)

1.缺失值处理 - 拉格朗日插值法 input_file数据文件内容(存在部分缺失值): from scipy.interpolate import lagrangeimport pandas as pdimport numpy as npinput_file = './dat...

无也Python
24分钟前
2
0
Spring MVC注解故障追踪记

Spring MVC是美团点评很多团队使用的Web框架。在基于Spring MVC的项目里,注解的使用几乎遍布在项目中的各个模块,有Java提供的注解,如:@Override、@Deprecated等;也有Spring提供的注解,...

Skqing
26分钟前
4
0
区块链入门教程以太坊源码分析cmd包分析

  兄弟连区块链入门教程以太坊源码分析cmd包分析。 ### cmd包概述 * geth 主要Ethereum CLI客户端。它是Ethereum网络(eth主网,测试网络或私有网)的入口点,使用此命令可以使节点作为ful...

兄弟连区块链入门教程
28分钟前
1
0
@Autowired 报红线

代码可正常跑,不过红线看着有点难受,解决方案 使用@Autowired(required=false) 或者@Resource. 这两者区别网上一大堆

斩神魂
33分钟前
1
0
DataTable中检索信息 (C#)

C#_从DataTable中检索信息 存在于内存中的虚拟表DataTable,绑定在数据显示控件后,如果想在再检索其中某些信息,可以利用DataTable.Select方法进行检索,避免了重复的读取数据库。Select方法...

CS-CS01
41分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部