Android 网络编程(一) 网络基本知识的了解

Android网络编程基础(一) - 基础知识 内容介绍:Android网络编程基础 博客地址:http://blog.youkuaiyun.com/kevindgk 版权声明:本文为原创文章,未经允许不得转载 联系方式:815852777@qq.com 前言 推荐书籍 基础知识 计算机网络概述 OSI参考模型和TCPIP模型 IP地址和端口号 端口号 单播组播广播 Android基本网络支持 获取网络基本信息 Socket相关 TCP通 阅读详情

引言

  Android网络编程知识是Android开发过程中必不可少的内容,在网络开发的过程中,我们通常会用到像Volley、OkHttp、Retrofit这些高度封装好的框架,这使得我们的开发很便利但也屏蔽了相关的技术细节。而作为想要进一步的开发者来说,我们不但要会用,有时候更要理解其实现的原理,理解了后更能促进我们更好的使用这些框架。Ok,这篇文章我们讲一讲网络的基本知识。

OSI 七层网络模型

  为了使不同的厂家生产的计算机能够通信,以便能在更大的范围内建立计算机网络,国际标准化组织(ISO)在 1978 年提出了“开放系统互联参考模型”,即 OSI/RM 模型(Open System Interconnection/Reference Model)。他将计算机网络体系结构的通信协议划分为了七层,自下而上依次分别是:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。其中低四层完成数据传输,高三层面向用户。

物理层

物理层(Physical Layer)在局部局域网上传送数据帧(data frame),它负责管理计算机通信设备和网络媒体之间的互通。包括了针脚、电压、线缆规范、集线器、中继器、网卡、主机适配器等。

数据链路层

数据链路层(Data Link Layer)负责网络寻址、错误侦测和改错。当表头和表尾被加至数据包时,会形成帧。数据链表头(DLH)是包含了物理地址和错误侦测及改错的方法。数据链表尾(DLT)是一串指示数据包末端的字符串。例如以太网、无线局域网(Wi-Fi)和通用分组无线服务(GPRS)等。
分为两个子层:逻辑链路控制(logic link control,LLC)子层和介质访问控制(media access control,MAC)子层。

网络层

网络层(Network Layer) 决定数据的路径选择和转寄,将网络表头(NH)加至数据包,以形成分组。网络表头包含了网络数据。例如:互联网协议(IP)等。

传输层

传输层(Transport Layer)把传输表头(TH)加至数据以形成数据包。传输表头包含了所使用的协议等发送信息。例如:传输控制协议(TCP)等。

会话层

会话层(Session Layer)负责在数据传输中设置和维护计算机网络中两台计算机之间的通信连接。

表达层

表达层(Presentation Layer)把数据转换为能与接收者的系统格式兼容并适合传输的格式。

应用层

应用层(Application Layer)提供为应用软件而设的接口,以设置与另一应用软件之间的通信。例如: HTTP,HTTPS,FTP,TELNET,SSH,SMTP,POP3等。

TCP/IP 四层模型

  由于 OSI/RM 模型过于复杂难以实现,现实中广泛使用的是 TCP/IP 模型。TCP/IP 是一个协议集,是由 ARPA ( Advanced Research Projects Agency Network 高等研究计划署网络 ) 于 1977 到 1979 年推出的一种网络体系结构和协议规范。随着 Internet 的发展,TCP/IP 得到进一步的研究和推广,成为 Internet 上的 “通用模型”。
  TCP/IP 模型在 OSI 模型的基础上进行了简化,去掉了OSI参考模型中的会话层和表示层(这两层的功能被合并到应用层实现),同时将OSI参考模型中的数据链路层和物理层合并为主机到网络层。变成了四层,从下到上分别为:网络接口层、网络层、传输层、应用层。与 OSI 体系结构对比如下:

OSI七层模型

TCP/IP 四层模型

网络协议

应用层

(Application)

应用层

HTTP(超文本传输协议)

HTTPS(超文本传输安全协议)

FTP(文件传输协议)

SMTP(简单邮件传输协议)

DNS(域名服务)

等等

表示层

(Presentation)

会话层

(Session)

传输层

(Transport)

传输层

TCP(传输控制协议)

