前言

  • Socket的使用在 Android网络编程中非常重要
  • 今天我将带大家全面了解 Socket 及 其使用方法 

目录


1.网络基础

1.1 计算机网络分层

计算机网络分为五层:物理层、数据链路层、网络层、运输层、应用层

其中:

  • 网络层:负责根据IP找到目的地址的主机
  • 运输层:通过端口把数据传到目的主机的目的进程,来实现进程与进程之间的通信

1.2 端口号(PORT)

端口号规定为16位,即允许一个IP主机有2的16次方65535个不同的端口。其中:

  • 0~1023:分配给系统的端口号

    我们不可以乱用

  • 1024~49151:登记端口号,主要是让第三方应用使用

    但是必须在IANA(互联网数字分配机构)按照规定手续登记,

  • 49152~65535:短暂端口号,是留给客户进程选择暂时使用,一个进程使用完就可以供其他进程使用。

在Socket使用时,可以用1024~65535的端口号

1.3 C/S结构

  • 定义:即客户端/服务器结构,是软件系统体系结构
  • 作用:充分利用两端硬件环境的优势,将任务合理分配到Client端和Server端来实现,降低了系统的通讯开销。 

    Socket正是使用这种结构建立连接的,一个套接字接客户端,一个套接字接服务器。

如图:
可以看出,Socket的使用可以基于TCP或者UDP协议。

1.4 TCP协议

  • 定义:Transmission Control Protocol,即传输控制协议,是一种传输层通信协议

    基于TCP的应用层协议有FTP、Telnet、SMTP、HTTP、POP3与DNS。

  • 特点:面向连接、面向字节流、全双工通信、可靠

    • 面向连接:指的是要使用TCP传输数据,必须先建立TCP连接,传输完成后释放连接,就像打电话一样必须先拨号建立一条连接,打完后挂机释放连接。

    • 全双工通信:即一旦建立了TCP连接,通信双方可以在任何时候都能发送数据。

    • 可靠的:指的是通过TCP连接传送的数据,无差错,不丢失,不重复,并且按序到达。

    • 面向字节流:流,指的是流入到进程或从进程流出的字符序列。简单来说,虽然有时候要传输的数据流太大,TCP报文长度有限制,不能一次传输完,要把它分为好几个数据块,但是由于可靠性保证,接收方可以按顺序接收数据块然后重新组成分块之前的数据流,所以TCP看起来就像直接互相传输字节流一样,面向字节流。

  • TCP建立连接 
    必须进行三次握手:若A要与B进行连接,则必须

    • 第一次握手:建立连接。客户端发送连接请求报文段,将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认。即A发送信息给B
    • 第二次握手:服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认。即B收到连接信息后向A返回确认信息
    • 第三次握手:客户端收到服务器的(SYN+ACK)报文段,并向服务器发送ACK报文段。即A收到确认信息后再次向B返回确认连接信息

    此时,A告诉自己上层连接建立;B收到连接信息后告诉上层连接建立。

这样就完成TCP三次握手 = 一条TCP连接建立完成 = 可以开始发送数据

  1. 三次握手期间任何一次未收到对面回复都要重发。
  2. 最后一个确认报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态。

为什么TCP建立连接需要三次握手?

答:防止服务器端因为接收了早已失效的连接请求报文从而一直等待客户端请求,从而浪费资源

  • “已失效的连接请求报文段”的产生在这样一种情况下:Client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。
  • 这是一个早已失效的报文段。但Server收到此失效的连接请求报文段后,就误认为是Client再次发出的一个新的连接请求。
  • 于是就向Client发出确认报文段,同意建立连接。
  • 假设不采用“三次握手”:只要Server发出确认,新的连接就建立了。
  • 由于现在Client并没有发出建立连接的请求,因此不会向Server发送数据。
  • 但Server却以为新的运输连接已经建立,并一直等待Client发来数据。>- 这样,Server的资源就白白浪费掉了。

采用“三次握手”的办法可以防止上述现象发生:

  • Client不会向Server的确认发出确认
  • Server由于收不到确认,就知道Client并没有要求建立连接
  • 所以Server不会等待Client发送数据,资源就没有被浪费

  • TCP释放连接 
    TCP释放连接需要四次挥手过程,现在假设A主动释放连接:(数据传输结束后,通信的双方都可释放连接)

    • 第一次挥手:A发送释放信息到B;(发出去之后,A->B发送数据这条路径就断了)
    • 第二次挥手:B收到A的释放信息之后,回复确认释放的信息:我同意你的释放连接请求

    • 第三次挥手:B发送“请求释放连接“信息给A

    • 第四次挥手:A收到B发送的信息后向B发送确认释放信息:我同意你的释放连接请求

      B收到确认信息后就会正式关闭连接; 
      A等待2MSL后依然没有收到回复,则证明B端已正常关闭,于是A关闭连接

为什么TCP释放连接需要四次挥手?

为了保证双方都能通知对方“需要释放连接”,即在释放连接后都无法接收或发送消息给对方

  • 需要明确的是:TCP是全双工模式,这意味着是双向都可以发送、接收的
  • 释放连接的定义是:双方都无法接收或发送消息给对方,是双向的
  • 当主机1发出“释放连接请求”(FIN报文段)时,只是表示主机1已经没有数据要发送 / 数据已经全部发送完毕; 

    但是,这个时候主机1还是可以接受来自主机2的数据。

  • 当主机2返回“确认释放连接”信息(ACK报文段)时,表示它已经知道主机1没有数据发送了 
    但此时主机2还是可以发送数据给主机1
  • 当主机2也发送了FIN报文段时,即告诉主机1我也没有数据要发送了 
    此时,主机1和2已经无法进行通信:主机1无法发送数据给主机2,主机2也无法发送数据给主机1,此时,TCP的连接才算释放
1.5 UDP协议
  • 定义:User Datagram Protocol,即用户数据报协议,是一种传输层通信协议。

    基于UDP的应用层协议有TFTP、SNMP与DNS。

  • 特点:无连接的、不可靠的、面向报文、没有拥塞控制

    • 无连接的:和TCP要建立连接不同,UDP传输数据不需要建立连接,就像写信,在信封写上收信人名称、地址就可以交给邮局发送了,至于能不能送到,就要看邮局的送信能力和送信过程的困难程度了。

    • 不可靠的:因为UDP发出去的数据包发出去就不管了,不管它会不会到达,所以很可能会出现丢包现象,使传输的数据出错。

    • 面向报文:数据报文,就相当于一个数据包,应用层交给UDP多大的数据包,UDP就照样发送,不会像TCP那样拆分。

    • 没有拥塞控制:拥塞,是指到达通信子网中某一部分的分组数量过多,使得该部分网络来不及处理,以致引起这部分乃至整个网络性能下降的现象,严重时甚至会导致网络通信业务陷入停顿,即出现死锁现象,就像交通堵塞一样。TCP建立连接后如果发送的数据因为信道质量的原因不能到达目的地,它会不断重发,有可能导致越来越塞,所以需要一个复杂的原理来控制拥塞。而UDP就没有这个烦恼,发出去就不管了。
  • 应用场景 
    很多的实时应用(如IP电话、实时视频会议、某些多人同时在线游戏等)要求源主机以很定的速率发送数据,并且允许在网络发生拥塞时候丢失一些数据,但是要求不能有太大的延时,UDP就刚好适合这种要求。所以说,只有不适合的技术,没有真正没用的技术。

1.6 HTTP协议

详情请看我写的另外一篇文章你需要了解的HTTP知识都在这里了!


2. Socket定义

  • 即套接字,是一个对 TCP / IP协议进行封装 的编程调用接口(API)

    1. 即通过Socket,我们才能在Andorid平台上通过 TCP/IP协议进行开发
    2. Socket不是一种协议,而是一个编程调用接口(API),属于传输层(主要解决数据如何在网络中传输)
  • 成对出现,一对套接字:

Socket ={(IP地址1:PORT端口号),(IP地址2:PORT端口号)}
  • 1
  • 1

3. 原理