UDP(用户数据报协议)

网络层

(Network)

网际互连层

IP(网际协议)

ICMP(网络控制消息协议)

IGMP(网络组管理协议)

数据链路层

(Data Link)

网络接口层

以太网

Wi-Fi

等等

物理层

(Physical)

IP 协议

  网际协议(英语:Internet Protocol,缩写为IP),又译互联网协议,是用于分组交换数据网络的一种协议。

  IP是在TCP/IP协议族中网络层的主要协议,任务仅仅是根据源主机和目的主机的地址来传送数据。为此目的,IP定义了寻址方法和数据报的封装结构。第一个架构的主要版本,现在称为IPv4,仍然是最主要的互联网协议,尽管世界各地正在积极部署IPv6。IP协议的作用在于把各种数据包准确无误的传递给对方,其中两个重要的条件是IP地址和MAC地址(Media Access Control Address)。由于IP地址是稀有资源,不可能每个人都拥有一个IP地址,所以我们通常的IP地址是路由器给我们生成的IP地址,路由器里面会记录我们的MAC地址。而MAC地址是全球唯一的,除去人为因素外不可能重复。举一个现实生活中的例子,IP地址就如同是我们居住小区的地址,而MAC地址就是我们住的那栋楼那个房间那个人。

TCP 协议

  传输控制协议(英语:Transmission Control Protocol,缩写为TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议。

  TCP 协议被认为是稳定的协议,因为它有以下特点:

  • 面向连接,“三次握手”
  • 双向通信
  • 保证数据按序发送,按序到达
  • 超时重传

  要使用 TCP 传输数据,必须先建立连接,传输完成后释放连接。分别对应常说的“三次握手”、“四次挥手”。

TCP 的三次握手与四次挥手

  三次握手与四次分手的流程如下所示:
在这里插入图片描述

三次握手

  • 第一次握手:建立连接。客户端发送连接请求报文段,将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;
  • 第二次握手:服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,自己自己还要发送SYN请求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RCVD状态;
  • 第三次握手:客户端收到服务器的SYN+ACK报文段。然后将ACK设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。

  当客户端和服务器通过三次握手建立了TCP连接后,当数据传输完毕,断开连接时就需要进行TCP的四次挥手。

四次挥手

  TCP 协议中,在通信结束后,需要断开连接,这需要通过四次挥手,客户端或服务器均可主动发起,主动的一方先断开,这里以客户端先断开为例:

  • 第一次分手:客户端设置Seq和ACK,向服务器端发送一个FIN报文段;此时,客户端进入FIN_WAIT_1状态;客户端表示没有数据要发送给服务器端了;
  • 第二次分手:服务器端收到了客户端发送的FIN报文段,向主机1回一个ACK报文段,ACK为Sequence Number加1;客户端进入FIN_WAIT_2状态;服务器告诉客户端,我“同意”你的关闭请求;
  • 第三次分手:服务器向客户端发送FIN报文段,请求关闭连接,同时服务器进入LAST_ACK状态;服务器告诉客户端,我也没啥数据要发给你了,请求断开。
  • 第四次分手:客户端收到服务器发送的FIN报文段,向服务器发送ACK报文段,然后客户端进入TIME_WAIT状态;服务器收到客户端的ACK报文段以后,就关闭连接;此时,客户端等待2MSL后依然没有收到回复,则证明服务端已正常关闭,那好,客户端也可以关闭连接了。

为什么要进行三次握手

  三次握手的目的是为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。

“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。

为什么要进行四次挥手

  TCP 连接是全双工的,每一端都可以同时发送和接受数据,关闭的时候两端都要关闭各自两个方向的通道,总共相当于要关闭四个。

以客户端发起关闭为例
1.服务器读通道关闭
​ 2.客户端写通道关闭
​ 3.客户端读通道关闭
​ 4.服务器写通道关闭

客户端为什么要等待 2MSL?

  MSL(Maximum Segment Life),是 TCP 对 TCP Segment 生存时间的限制
  客户端在发出确认服务端关闭的 ACK 后,它没有办法知道对方是否收到这个消息,于是需要等待一段时间,如果服务端没有收到关闭的消息后会重新发出 FIN 报文,这样客户端就知道自己上条消息丢了,需要再发一次;如果等待的这段时间没有在收到 FIN 的重发报文,说明它的确已经收到断开的消息并且已经断开了。
  这个等待时间至少是:客户端的 timeout + FIN 的传输时间,为了保证可靠,采用更加保守的等待时间 2MSL。

UDP协议

  用户数据报协议(英语:User Datagram Protocol,缩写为UDP),又称用户数据报文协议,是一个简单的面向数据报的传输层协议。

  UDP是一个不可靠的或者说无连接的协议,他有以下的特点:

  • UDP 缺乏可靠性。UDP 本身不提供确认,序列号,超时重传等机制。UDP 数据报可能在网络中被复制,被重新排序。即 UDP 不保证数据报会到达其最终目的地,也不保证各个数据报的先后顺序,也不保证每个数据报只到达一次
  • UDP 数据报是有长度的。每个 UDP 数据报都有长度,如果一个数据报正确地到达目的地,那么该数据报的长度将随数据一起传递给接收方。而 TCP 是一个字节流协议,没有任何(协议上的)记录边界。
  • UDP 是无连接的。UDP 客户和服务器之前不必存在长期的关系。UDP 发送数据报之前也不需要经过握手创建连接的过程。
  • UDP 支持多播和广播。

  UDP 协议没有 TCP 协议稳定,因为它不建立连接,也不按顺序发送,可能会出现丢包现象,使传输的数据出错。但是有得就有失,UDP 的效率更高,因为 UDP 头包含很少的字节,比 TCP 负载消耗少,同时也可以实现双向通信,不管消息送达的准确率,只负责无脑发送。UDP 服务于很多知名应用层协议,比如 NFS(网络文件系统)、SNMP(简单网络管理协议)。UDP 一般多用于 IP 电话、网络视频等容错率强的场景。

Socket (套接字)

在这里插入图片描述
  Socket 作为应用层和传输层之间的桥梁,与之关系最大的两个协议就是传输层中的 TCP 和 UDP协议。
  Socket 是对 TCP/IP 协议族的一种封装,是应用层与TCP/IP协议族通信的中间软件抽象层。TCP或者UDP的报文中,除了数据本身还包含了包的信息,比如目的地址和端口,包的源地址和端口,以及其他附加校验信息。从设计模式的角度看来,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
  Socket 还可以认为是一种网络间不同计算机上的进程通信的一种方法,利用三元组(ip地址,协议,端口)就可以唯一标识网络中的进程,网络中的进程通信可以利用这个标志与其它进程进行交互。
  Socket 起源于 Unix ,Unix/Linux 基本哲学之一就是“一切皆文件”,都可以用“打开(open) –> 读写(write/read) –> 关闭(close)”模式来进行操作。因此 Socket 也被处理为一种特殊的文件。
在这里插入图片描述
  如图所示,Socket 被称为“套接字”,它把复杂的 TCP/IP 协议簇隐藏在背后,为用户提供简单的客户端到服务端接口,让我们感觉这边输入数据,那边就直接收到了数据,像一个“管道”一样。

Socket 的使用

Socket 的基本操作有以下几部分:

  1. 连接远程机器
  2. 发送数据
  3. 接收数据
  4. 关闭连接
  5. 绑定端口
  6. 监听到达数据
  7. 在绑定的端口上接受来自远程机器的连接

要实现客户端与服务端的通信,双方都需要实例化一个 Socket。
在 Java 中,客户端可以实现上面的 1、2、3、4、,服务端实现 5、6、7.
Java.net 中为我们提供了使用 TCP、UDP 通信的两种 Socket:

  • ServerSocket:流套接字,TCP
  • DatagramSocket:数据报套接字,UDP

使用 TCP 通信的 Socket 流程

服务端:

  1. 调用 ServerSocket(int port) 创建一个 ServerSocket,绑定到指定端口
  2. 调用 accept() 监听连接请求,如果客户端请求连接则接受,返回通信套接字
  3. 调用 Socket 类的 getOutputStream() 和 getInputStream() 获取输出和输入流,进行网络数据的收发
  4. 关闭套接字

客户端:

  1. 调用 Socket() 创建一个流套接字,连接到服务端
  2. 调用 Socket 类的 getOutputStream() 和 getInputStream() 获取输出和输入流,进行网络数据的收发
  3. 关闭套接字

使用 UDP 通信的 Socket 流程

服务端:

  1. 调用 DatagramSocket(int port) 创建一个数据报套接字,绑定到指定端口
  2. 调用 DatagramPacket(byte[] buf, int length) 建立一个字节数组,以接受 UDP 包
  3. 调用 DatagramSocket 的 receive() 接收 UDP 包
  4. 调用 DatagramSocket.send() 发送 UDP 包
  5. 关闭数据报套接字

客户端:

  1. 调用 DatagramSocket() 创建一个数据报套接字
  2. 调用 DatagramPacket(byte buf[], int offset, int length,InetAddress address, int port) 建立要发送的 UDP 包
  3. 调用 DatagramSocket 的 receive() 接收 UDP 包
  4. 调用 DatagramSocket.send() 发送 UDP 包
  5. 关闭数据报套接字

Demo演示:TCP 通信的 Socket 实现跨进程聊天

配置

  首先我们来实现服务端,当然要使用Socket我们需要在AndroidManifest.xml声明如下的权限:

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

  我们需要实现一个远程的Service来当作聊天程序的服务端,AndroidManifest.xml文件中配置service:

<service
            android:name=".SocketServerService"
            android:process=":remote" />

实现Service

  接下来我们在Service启动时,在线程中建立TCP服务,我们监听的是8688端口,等待客户端连接,当客户端连接时就会生成Socket。通过每次创建的Socket就可以和不同的客户端通信了。当客户端断开连接时,服务端也会关闭Socket并结束结束通话线程。服务端首先会向客户端发送一条消息:“您好,我是服务端”,并接收客户端发来的消息,将收到的消息进行加工再返回给客户端。

public class SocketServerService extends Service {

    private boolean isServiceDestroy = false;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        new Thread(new TcpServer()).start();
        Log.d("SocketServerServer", "服务端已onCreate: ");
    }

    private class TcpServer implements Runnable {

        @Override
        public void run() {
            ServerSocket serverSocket;
            try {
                //监听指定的端口
                serverSocket = new ServerSocket(SocketClientActivity.CODE_SOCKET_CONNECT);
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }
            while (!isServiceDestroy) {
                try {
                    // 如果客户端请求连接则接受,返回通信套接字
                    final Socket client = serverSocket.accept();
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                // 响应给客户端信息
                                responseClient(client);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }).start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void responseClient(Socket client) throws IOException {
        // 获取输入流 用于接收客户端消息
        BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
        // 获取输出流 用于向客户端发送消息
        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())),true);
        out.println("服务端已连接");
        while (!isServiceDestroy) {
            String str = in.readLine();
            Log.d("SocketServerServer", "服务器收到的信息: " + str);
            if (TextUtils.isEmpty(str)) {
                Log.d("SocketServerServer", "服务器收到的信息为空,已断开连接 ");
                break;
            }
            // 从客户端收到的消息加工再发送给客户端
            out.println("收到了客户端发来的消息------" + str);
        }
        in.close();
        out.close();
        client.close();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        isServiceDestroy = true;
    }
}