Socket的使用类型主要有两种:

  • 流套接字(streamsocket) :基于 TCP协议,采用 流的方式 提供可靠的字节流服务
  • 数据报套接字(datagramsocket):基于 UDP协议,采用 数据报文 提供数据打包发送的服务

具体原理图如下:

4. Socket 与 Http 对比

  • Socket属于传输层,因为 TCP / IP协议属于传输层,解决的是数据如何在网络中传输的问题
  • HTTP协议 属于 应用层,解决的是如何包装数据

由于二者不属于同一层面,所以本来是没有可比性的。但随着发展,默认的Http里封装了下面几层的使用,所以才会出现Socket & HTTP协议的对比:(主要是工作方式的不同):

  • Http:采用 请求—响应 方式。

    1. 即建立网络连接后,当 客户端 向 服务器 发送请求后,服务器端才能向客户端返回数据。
    2. 可理解为:是客户端有需要才进行通信
  • Socket:采用 服务器主动发送数据 的方式

    1. 即建立网络连接后,服务器可主动发送消息给客户端,而不需要由客户端向服务器发送请求
    2. 可理解为:是服务器端有需要才进行通信

5. 使用步骤

  • Socket可基于TCP或者UDP协议,但TCP更加常用
  • 所以下面的使用步骤 & 实例的Socket将基于TCP协议

// 步骤1:创建客户端 & 服务器的连接// 创建Socket对象 & 指定服务端的IP及端口号 Socket socket = new Socket("192.168.1.32", 1989);  // 判断客户端和服务器是否连接成功  socket.isConnected());// 步骤2:客户端 & 服务器 通信
// 通信包括:客户端 接收服务器的数据 & 发送数据 到 服务器<-- 操作1:接收服务器的数据 -->// 步骤1:创建输入流对象InputStreamInputStream is = socket.getInputStream() // 步骤2:创建输入流读取器对象 并传入输入流对象// 该对象作用:获取服务器返回的数据InputStreamReader isr = new InputStreamReader(is);BufferedReader br = new BufferedReader(isr);// 步骤3:通过输入流读取器对象 接收服务器发送过来的数据br.readLine();<-- 操作2:发送数据 到 服务器 -->                  // 步骤1:从Socket 获得输出流对象OutputStream// 该对象作用:发送数据OutputStream outputStream = socket.getOutputStream(); // 步骤2:写入需要发送的数据到输出流对象中outputStream.write(("Carson_Ho"+"\n").getBytes("utf-8"));// 特别注意:数据的结尾加上换行符才可让服务器端的readline()停止阻塞// 步骤3:发送数据到服务端 outputStream.flush();  // 步骤3:断开客户端 & 服务器 连接os.close();// 断开 客户端发送到服务器 的连接,即关闭输出流对象OutputStreambr.close();// 断开 服务器发送到客户端 的连接,即关闭输入流读取器对象BufferedReadersocket.close();// 最终关闭整个Socket连接
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

6. 具体实例

  • 实例 Demo 代码包括:客户端 & 服务器
  • 本文着重讲解客户端,服务器仅采用最简单的写法进行展示

6.1 客户端 实现

步骤1:加入网络权限

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

步骤2:主布局界面设置

包括创建Socket连接、客户端 & 服务器通信的按钮

    <Buttonandroid:id="@+id/connect"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="connect" /><Buttonandroid:id="@+id/disconnect"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="disconnect" /><TextViewandroid:id="@+id/receive_message"android:layout_width="match_parent"android:layout_height="wrap_content" /><Buttonandroid:id="@+id/Receive"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Receive from message" /><EditTextandroid:id="@+id/edit"android:layout_width="match_parent"android:layout_height="wrap_content" /><Buttonandroid:id="@+id/send"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="send"/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

步骤3:创建Socket连接、客户端 & 服务器通信

具体请看注释

MainActivity.Java