实现聊天程序客户端

  客户端activity_socket_client.xml 的布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/tv_message"
        android:layout_width="match_parent"
        android:layout_height="400dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal">

        <EditText
            android:id="@+id/et_receive"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="2" />

        <Button
            android:id="@+id/bt_send"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="向服务器发消息" />
    </LinearLayout>
</RelativeLayout>

  客户端Activity会在onCreate方法中启动服务端,并开启线程连接服务端Socket。为了确保能连接成功,采用了超时重连的策略,每次连接失败时都会重新建立连接。连接成功后,客户端会收到服务端发送的消息:“您好,我是服务端”,我们也可以在EditText输入字符并发送到服务端。

public class SocketClientActivity extends AppCompatActivity {

    public static final int CODE_SOCKET_CONNECT = 8688;
    private Button bt_send;
    private EditText et_receive;
    private PrintWriter mPrintWriter;
    private TextView tv_message;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_socket_client);
        initView();
        // 开启服务端
        Intent intent = new Intent(this, SocketServerService.class);
        startService(intent);
        new Thread() {
            @Override
            public void run() {
                // 连接到服务端
                connectSocketServer();
            }
        }.start();
    }

    private void initView() {
        et_receive = (EditText) findViewById(R.id.et_receive);
        bt_send = (Button) findViewById(R.id.bt_send);
        tv_message = (TextView) this.findViewById(R.id.tv_message);
        bt_send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final String msg = et_receive.getText().toString();
                //向服务器发送信息
                if (!TextUtils.isEmpty(msg) && null != mPrintWriter) {
                    mPrintWriter.println(msg);
                    tv_message.setText(tv_message.getText() + "\n" + getCurrentTime() + "\n" + "客户端:" + msg);
                    et_receive.setText("");
                }
            }
        });
    }

    private void connectSocketServer() {
        Socket socket = null;
        while (socket == null) {
            try {
                // 一个流套接字,连接到服务端
                socket = new Socket("localhost", CODE_SOCKET_CONNECT);
                // 获取到客户端的文本输出流
                mPrintWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
            } catch (IOException e) {
                e.printStackTrace();
                SystemClock.sleep(1000);
            }
        }

        try {
            // 接收服务端发送的消息
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while (!isFinishing()) {
                final String str = reader.readLine();
                if (str != null) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            tv_message.setText(tv_message.getText() + "\n" + getCurrentTime() + "\n" + "服务端:" + str);
                        }
                    });
                }
            }
            mPrintWriter.close();
            reader.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String getCurrentTime() {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
        return df.format(new Date());// new Date()为获取当前系统时间
    }
    
}

  最后我们来看下效果图:
在这里插入图片描述

总结

   点击可查看Socket 聊天程序的代码,以上就是网络基本知识内容的了解,下一篇文章打算写应用层的HTTP协议。

安卓学习笔记42:基于HTTP网络编程 利用URLConnection和HttpClient访问网络资源 阅读详情

相关推荐

安卓学习笔记40:基于套接字网络编程

1. 了解基于套接字网络有两种传输模式; 2. 掌握基于TCP/IP协议的套接字网络编程

howard2005的专栏 2343

Android-第九节网络编程

android网络编程

H_xxxxd的博客 2416

扫地机器人全场景测试实战:从实验室到真实家庭的可靠性验证

本文深入探讨了扫地机器人从实验室到真实家庭的全场景测试方法,揭示了软硬件测试中的关键挑战。通过分析场景化测试的重要性,文章详细介绍了硬件耐久性、软件稳定性和环境适应性三大测试维度,并提供了真实家庭测试的实用方法论。消费者可重点关注清洁率、覆盖率等核心指标,同时了解测试工程师的私房建议,帮助选择更可靠的扫地机器人产品。

hhh00的博客 1075

Android 网络编程基础

Android 网络编程是指在 Android 应用程序中实现网络通信功能。通过网络编程,可以使我们的应用程序与互联网进行交互,从而实现各种有趣、实用的功能。例如,获取最新新闻、下载文件、上传数据等。

特立独行的博客 1501

Wincc7.5SP1 按钮操作记录(二次确认及语音播报)

Wincc 7.5 SP1 按钮操作记录生成(含二次确认及语音播报) 前面一篇文章已经介绍了“语音播报WINCC报警”,本文是之前功能的延伸,记录按钮操作记录并实现播报。 操作记录及语音播报效果 <创建消息文本> 1. 创建消息文本 消息编号100,消息等级“系统无确认”,消息类型“操作员输入消息”,消息文本“循环水泵启动操作”,其他参数默认。 消息编号101,消息等级“系

徐站的春天 1万+

基于OpenCV C++实现工业级形状模板匹配:仿Halcon SBM算法全解析

在计算机视觉和工业自动化领域,模板匹配是一项基础且关键的技术,用于在图像中定位已知目标。其核心原理是通过计算图像区域与预设模板之间的相似度来识别目标位置。传统的基于灰度值的匹配方法对光照变化敏感,鲁棒性不足。而基于边缘梯度方向的形状匹配技术,通过计算轮廓梯度方向的一致性进行相似度度量,从根本上提升了对光照变化的鲁棒性,并支持目标的旋转与缩放,技术价值显著。这项技术广泛应用于工业视觉检测、机器人引导、PCB定位等对精度和稳定性要求极高的场景。本文聚焦于使用开源OpenCV库,从底层仿照Halcon的Shape