package scut.carson_ho.socket_carson;import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class MainActivity extends AppCompatActivity {/*** 主 变量*/// 主线程Handler// 用于将从服务器获取的消息显示出来private Handler mMainHandler;// Socket变量private Socket socket;// 线程池// 为了方便展示,此处直接采用线程池进行线程管理,而没有一个个开线程private ExecutorService mThreadPool;/*** 接收服务器消息 变量*/// 输入流对象InputStream is;// 输入流读取器对象InputStreamReader isr ;BufferedReader br ;// 接收服务器发送过来的消息String response;/*** 发送消息到服务器 变量*/// 输出流对象OutputStream outputStream;/*** 按钮 变量*/// 连接 断开连接 发送数据到服务器 的按钮变量private Button btnConnect, btnDisconnect, btnSend;// 显示接收服务器消息 按钮private TextView Receive,receive_message;// 输入需要发送的消息 输入框private EditText mEdit;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);/*** 初始化操作*/// 初始化所有按钮btnConnect = (Button) findViewById(R.id.connect);btnDisconnect = (Button) findViewById(R.id.disconnect);btnSend = (Button) findViewById(R.id.send);mEdit = (EditText) findViewById(R.id.edit);receive_message = (TextView) findViewById(R.id.receive_message);Receive = (Button) findViewById(R.id.Receive);// 初始化线程池mThreadPool = Executors.newCachedThreadPool();// 实例化主线程,用于更新接收过来的消息mMainHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case 0:receive_message.setText(response);break;}}};/*** 创建客户端 & 服务器的连接*/btnConnect.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 利用线程池直接开启一个线程 & 执行该线程mThreadPool.execute(new Runnable() {@Overridepublic void run() {try {// 创建Socket对象 & 指定服务端的IP 及 端口号socket = new Socket("192.168.1.172", 8989);// 判断客户端和服务器是否连接成功System.out.println(socket.isConnected());} catch (IOException e) {e.printStackTrace();}}});}});/*** 接收 服务器消息*/Receive.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 利用线程池直接开启一个线程 & 执行该线程mThreadPool.execute(new Runnable() {@Overridepublic void run() {try {// 步骤1:创建输入流对象InputStreamis = socket.getInputStream();// 步骤2:创建输入流读取器对象 并传入输入流对象// 该对象作用:获取服务器返回的数据isr = new InputStreamReader(is);br = new BufferedReader(isr);// 步骤3:通过输入流读取器对象 接收服务器发送过来的数据response = br.readLine();// 步骤4:通知主线程,将接收的消息显示到界面Message msg = Message.obtain();msg.what = 0;mMainHandler.sendMessage(msg);} catch (IOException e) {e.printStackTrace();}}});}});/*** 发送消息 给 服务器*/btnSend.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 利用线程池直接开启一个线程 & 执行该线程mThreadPool.execute(new Runnable() {@Overridepublic void run() {try {// 步骤1:从Socket 获得输出流对象OutputStream// 该对象作用:发送数据outputStream = socket.getOutputStream();// 步骤2:写入需要发送的数据到输出流对象中outputStream.write((mEdit.getText().toString()+"\n").getBytes("utf-8"));// 特别注意:数据的结尾加上换行符才可让服务器端的readline()停止阻塞// 步骤3:发送数据到服务端outputStream.flush();} catch (IOException e) {e.printStackTrace();}}});}});/*** 断开客户端 & 服务器的连接*/btnDisconnect.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {try {// 断开 客户端发送到服务器 的连接,即关闭输出流对象OutputStreamoutputStream.close();// 断开 服务器发送到客户端 的连接,即关闭输入流读取器对象BufferedReaderbr.close();// 最终关闭整个Socket连接socket.close();// 判断客户端和服务器是否已经断开连接System.out.println(socket.isConnected());} catch (IOException e) {e.printStackTrace();}}});}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 3

socket协议解读相关推荐

  1. 自行控制loadrunner的socket协议性能测试 (转)

    一前言 二任务的提出 三实现方案讨论 四技术要点讲解 如何开始录制一个最简单的收发数据包脚本 写日志文件 一行一行读数据包文件 字符串转换为十六进制数据包 发送自己定义的数据包 接收数据包到自定义缓冲 ...

  2. 网络协议之:socket协议详解之Datagram Socket

    文章目录 简介 什么是Datagram Socket 使用socat来创建UDP服务 使用ss命令来监控Datagram Sockets 使用nc建立和UDP Socket的连接 总结 简介 上一篇文 ...

  3. 3gpp协议_3GPP都在干什么(16)?:3GPP中网络切片原理及协议解读

    本文归属于<3GPP在干什么>系列.全文71页PPT.(此系列是春天工作室一大IP(品牌),主要是协议解读.标准化进展梳理,新技术跟踪等). 今年我们会投入较多的时间和精力,重点研究和跟踪 ...

  4. CANopen协议解读

    CANopen协议解读 一.协议标准 二.CANopen报文说明 三.CANopen协议内容 1. ID的理解 2. NMT (1) 节点状态 (2) 节点状态控制 (3) 节点心跳报文 一.协议标准 ...

  5. 手游-放开那三国socket协议分析

    手游-放开那三国socket协议分析 图文:a4727603 楼主本就是一个偷懒的人,玩游戏最什么的最讨厌了还要一遍遍的刷副本,于是就有了这个破解的过程 刷副本太累,想写个脱机挂自动打副本,背景交代完 ...

  6. Socket协议编程实践

    Socket协议编程实践[分布式计算] Socket之UDP和TCP 文章目录 Socket协议编程实践[分布式计算] 前言 一.什么是Socket 二.为什么要使用Socket 三.套接字 四.实验 ...

  7. socket协议基础知识

    Socket协议的形象描述 socket的英文原义是"孔"或"插座".在这里作为4BDS UNIX的进程通信机制,取后一种意思.socket非常类似于电话插座. ...

  8. cs架构接口协议(常用socket协议)与bs架构接口协议(常用http协议)

    Socket原理以及与websocket.http的区别: B/S的系统通常使用http协议进行客户端和服务器商的信息交换,C/S的系统通常使用socket协议进行信息交换 参考:https://bl ...

  9. socket协议介绍

    2019独角兽企业重金招聘Python工程师标准>>> 本文主要讲述了Socket协议脚本的基础知识和编写方法,让大家能够在短时间内快速掌握简单的Socket协议脚本的编写方法. 1 ...

最新文章

  1. 微信小程序开发分销制度济南_花店微信小程序开发教程
  2. Requirejs定义模块
  3. 用递归方法计算斐波那契数列(Recursion Fibonacci Sequence Python)
  4. java坐标移动题目case_坐标移动
  5. go编译成c语言,Go语言是怎么完成编译的
  6. Qt工作笔记-QMap的进一步操作
  7. 做基础产品的体会【转载】
  8. python获取表格中的所有数据_【经验分享】用Python读取电子表格中的数据
  9. python变现实现新浪微博登陆
  10. Android开发中自定义表情并发送出去之经典的发送表情
  11. R语言forestplot 根据分组设置不同颜色
  12. jdon的设计模式详细解读
  13. 【Ubuntu系列】Ubuntu20.04系统下3060显卡驱动安装记录
  14. 土微数字隔离器和接口类芯片可完美替代进口品牌TI和ADI
  15. DAY2作业-假如生活欺骗了你!
  16. 风雨沧桑50年:中国卫星通信的发展历程(上)
  17. 北理工乐学C语言 47. 【大学】北理工的恶龙
  18. (单片机原理与应用)智能温度监测系统(设计)
  19. 程序员延寿指南、如何活得更长
  20. 有个程序员女朋友是什么体验?

热门文章

  1. linux apt-get找不到命令,ubuntu 下 apt /apt-get command not found 命令找不到
  2. mysql数据库恢复 覆盖吗_MySQL数据库恢复
  3. 汤姆大叔的博客:深入理解JavaScript系列
  4. 国内各银行信用卡系统概况表
  5. 有趣的java 开发_开发人员历史中的五个有趣时刻
  6. android 4.2 开机动画,android开机动画制作与播放原理简介 (适用android4-4.2,其他版本未试验)...
  7. C# SolidWorks二次开发---工程图中心标记(Center Marks)
  8. 从浏览器输入url到页面加载(六)前端必须了解的路由器和光纤小知识
  9. KITTI数据集的点云格式转PCD格式
  10. 修改Linux系统时间和时区