weixin_33691817的博客 500

Android网络编程简介

一、Android网络编程简介        我们在平时的开发中,不可避免的会使用到网络编程方面的知识;在我的理解中,App好比是一个壳,它的作用是将用户和服务器联系起来,用户通过操作App向服务器发送或者接收数据,并且以友好的方式反馈给用户,而App要和服务器交互数据,就会设计到网络编程。在Android App的开发中,用到最多的通信方式是基于Http协议,如果涉及到消息推送,可能会使用到W...

xiao_nian的博客 2166

Geant4 案例分析(一): B1

本文是对Geant4 B1的案例分析,其中特定的功能不做介绍,而注重于各个文件的主要功能,以及它们组织的方式。

m0_51809467的博客 1579

Android 网络浅析

所谓协议,就是一种“规范”、或者说“约定”,在通俗点就是“某种规则”。 平时编程用到语言:java、c++、js等也属于协议。 协议一般包含三个要素: * 语法 按照某种规则。如谍战片中的加密电报 * 语义 根据这种规则,需要表达的意思 * 顺序 形成某种顺序,包含上下文信息 如 先干什么,然后在干什么等等............

bugyinyin的博客 979

MuJoCo 机械臂关节空间阻抗控制Impedance实现(附代码)

阻抗控制通过调整关节的刚度和阻尼,让机器人在接触时产生顺应性,减少冲击力,其核心目标是在接触外部载荷时能够自适应调整输出力矩,实现力与位置的协同控制。阻抗控制可以很快的到达设定位置,在此基础上,使用mujoco交互中的施加外力操作,可以看到当外力松开后,机械臂也可以很快的回弹回设定位置。其中self.Kp和self.Kd为固定刚度和阻尼系数,通过修改刚度和阻尼参数,可以变得更柔顺来应对各种场景。注释掉该行后,直接simulate仿真可以看到机械臂控制位置震荡等情况,接下来引入关节空间阻抗控制的代码。

darcsdn 1266

MIKE水动力笔记7_实测数据与模型输出结果的拟合对比

上一博文【MIKE水动力笔记6】主要讲解如何自己制作实测数据的时间序列文件dfs0,而本博文讲解如何进行实测数据与模型输出结果的拟合对比。

晏长街的博客 1万+

【安卓开发】安卓网络编程

既然要刷新,就必然会用到sleep()方法去睡眠等待刷新时间,但是在之前我们曾经出错过,如果我们想要不断刷新修改一个控件(比如文本控件)的内容,我们应该如何做呢?我们可以看到,程序又崩溃了。......

qq_62361050的博客 1409

YOLO26 终极蒸馏指南:从入门到 SOTA (The Ultimate Distillation Guide)

《YOLO26 蒸馏技术指南》深入解析了知识蒸馏在目标检测中的应用,提出五大蒸馏范式:响应蒸馏(学习最终输出)、特征蒸馏(模仿中间特征)、关系蒸馏(捕捉通道关联)、CWD(通道语义对齐)和FGD(前景背景分离)。实验表明,"Response KD + CWD + FGD"组合效果最佳,使YOLO26n在0.5ms推理速度下达到0.956 mAP50,甚至超越教师模型。指南提供模块化代码实现和超参数调优建议,强调蒸馏能平衡模型精度与效率,是轻量化部署的有效方案。

weixin_51988935的博客 717

安卓网络编程——HttpURLConnection

部分案例需要一定的XML和JSON解析知识 https://blog.youkuaiyun.com/nishigesb123/article/details/89190973 Socket、TCP、HTTP等等概念搞不清区别的可以先走下面的链接(好像也是转的,不过贴的几张图很好) https://www.cnblogs.com/merray/p/7918977.html 暂时不涉及Socket部分的内...

旧日灯塔 2553

5G射频设计中N77&N79的PRX为什么需要3个SRS

首先,我们来逐个拆解一下这个神秘的“

weixin_43199439的博客 1323

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Android 网络编程入门指南

在移动应用开发中,网络编程是一个不可或缺的部分。它允许应用与远程服务器进行数据交换,实现数据的上传和下载。本文将为你提供一个关于Android网络编程的入门指南,帮助你理解基本概念和实现步骤。

Unity打怪升级 2327

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Android Studio之网络编程

Android Studio之网络编程 在Android studio中,有时候需要获取HTTP请求,简单点来说就是从服务器中获取相关资源和信息。HTTP协议定义了很多于服务器交互的方法,即HTTP请求的种类中,最基本的有4种,分别是GET、POST、PUT、DELETE。一个URL地址用于描述一个网络上的资源,而HTTP中GET、POST、PUT、DELETE就对应着对这个资源的查、改、增、删4个操作,我们最常见的就是GET和POST了。 GET:通过请求URL得到资源。一般用于获取/查询资源信息。

zhimingdaye的博客 7081

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Android初学八之Android网络编程

1. 掌握Android网络编程基本原理; 2. 掌握常用网络编程框架OKhttp; 3. 能够进行APP网络编程开发。

雨落i的博客 5443

安卓网络编程实例

在实验的安卓界面完成后,下一步就是对接后台了。在实际的应用中,通常需要从后台接口中获取或修改数据库数据,展示在安卓界面中。为了完成这样的功能,学习了安卓的网络编程实例。 使用网络获取数据 使用网络技术也很简单,无非是发送http请求并解析返回数据,在这里使用了android的网络通信库OkHttp,它能更加简化网络请求的步骤。首先在app/build.gradle文件中声明OkHttp依...

weixin_41419564的博客 965

Android网络编程(一)

Android网络编程概述 首先,应该了解的几个问题: 1)Android平台网络相关API接口 a) java.net.*(标准Java接口) java.net.*提供与联网有关的类,包括流、数据包套接字(socket)、Internet协议、常见Http处理等。比如:创建URL,以及URLConnection/HttpURLConnection对象、设置链接参数、链接到服务器、向服务器写数据、从服务器读取数据等通信。这些在Java网络编程中均有涉及。 b) Org.apache接口 对于大部分应用程序而

m0_67403073的博客 1082

Android 网络编程-网络请求

网络请求一定要在子线程执行,否则会报错。数据返回后要显示在界面上要切换回主线程。如果频率很多的使用网络请求,直接使用原生请求即可,不用使用网络框架。如果使用频率很高,可以使用健全的网络框架:OkHttp/Retrofit;OkHttp使用简单,Retrofit 使用复杂一些,但是和很多其他框架可以结合使用,比如Gson,RxJava等。

wenzhi的博客 1715

Android基础——网络编程

网络编程网络编程和数据解析是什么?WebView三级目录 网络编程和数据解析是什么? 网络编程指Android系统使用http协议和服务器交互,并对服务器返回的数据(xml、json)进行解析 WebView Web控件可以让我们在应用程序中嵌入浏览器,展示网页信息 修改activity_main.xml: 三级目录 ...

松仔Log的博客 2566

Android网络编程

1、网络的基本知识: 计算机网络:是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。 计算机网络体系结构: 2、HTTP协议: 3、HTTPS协议: ...

C_leng的博客 1527

安卓下的网络编程

一、概述安卓下的网络编程和javaweb中并没有很大的差别,还就是向服务器发请求,服务器返回响应。安卓下的网络编程指的是客户端向服务器请求数据。网络编程一般的尿性如下: 向服务器发出请求GET方式在地址栏放数据 POST方式通过相应对象设置键值,再发送 服务器根据请求,运算后返回结果 客户端根据服务器返回的状态、结果再次处理 输入输出流读啊读 过程中注意中文乱码问题 安卓中有一点值的注意的是:向服务

yytian9的博客 479
上一篇: Eclipse 和Android Studio 本地工程自动编译APK,可以实现远程依赖
下一篇: Android 网络编程(二) HTTP协议解析
谦行
博客等级 码龄11年 182粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值